* lib/{soap,wsdl,xsd}, test/{soap,wsdl,xsd}: imported soap4r/1.5.4.
== SOAP client and server == === for both client side and server side === * improved document/literal service support. style(rpc,document)/use(encoding, literal) combination are all supported. for the detail about combination, see test/soap/test_style.rb. * let WSDLEncodedRegistry#soap2obj map SOAP/OM to Ruby according to WSDL as well as obj2soap. closes #70. * let SOAP::Mapping::Object handle XML attribute for doc/lit service. you can set/get XML attribute via accessor methods which as a name 'xmlattr_' prefixed (<foo name="bar"/> -> Foo#xmlattr_name). === client side === * WSDLDriver capitalized name operation bug fixed. from 1.5.3-ruby1.8.2, operation which has capitalized name (such as KeywordSearchRequest in AWS) is defined as a method having uncapitalized name. (converted with GenSupport.safemethodname to handle operation name 'foo-bar'). it introduced serious incompatibility; in the past, it was defined as a capitalized. define capitalized method as well under that circumstance. * added new factory interface 'WSDLDriverFactory#create_rpc_driver' to create RPC::Driver, not WSDLDriver (RPC::Driver and WSDLDriver are merged). 'WSDLDriverFactory#create_driver' still creates WSDLDriver for compatibility but it warns that the method is deprecated. please use create_rpc_driver instead of create_driver. * allow to use an URI object as an endpoint_url even with net/http, not http-access2. === server side === * added mod_ruby support to SOAP::CGIStub. rename a CGI script server.cgi to server.rb and let mod_ruby's RubyHandler handles the script. CGIStub detects if it's running under mod_ruby environment or not. * added fcgi support to SOAP::CGIStub. see the sample at sample/soap/calc/server.fcgi. (almost same as server.cgi but has fcgi handler at the bottom.) * allow to return a SOAPFault object to respond customized SOAP fault. * added the interface 'generate_explicit_type' for server side (CGIStub, HTTPServer). call 'self.generate_explicit_type = true' if you want to return simplified XML even if it's rpc/encoded service. == WSDL == === WSDL definition === * improved XML Schema support such as extension, restriction, simpleType, complexType + simpleContent, ref, length, import, include. * reduced "unknown element/attribute" warnings (warn only 1 time for each QName). * importing XSD file at schemaLocation with xsd:import. === code generation from WSDL === * generator crashed when there's '-' in defined element/attribute name. * added ApacheMap WSDL definition. * sample/{soap,wsdl}: removed. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8500 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
7aea792d3b
commit
eb3f829be9
79
ChangeLog
79
ChangeLog
@ -1,3 +1,82 @@
|
|||||||
|
Sun May 22 21:54:06 2005 NAKAMURA, Hiroshi <nakahiro@sarion.co.jp>
|
||||||
|
|
||||||
|
* lib/{soap,wsdl,xsd}, test/{soap,wsdl,xsd}: imported soap4r/1.5.4.
|
||||||
|
|
||||||
|
== SOAP client and server ==
|
||||||
|
|
||||||
|
=== for both client side and server side ===
|
||||||
|
|
||||||
|
* improved document/literal service support.
|
||||||
|
style(rpc,document)/use(encoding, literal) combination are all
|
||||||
|
supported. for the detail about combination, see
|
||||||
|
test/soap/test_style.rb.
|
||||||
|
|
||||||
|
* let WSDLEncodedRegistry#soap2obj map SOAP/OM to Ruby according to
|
||||||
|
WSDL as well as obj2soap. closes #70.
|
||||||
|
|
||||||
|
* let SOAP::Mapping::Object handle XML attribute for doc/lit service.
|
||||||
|
you can set/get XML attribute via accessor methods which as a name
|
||||||
|
'xmlattr_' prefixed (<foo name="bar"/> -> Foo#xmlattr_name).
|
||||||
|
|
||||||
|
=== client side ===
|
||||||
|
|
||||||
|
* WSDLDriver capitalized name operation bug fixed. from
|
||||||
|
1.5.3-ruby1.8.2, operation which has capitalized name (such as
|
||||||
|
KeywordSearchRequest in AWS) is defined as a method having
|
||||||
|
uncapitalized name. (converted with GenSupport.safemethodname
|
||||||
|
to handle operation name 'foo-bar'). it introduced serious
|
||||||
|
incompatibility; in the past, it was defined as a capitalized.
|
||||||
|
define capitalized method as well under that circumstance.
|
||||||
|
|
||||||
|
* added new factory interface 'WSDLDriverFactory#create_rpc_driver'
|
||||||
|
to create RPC::Driver, not WSDLDriver (RPC::Driver and WSDLDriver
|
||||||
|
are merged). 'WSDLDriverFactory#create_driver' still creates
|
||||||
|
WSDLDriver for compatibility but it warns that the method is
|
||||||
|
deprecated. please use create_rpc_driver instead of create_driver.
|
||||||
|
|
||||||
|
* allow to use an URI object as an endpoint_url even with net/http,
|
||||||
|
not http-access2.
|
||||||
|
|
||||||
|
=== server side ===
|
||||||
|
|
||||||
|
* added mod_ruby support to SOAP::CGIStub. rename a CGI script
|
||||||
|
server.cgi to server.rb and let mod_ruby's RubyHandler handles the
|
||||||
|
script. CGIStub detects if it's running under mod_ruby environment
|
||||||
|
or not.
|
||||||
|
|
||||||
|
* added fcgi support to SOAP::CGIStub. see the sample at
|
||||||
|
sample/soap/calc/server.fcgi. (almost same as server.cgi but has
|
||||||
|
fcgi handler at the bottom.)
|
||||||
|
|
||||||
|
* allow to return a SOAPFault object to respond customized SOAP fault.
|
||||||
|
|
||||||
|
* added the interface 'generate_explicit_type' for server side
|
||||||
|
(CGIStub, HTTPServer). call 'self.generate_explicit_type = true'
|
||||||
|
if you want to return simplified XML even if it's rpc/encoded
|
||||||
|
service.
|
||||||
|
|
||||||
|
== WSDL ==
|
||||||
|
|
||||||
|
=== WSDL definition ===
|
||||||
|
|
||||||
|
* improved XML Schema support such as extension, restriction,
|
||||||
|
simpleType, complexType + simpleContent, ref, length, import,
|
||||||
|
include.
|
||||||
|
|
||||||
|
* reduced "unknown element/attribute" warnings (warn only 1 time for
|
||||||
|
each QName).
|
||||||
|
|
||||||
|
* importing XSD file at schemaLocation with xsd:import.
|
||||||
|
|
||||||
|
=== code generation from WSDL ===
|
||||||
|
|
||||||
|
* generator crashed when there's '-' in defined element/attribute
|
||||||
|
name.
|
||||||
|
|
||||||
|
* added ApacheMap WSDL definition.
|
||||||
|
|
||||||
|
* sample/{soap,wsdl}: removed.
|
||||||
|
|
||||||
Sun May 22 19:11:35 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
|
Sun May 22 19:11:35 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
|
||||||
|
|
||||||
* ext/openssl/lib/openssl/ssl.rb (OpenSSL::SSL::SSLServer#intialize):
|
* ext/openssl/lib/openssl/ssl.rb (OpenSSL::SSL::SSLServer#intialize):
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# soap/baseData.rb: SOAP4R - Base type library
|
# soap/baseData.rb: SOAP4R - Base type library
|
||||||
# Copyright (C) 2000, 2001, 2003, 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 2000, 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;
|
||||||
@ -56,6 +56,14 @@ module SOAPType
|
|||||||
@extraattr = {}
|
@extraattr = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def inspect
|
||||||
|
if self.is_a?(XSD::NSDBase)
|
||||||
|
sprintf("#<%s:0x%x %s %s>", self.class.name, __id__, self.elename, self.type)
|
||||||
|
else
|
||||||
|
sprintf("#<%s:0x%x %s>", self.class.name, __id__, self.elename)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def rootnode
|
def rootnode
|
||||||
node = self
|
node = self
|
||||||
while node = node.parent
|
while node = node.parent
|
||||||
@ -399,7 +407,7 @@ public
|
|||||||
def to_s()
|
def to_s()
|
||||||
str = ''
|
str = ''
|
||||||
self.each do |key, data|
|
self.each do |key, data|
|
||||||
str << "#{ key }: #{ data }\n"
|
str << "#{key}: #{data}\n"
|
||||||
end
|
end
|
||||||
str
|
str
|
||||||
end
|
end
|
||||||
@ -442,6 +450,25 @@ public
|
|||||||
@array
|
@array
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_obj
|
||||||
|
hash = {}
|
||||||
|
proptype = {}
|
||||||
|
each do |k, v|
|
||||||
|
value = v.respond_to?(:to_obj) ? v.to_obj : v.to_s
|
||||||
|
case proptype[k]
|
||||||
|
when :single
|
||||||
|
hash[k] = [hash[k], value]
|
||||||
|
proptype[k] = :multi
|
||||||
|
when :multi
|
||||||
|
hash[k] << value
|
||||||
|
else
|
||||||
|
hash[k] = value
|
||||||
|
proptype[k] = :single
|
||||||
|
end
|
||||||
|
end
|
||||||
|
hash
|
||||||
|
end
|
||||||
|
|
||||||
def each
|
def each
|
||||||
for i in 0..(@array.length - 1)
|
for i in 0..(@array.length - 1)
|
||||||
yield(@array[i], @data[i])
|
yield(@array[i], @data[i])
|
||||||
@ -509,6 +536,10 @@ class SOAPElement
|
|||||||
@text = text
|
@text = text
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def inspect
|
||||||
|
sprintf("#<%s:0x%x %s>", self.class.name, __id__, self.elename)
|
||||||
|
end
|
||||||
|
|
||||||
# Text interface.
|
# Text interface.
|
||||||
attr_accessor :text
|
attr_accessor :text
|
||||||
alias data text
|
alias data text
|
||||||
@ -548,8 +579,19 @@ class SOAPElement
|
|||||||
@text
|
@text
|
||||||
else
|
else
|
||||||
hash = {}
|
hash = {}
|
||||||
|
proptype = {}
|
||||||
each do |k, v|
|
each do |k, v|
|
||||||
hash[k] = v.is_a?(SOAPElement) ? v.to_obj : v.to_s
|
value = v.respond_to?(:to_obj) ? v.to_obj : v.to_s
|
||||||
|
case proptype[k]
|
||||||
|
when :single
|
||||||
|
hash[k] = [hash[k], value]
|
||||||
|
proptype[k] = :multi
|
||||||
|
when :multi
|
||||||
|
hash[k] << value
|
||||||
|
else
|
||||||
|
hash[k] = value
|
||||||
|
proptype[k] = :single
|
||||||
|
end
|
||||||
end
|
end
|
||||||
hash
|
hash
|
||||||
end
|
end
|
||||||
@ -566,20 +608,41 @@ class SOAPElement
|
|||||||
o
|
o
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.from_obj(hash_or_string)
|
def self.from_obj(obj, namespace = nil)
|
||||||
o = SOAPElement.new(nil)
|
o = SOAPElement.new(nil)
|
||||||
if hash_or_string.is_a?(Hash)
|
case obj
|
||||||
hash_or_string.each do |k, v|
|
when nil
|
||||||
child = self.from_obj(v)
|
o.text = nil
|
||||||
child.elename = k.is_a?(XSD::QName) ? k : XSD::QName.new(nil, k.to_s)
|
when Hash
|
||||||
|
obj.each do |elename, value|
|
||||||
|
if value.is_a?(Array)
|
||||||
|
value.each do |subvalue|
|
||||||
|
child = from_obj(subvalue, namespace)
|
||||||
|
child.elename = to_elename(elename, namespace)
|
||||||
o.add(child)
|
o.add(child)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
o.text = hash_or_string
|
child = from_obj(value, namespace)
|
||||||
|
child.elename = to_elename(elename, namespace)
|
||||||
|
o.add(child)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
o.text = obj.to_s
|
||||||
end
|
end
|
||||||
o
|
o
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.to_elename(obj, namespace = nil)
|
||||||
|
if obj.is_a?(XSD::QName)
|
||||||
|
obj
|
||||||
|
elsif /\A(.+):([^:]+)\z/ =~ obj.to_s
|
||||||
|
XSD::QName.new($1, $2)
|
||||||
|
else
|
||||||
|
XSD::QName.new(namespace, obj.to_s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def add_member(name, value)
|
def add_member(name, value)
|
||||||
@ -590,18 +653,32 @@ private
|
|||||||
value
|
value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if RUBY_VERSION > "1.7.0"
|
||||||
def add_accessor(name)
|
def add_accessor(name)
|
||||||
methodname = name
|
methodname = name
|
||||||
if self.respond_to?(methodname)
|
if self.respond_to?(methodname)
|
||||||
methodname = safe_accessor_name(methodname)
|
methodname = safe_accessor_name(methodname)
|
||||||
end
|
end
|
||||||
sclass = class << self; self; end
|
Mapping.define_singleton_method(self, methodname) do
|
||||||
sclass.__send__(:define_method, methodname, proc {
|
|
||||||
@data[@array.index(name)]
|
@data[@array.index(name)]
|
||||||
})
|
end
|
||||||
sclass.__send__(:define_method, methodname + '=', proc { |value|
|
Mapping.define_singleton_method(self, methodname + '=') do |value|
|
||||||
@data[@array.index(name)] = value
|
@data[@array.index(name)] = value
|
||||||
})
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
def add_accessor(name)
|
||||||
|
methodname = safe_accessor_name(name)
|
||||||
|
instance_eval <<-EOS
|
||||||
|
def #{methodname}
|
||||||
|
@data[@array.index(#{name.dump})]
|
||||||
|
end
|
||||||
|
|
||||||
|
def #{methodname}=(value)
|
||||||
|
@data[@array.index(#{name.dump})] = value
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def safe_accessor_name(name)
|
def safe_accessor_name(name)
|
||||||
@ -624,7 +701,7 @@ public
|
|||||||
|
|
||||||
def initialize(type = nil, rank = 1, arytype = nil)
|
def initialize(type = nil, rank = 1, arytype = nil)
|
||||||
super()
|
super()
|
||||||
@type = type || XSD::QName.new
|
@type = type || ValueArrayName
|
||||||
@rank = rank
|
@rank = rank
|
||||||
@data = Array.new
|
@data = Array.new
|
||||||
@sparse = false
|
@sparse = false
|
||||||
@ -646,7 +723,7 @@ public
|
|||||||
|
|
||||||
def [](*idxary)
|
def [](*idxary)
|
||||||
if idxary.size != @rank
|
if idxary.size != @rank
|
||||||
raise ArgumentError.new("Given #{ idxary.size } params does not match rank: #{ @rank }")
|
raise ArgumentError.new("given #{idxary.size} params does not match rank: #{@rank}")
|
||||||
end
|
end
|
||||||
|
|
||||||
retrieve(idxary)
|
retrieve(idxary)
|
||||||
@ -656,7 +733,8 @@ public
|
|||||||
value = idxary.slice!(-1)
|
value = idxary.slice!(-1)
|
||||||
|
|
||||||
if idxary.size != @rank
|
if idxary.size != @rank
|
||||||
raise ArgumentError.new("Given #{ idxary.size } params(#{ idxary }) does not match rank: #{ @rank }")
|
raise ArgumentError.new("given #{idxary.size} params(#{idxary})" +
|
||||||
|
" does not match rank: #{@rank}")
|
||||||
end
|
end
|
||||||
|
|
||||||
for i in 0..(idxary.size - 1)
|
for i in 0..(idxary.size - 1)
|
||||||
@ -836,7 +914,7 @@ public
|
|||||||
private
|
private
|
||||||
|
|
||||||
def self.create_arytype(typename, rank)
|
def self.create_arytype(typename, rank)
|
||||||
"#{ typename }[" << ',' * (rank - 1) << ']'
|
"#{typename}[" << ',' * (rank - 1) << ']'
|
||||||
end
|
end
|
||||||
|
|
||||||
TypeParseRegexp = Regexp.new('^(.+)\[([\d,]*)\]$')
|
TypeParseRegexp = Regexp.new('^(.+)\[([\d,]*)\]$')
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# SOAP4R - SOAP elements library
|
# SOAP4R - SOAP elements library
|
||||||
# Copyright (C) 2000, 2001, 2003, 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 2000, 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;
|
||||||
@ -99,7 +99,15 @@ class SOAPBody < SOAPStruct
|
|||||||
super(nil)
|
super(nil)
|
||||||
@elename = EleBodyName
|
@elename = EleBodyName
|
||||||
@encodingstyle = nil
|
@encodingstyle = nil
|
||||||
add(data.elename.name, data) if data
|
if data
|
||||||
|
if data.respond_to?(:elename)
|
||||||
|
add(data.elename.name, data)
|
||||||
|
else
|
||||||
|
data.to_a.each do |datum|
|
||||||
|
add(datum.elename.name, datum)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@is_fault = is_fault
|
@is_fault = is_fault
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -129,7 +137,7 @@ class SOAPBody < SOAPStruct
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
raise SOAPParser::FormatDecodeError.new('No root element.')
|
raise Parser::FormatDecodeError.new('no root element')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -231,8 +239,7 @@ class SOAPEnvelope < XSD::NSDBase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def encode(generator, ns, attrs = {})
|
def encode(generator, ns, attrs = {})
|
||||||
SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace,
|
SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace, SOAPNamespaceTag)
|
||||||
SOAPNamespaceTag)
|
|
||||||
name = ns.name(@elename)
|
name = ns.name(@elename)
|
||||||
generator.encode_tag(name, attrs)
|
generator.encode_tag(name, attrs)
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# SOAP4R - ASP.NET EncodingStyle handler library
|
# SOAP4R - ASP.NET EncodingStyle handler 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;
|
||||||
@ -30,7 +30,7 @@ class ASPDotNetHandler < Handler
|
|||||||
def encode_data(generator, ns, qualified, data, parent)
|
def encode_data(generator, ns, qualified, data, parent)
|
||||||
attrs = {}
|
attrs = {}
|
||||||
name = if qualified and data.elename.namespace
|
name = if qualified and data.elename.namespace
|
||||||
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace)
|
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace, '')
|
||||||
ns.name(data.elename)
|
ns.name(data.elename)
|
||||||
else
|
else
|
||||||
data.elename.name
|
data.elename.name
|
||||||
@ -61,8 +61,8 @@ class ASPDotNetHandler < Handler
|
|||||||
yield(child, true)
|
yield(child, true)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise EncodingStyleError.new("Unknown object:#{ data } in this encodingSt
|
raise EncodingStyleError.new(
|
||||||
yle.")
|
"unknown object:#{data} in this encodingStyle")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -119,7 +119,6 @@ yle.")
|
|||||||
end
|
end
|
||||||
|
|
||||||
def decode_tag(ns, elename, attrs, parent)
|
def decode_tag(ns, elename, attrs, parent)
|
||||||
# ToDo: check if @textbuf is empty...
|
|
||||||
@textbuf = ''
|
@textbuf = ''
|
||||||
o = SOAPUnknown.new(self, elename)
|
o = SOAPUnknown.new(self, elename)
|
||||||
o.parent = parent
|
o.parent = parent
|
||||||
@ -190,11 +189,11 @@ yle.")
|
|||||||
end
|
end
|
||||||
|
|
||||||
when SOAPBasetype
|
when SOAPBasetype
|
||||||
raise EncodingStyleError.new("SOAP base type must not have a child.")
|
raise EncodingStyleError.new("SOAP base type must not have a child")
|
||||||
|
|
||||||
else
|
else
|
||||||
# SOAPUnknown does not have parent.
|
# SOAPUnknown does not have parent.
|
||||||
# raise EncodingStyleError.new("Illegal parent: #{ parent }.")
|
# raise EncodingStyleError.new("illegal parent: #{parent}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# SOAP4R - XML Literal EncodingStyle handler library
|
# SOAP4R - XML Literal EncodingStyle handler library
|
||||||
# Copyright (C) 2001, 2003, 2004 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;
|
||||||
@ -29,11 +29,22 @@ class LiteralHandler < Handler
|
|||||||
def encode_data(generator, ns, qualified, data, parent)
|
def encode_data(generator, ns, qualified, data, parent)
|
||||||
attrs = {}
|
attrs = {}
|
||||||
name = if qualified and data.elename.namespace
|
name = if qualified and data.elename.namespace
|
||||||
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace)
|
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace, '')
|
||||||
ns.name(data.elename)
|
ns.name(data.elename)
|
||||||
else
|
else
|
||||||
data.elename.name
|
data.elename.name
|
||||||
end
|
end
|
||||||
|
data.extraattr.each do |k, v|
|
||||||
|
if k.is_a?(XSD::QName)
|
||||||
|
if k.namespace
|
||||||
|
SOAPGenerator.assign_ns(attrs, ns, k.namespace)
|
||||||
|
k = ns.name(k)
|
||||||
|
else
|
||||||
|
k = k.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
attrs[k] = v
|
||||||
|
end
|
||||||
|
|
||||||
case data
|
case data
|
||||||
when SOAPRawString
|
when SOAPRawString
|
||||||
@ -62,13 +73,14 @@ class LiteralHandler < Handler
|
|||||||
yield(child, true)
|
yield(child, true)
|
||||||
end
|
end
|
||||||
when SOAPElement
|
when SOAPElement
|
||||||
generator.encode_tag(name, attrs.update(data.extraattr))
|
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)
|
yield(value, qualified)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise EncodingStyleError.new("Unknown object:#{ data } in this encodingStyle.")
|
raise EncodingStyleError.new(
|
||||||
|
"unknown object:#{data} in this encodingStyle")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -78,7 +90,8 @@ class LiteralHandler < Handler
|
|||||||
else
|
else
|
||||||
data.elename.name
|
data.elename.name
|
||||||
end
|
end
|
||||||
cr = data.is_a?(SOAPElement) && !data.text
|
cr = (data.is_a?(SOAPCompoundtype) or
|
||||||
|
(data.is_a?(SOAPElement) and !data.text))
|
||||||
generator.encode_tag_end(name, cr)
|
generator.encode_tag_end(name, cr)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -128,7 +141,6 @@ class LiteralHandler < Handler
|
|||||||
end
|
end
|
||||||
|
|
||||||
def decode_tag(ns, elename, attrs, parent)
|
def decode_tag(ns, elename, attrs, parent)
|
||||||
# ToDo: check if @textbuf is empty...
|
|
||||||
@textbuf = ''
|
@textbuf = ''
|
||||||
o = SOAPUnknown.new(self, elename, decode_attrs(ns, attrs))
|
o = SOAPUnknown.new(self, elename, decode_attrs(ns, attrs))
|
||||||
o.parent = parent
|
o.parent = parent
|
||||||
@ -172,21 +184,19 @@ class LiteralHandler < Handler
|
|||||||
end
|
end
|
||||||
|
|
||||||
def decode_parent(parent, node)
|
def decode_parent(parent, node)
|
||||||
|
return unless parent.node
|
||||||
case parent.node
|
case parent.node
|
||||||
when SOAPUnknown
|
when SOAPUnknown
|
||||||
newparent = parent.node.as_element
|
newparent = parent.node.as_element
|
||||||
node.parent = newparent
|
node.parent = newparent
|
||||||
parent.replace_node(newparent)
|
parent.replace_node(newparent)
|
||||||
decode_parent(parent, node)
|
decode_parent(parent, node)
|
||||||
|
|
||||||
when SOAPElement
|
when SOAPElement
|
||||||
parent.node.add(node)
|
parent.node.add(node)
|
||||||
node.parent = parent.node
|
node.parent = parent.node
|
||||||
|
|
||||||
when SOAPStruct
|
when SOAPStruct
|
||||||
parent.node.add(node.elename.name, node)
|
parent.node.add(node.elename.name, node)
|
||||||
node.parent = parent.node
|
node.parent = parent.node
|
||||||
|
|
||||||
when SOAPArray
|
when SOAPArray
|
||||||
if node.position
|
if node.position
|
||||||
parent.node[*(decode_arypos(node.position))] = node
|
parent.node[*(decode_arypos(node.position))] = node
|
||||||
@ -195,13 +205,8 @@ class LiteralHandler < Handler
|
|||||||
parent.node.add(node)
|
parent.node.add(node)
|
||||||
end
|
end
|
||||||
node.parent = parent.node
|
node.parent = parent.node
|
||||||
|
|
||||||
when SOAPBasetype
|
|
||||||
raise EncodingStyleError.new("SOAP base type must not have a child.")
|
|
||||||
|
|
||||||
else
|
else
|
||||||
# SOAPUnknown does not have parent.
|
raise EncodingStyleError.new("illegal parent: #{parent.node}")
|
||||||
raise EncodingStyleError.new("Illegal parent: #{ parent }.")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# SOAP4R - SOAP EncodingStyle handler library
|
# SOAP4R - SOAP EncodingStyle handler 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;
|
||||||
@ -33,7 +33,7 @@ class SOAPHandler < Handler
|
|||||||
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 = nil
|
name = nil
|
||||||
@ -75,7 +75,7 @@ class SOAPHandler < Handler
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise EncodingStyleError.new(
|
raise EncodingStyleError.new(
|
||||||
"Unknown object:#{ data } in this encodingStyle.")
|
"unknown object:#{data} in this encodingStyle")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -156,7 +156,6 @@ class SOAPHandler < Handler
|
|||||||
end
|
end
|
||||||
|
|
||||||
def decode_tag(ns, elename, attrs, parent)
|
def decode_tag(ns, elename, attrs, parent)
|
||||||
# ToDo: check if @textbuf is empty...
|
|
||||||
@textbuf = ''
|
@textbuf = ''
|
||||||
is_nil, type, arytype, root, offset, position, href, id, extraattr =
|
is_nil, type, arytype, root, offset, position, href, id, extraattr =
|
||||||
decode_attrs(ns, attrs)
|
decode_attrs(ns, attrs)
|
||||||
@ -227,6 +226,7 @@ class SOAPHandler < Handler
|
|||||||
end
|
end
|
||||||
|
|
||||||
def decode_parent(parent, node)
|
def decode_parent(parent, node)
|
||||||
|
return unless parent.node
|
||||||
case parent.node
|
case parent.node
|
||||||
when SOAPUnknown
|
when SOAPUnknown
|
||||||
newparent = parent.node.as_struct
|
newparent = parent.node.as_struct
|
||||||
@ -247,10 +247,8 @@ class SOAPHandler < Handler
|
|||||||
parent.node.add(node)
|
parent.node.add(node)
|
||||||
end
|
end
|
||||||
node.parent = parent.node
|
node.parent = parent.node
|
||||||
when SOAPBasetype
|
|
||||||
raise EncodingStyleError.new("SOAP base type must not have a child.")
|
|
||||||
else
|
else
|
||||||
raise EncodingStyleError.new("Illegal parent: #{ parent.node }.")
|
raise EncodingStyleError.new("illegal parent: #{parent.node}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -266,7 +264,7 @@ private
|
|||||||
|
|
||||||
def create_arytype(ns, data)
|
def create_arytype(ns, data)
|
||||||
XSD::QName.new(data.arytype.namespace,
|
XSD::QName.new(data.arytype.namespace,
|
||||||
content_typename(data.arytype.name) + "[#{ data.size.join(',') }]")
|
content_typename(data.arytype.name) + "[#{data.size.join(',')}]")
|
||||||
end
|
end
|
||||||
|
|
||||||
def encode_attrs(generator, ns, data, parent)
|
def encode_attrs(generator, ns, data, parent)
|
||||||
@ -383,7 +381,7 @@ private
|
|||||||
|
|
||||||
def decode_definedtype(elename, typename, typedef, arytypestr)
|
def decode_definedtype(elename, typename, typedef, arytypestr)
|
||||||
unless typedef
|
unless typedef
|
||||||
raise EncodingStyleError.new("Unknown type '#{ typename }'.")
|
raise EncodingStyleError.new("unknown type '#{typename}'")
|
||||||
end
|
end
|
||||||
if typedef.is_a?(::WSDL::XMLSchema::SimpleType)
|
if typedef.is_a?(::WSDL::XMLSchema::SimpleType)
|
||||||
decode_defined_simpletype(elename, typename, typedef, arytypestr)
|
decode_defined_simpletype(elename, typename, typedef, arytypestr)
|
||||||
@ -421,6 +419,10 @@ private
|
|||||||
end
|
end
|
||||||
o.definedtype = typedef
|
o.definedtype = typedef
|
||||||
return o
|
return o
|
||||||
|
when :TYPE_EMPTY
|
||||||
|
o = SOAPNil.decode(elename)
|
||||||
|
o.definedtype = typedef
|
||||||
|
return o
|
||||||
else
|
else
|
||||||
raise RuntimeError.new(
|
raise RuntimeError.new(
|
||||||
"Unknown kind of complexType: #{typedef.compoundtype}")
|
"Unknown kind of complexType: #{typedef.compoundtype}")
|
||||||
@ -509,7 +511,7 @@ private
|
|||||||
case qname.name
|
case qname.name
|
||||||
when XSD::NilLiteral
|
when XSD::NilLiteral
|
||||||
is_nil = NilLiteralMap[value] or
|
is_nil = NilLiteralMap[value] or
|
||||||
raise EncodingStyleError.new("Cannot accept attribute value: #{ value } as the value of xsi:#{ XSD::NilLiteral } (expected 'true', 'false', '1', or '0').")
|
raise EncodingStyleError.new("cannot accept attribute value: #{value} as the value of xsi:#{XSD::NilLiteral} (expected 'true', 'false', '1', or '0')")
|
||||||
next
|
next
|
||||||
when XSD::AttrType
|
when XSD::AttrType
|
||||||
type = value
|
type = value
|
||||||
@ -523,7 +525,7 @@ private
|
|||||||
when AttrRoot
|
when AttrRoot
|
||||||
root = RootLiteralMap[value] or
|
root = RootLiteralMap[value] or
|
||||||
raise EncodingStyleError.new(
|
raise EncodingStyleError.new(
|
||||||
"Illegal root attribute value: #{ value }.")
|
"illegal root attribute value: #{value}")
|
||||||
next
|
next
|
||||||
when AttrOffset
|
when AttrOffset
|
||||||
offset = value
|
offset = value
|
||||||
@ -578,7 +580,7 @@ private
|
|||||||
ref.__setobj__(o)
|
ref.__setobj__(o)
|
||||||
false
|
false
|
||||||
else
|
else
|
||||||
raise EncodingStyleError.new("Unresolved reference: #{ ref.refid }.")
|
raise EncodingStyleError.new("unresolved reference: #{ref.refid}")
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
count -= 1
|
count -= 1
|
||||||
|
@ -175,7 +175,12 @@ public
|
|||||||
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 and !ns.assigned?(namespace)
|
||||||
tag = ns.assign(namespace, tag)
|
tag = ns.assign(namespace, tag)
|
||||||
attrs['xmlns:' << tag] = namespace
|
if tag == ''
|
||||||
|
attr = 'xmlns'
|
||||||
|
else
|
||||||
|
attr = "xmlns:#{tag}"
|
||||||
|
end
|
||||||
|
attrs[attr] = namespace
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -18,6 +18,12 @@ class HandlerSet
|
|||||||
@store = XSD::NamedElements.new
|
@store = XSD::NamedElements.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def dup
|
||||||
|
obj = HandlerSet.new
|
||||||
|
obj.store = @store.dup
|
||||||
|
obj
|
||||||
|
end
|
||||||
|
|
||||||
def add(handler)
|
def add(handler)
|
||||||
@store << handler
|
@store << handler
|
||||||
end
|
end
|
||||||
@ -51,6 +57,12 @@ class HandlerSet
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def store=(store)
|
||||||
|
@store = store
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# SOAP4R - SOAP Simple header item handler
|
# SOAP4R - SOAP Simple header item handler
|
||||||
# Copyright (C) 2003, 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 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;
|
||||||
@ -30,7 +30,7 @@ class SimpleHandler < SOAP::Header::Handler
|
|||||||
|
|
||||||
def on_outbound
|
def on_outbound
|
||||||
h = on_simple_outbound
|
h = on_simple_outbound
|
||||||
h ? SOAPElement.from_obj(h) : nil
|
h ? SOAPElement.from_obj(h, elename.namespace) : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_inbound(header, mustunderstand)
|
def on_inbound(header, mustunderstand)
|
||||||
|
116
lib/soap/httpconfigloader.rb
Normal file
116
lib/soap/httpconfigloader.rb
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
# SOAP4R - HTTP config loader.
|
||||||
|
# Copyright (C) 2005 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/property'
|
||||||
|
|
||||||
|
|
||||||
|
module SOAP
|
||||||
|
|
||||||
|
|
||||||
|
module HTTPConfigLoader
|
||||||
|
module_function
|
||||||
|
|
||||||
|
def set_options(client, options)
|
||||||
|
client.proxy = options["proxy"]
|
||||||
|
options.add_hook("proxy") do |key, value|
|
||||||
|
client.proxy = value
|
||||||
|
end
|
||||||
|
client.no_proxy = options["no_proxy"]
|
||||||
|
options.add_hook("no_proxy") do |key, value|
|
||||||
|
client.no_proxy = value
|
||||||
|
end
|
||||||
|
if client.respond_to?(:protocol_version=)
|
||||||
|
client.protocol_version = options["protocol_version"]
|
||||||
|
options.add_hook("protocol_version") do |key, value|
|
||||||
|
client.protocol_version = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ssl_config = options["ssl_config"] ||= ::SOAP::Property.new
|
||||||
|
set_ssl_config(client, ssl_config)
|
||||||
|
ssl_config.add_hook(true) do |key, value|
|
||||||
|
set_ssl_config(client, ssl_config)
|
||||||
|
end
|
||||||
|
basic_auth = options["basic_auth"] ||= ::SOAP::Property.new
|
||||||
|
set_basic_auth(client, basic_auth)
|
||||||
|
basic_auth.add_hook do |key, value|
|
||||||
|
set_basic_auth(client, basic_auth)
|
||||||
|
end
|
||||||
|
options.add_hook("connect_timeout") do |key, value|
|
||||||
|
client.connect_timeout = value
|
||||||
|
end
|
||||||
|
options.add_hook("send_timeout") do |key, value|
|
||||||
|
client.send_timeout = value
|
||||||
|
end
|
||||||
|
options.add_hook("receive_timeout") do |key, value|
|
||||||
|
client.receive_timeout = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_basic_auth(client, basic_auth)
|
||||||
|
basic_auth.values.each do |url, userid, passwd|
|
||||||
|
client.set_basic_auth(url, userid, passwd)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_ssl_config(client, ssl_config)
|
||||||
|
ssl_config.each do |key, value|
|
||||||
|
cfg = client.ssl_config
|
||||||
|
case key
|
||||||
|
when 'client_cert'
|
||||||
|
cfg.client_cert = cert_from_file(value)
|
||||||
|
when 'client_key'
|
||||||
|
cfg.client_key = key_from_file(value)
|
||||||
|
when 'client_ca'
|
||||||
|
cfg.client_ca = value
|
||||||
|
when 'ca_path'
|
||||||
|
cfg.set_trust_ca(value)
|
||||||
|
when 'ca_file'
|
||||||
|
cfg.set_trust_ca(value)
|
||||||
|
when 'crl'
|
||||||
|
cfg.set_crl(value)
|
||||||
|
when 'verify_mode'
|
||||||
|
cfg.verify_mode = ssl_config_int(value)
|
||||||
|
when 'verify_depth'
|
||||||
|
cfg.verify_depth = ssl_config_int(value)
|
||||||
|
when 'options'
|
||||||
|
cfg.options = value
|
||||||
|
when 'ciphers'
|
||||||
|
cfg.ciphers = value
|
||||||
|
when 'verify_callback'
|
||||||
|
cfg.verify_callback = value
|
||||||
|
when 'cert_store'
|
||||||
|
cfg.cert_store = value
|
||||||
|
else
|
||||||
|
raise ArgumentError.new("unknown ssl_config property #{key}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def ssl_config_int(value)
|
||||||
|
if value.nil? or value.to_s.empty?
|
||||||
|
nil
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Integer(value)
|
||||||
|
rescue ArgumentError
|
||||||
|
::SOAP::Property::Util.const_from_name(value.to_s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def cert_from_file(filename)
|
||||||
|
OpenSSL::X509::Certificate.new(File.open(filename) { |f| f.read })
|
||||||
|
end
|
||||||
|
|
||||||
|
def key_from_file(filename)
|
||||||
|
OpenSSL::PKey::RSA.new(File.open(filename) { |f| f.read })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
@ -37,22 +37,26 @@ class Factory
|
|||||||
end
|
end
|
||||||
|
|
||||||
def setiv2soap(node, obj, map)
|
def setiv2soap(node, obj, map)
|
||||||
|
if obj.class.class_variables.include?('@@schema_element')
|
||||||
|
obj.class.class_eval('@@schema_element').each do |name, info|
|
||||||
|
type, qname = info
|
||||||
|
if qname
|
||||||
|
elename = qname.name
|
||||||
|
else
|
||||||
|
elename = Mapping.name2elename(name)
|
||||||
|
end
|
||||||
|
node.add(elename,
|
||||||
|
Mapping._obj2soap(obj.instance_variable_get('@' + name), map))
|
||||||
|
end
|
||||||
|
else
|
||||||
# should we sort instance_variables?
|
# should we sort instance_variables?
|
||||||
obj.instance_variables.each do |var|
|
obj.instance_variables.each do |var|
|
||||||
name = var.sub(/^@/, '')
|
name = var.sub(/^@/, '')
|
||||||
node.add(Mapping.name2elename(name),
|
elename = Mapping.name2elename(name)
|
||||||
|
node.add(elename,
|
||||||
Mapping._obj2soap(obj.instance_variable_get(var), map))
|
Mapping._obj2soap(obj.instance_variable_get(var), map))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# It breaks Thread.current[:SOAPMarshalDataKey].
|
|
||||||
def mark_marshalled_obj(obj, soap_obj)
|
|
||||||
Thread.current[:SOAPMarshalDataKey][obj.__id__] = soap_obj
|
|
||||||
end
|
|
||||||
|
|
||||||
# It breaks Thread.current[:SOAPMarshalDataKey].
|
|
||||||
def mark_unmarshalled_obj(node, obj)
|
|
||||||
Thread.current[:SOAPMarshalDataKey][node.id] = obj
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -68,7 +72,7 @@ private
|
|||||||
node.each do |name, value|
|
node.each do |name, value|
|
||||||
vars[Mapping.elename2name(name)] = Mapping._soap2obj(value, map)
|
vars[Mapping.elename2name(name)] = Mapping._soap2obj(value, map)
|
||||||
end
|
end
|
||||||
Mapping.set_instance_vars(obj, vars)
|
Mapping.set_attributes(obj, vars)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -156,20 +160,14 @@ class DateTimeFactory_ < Factory
|
|||||||
end
|
end
|
||||||
|
|
||||||
def soap2obj(obj_class, node, info, map)
|
def soap2obj(obj_class, node, info, map)
|
||||||
obj = nil
|
if node.respond_to?(:to_obj)
|
||||||
if obj_class == Time
|
obj = node.to_obj(obj_class)
|
||||||
obj = node.to_time
|
return false if obj.nil?
|
||||||
if obj.nil?
|
mark_unmarshalled_obj(node, obj)
|
||||||
# Is out of range as a Time
|
return true, obj
|
||||||
return false
|
|
||||||
end
|
|
||||||
elsif obj_class == Date
|
|
||||||
obj = node.data
|
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
mark_unmarshalled_obj(node, obj)
|
|
||||||
return true, obj
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# SOAP4R - Ruby type mapping utility.
|
# SOAP4R - Ruby type mapping utility.
|
||||||
# Copyright (C) 2000, 2001, 2003, 2004 NAKAMURA Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 2000, 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;
|
||||||
@ -23,10 +23,12 @@ module Mapping
|
|||||||
# TraverseSupport breaks Thread.current[:SOAPMarshalDataKey].
|
# TraverseSupport breaks Thread.current[:SOAPMarshalDataKey].
|
||||||
module TraverseSupport
|
module TraverseSupport
|
||||||
def mark_marshalled_obj(obj, soap_obj)
|
def mark_marshalled_obj(obj, soap_obj)
|
||||||
|
raise if obj.nil?
|
||||||
Thread.current[:SOAPMarshalDataKey][obj.__id__] = soap_obj
|
Thread.current[:SOAPMarshalDataKey][obj.__id__] = soap_obj
|
||||||
end
|
end
|
||||||
|
|
||||||
def mark_unmarshalled_obj(node, obj)
|
def mark_unmarshalled_obj(node, obj)
|
||||||
|
return if obj.nil?
|
||||||
# node.id is not Object#id but SOAPReference#id
|
# node.id is not Object#id but SOAPReference#id
|
||||||
Thread.current[:SOAPMarshalDataKey][node.id] = obj
|
Thread.current[:SOAPMarshalDataKey][node.id] = obj
|
||||||
end
|
end
|
||||||
@ -41,10 +43,10 @@ module Mapping
|
|||||||
soap_obj
|
soap_obj
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.soap2obj(node, registry = nil)
|
def self.soap2obj(node, registry = nil, klass = nil)
|
||||||
registry ||= Mapping::DefaultRegistry
|
registry ||= Mapping::DefaultRegistry
|
||||||
Thread.current[:SOAPMarshalDataKey] = {}
|
Thread.current[:SOAPMarshalDataKey] = {}
|
||||||
obj = _soap2obj(node, registry)
|
obj = _soap2obj(node, registry, klass)
|
||||||
Thread.current[:SOAPMarshalDataKey] = nil
|
Thread.current[:SOAPMarshalDataKey] = nil
|
||||||
obj
|
obj
|
||||||
end
|
end
|
||||||
@ -107,21 +109,21 @@ module Mapping
|
|||||||
elsif registry
|
elsif registry
|
||||||
registry.obj2soap(obj, type)
|
registry.obj2soap(obj, type)
|
||||||
else
|
else
|
||||||
raise MappingError.new("No mapping registry given.")
|
raise MappingError.new("no mapping registry given")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self._soap2obj(node, registry)
|
def self._soap2obj(node, registry, klass = nil)
|
||||||
if node.is_a?(SOAPReference)
|
if node.is_a?(SOAPReference)
|
||||||
target = node.__getobj__
|
target = node.__getobj__
|
||||||
# target.id is not Object#id but SOAPReference#id
|
# target.id is not Object#id but SOAPReference#id
|
||||||
if referent = Thread.current[:SOAPMarshalDataKey][target.id]
|
if referent = Thread.current[:SOAPMarshalDataKey][target.id]
|
||||||
return referent
|
return referent
|
||||||
else
|
else
|
||||||
return _soap2obj(target, registry)
|
return _soap2obj(target, registry, klass)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return registry.soap2obj(node)
|
return registry.soap2obj(node, klass)
|
||||||
end
|
end
|
||||||
|
|
||||||
if Object.respond_to?(:allocate)
|
if Object.respond_to?(:allocate)
|
||||||
@ -157,29 +159,6 @@ module Mapping
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
unless Object.respond_to?(:instance_variable_get)
|
|
||||||
class Object
|
|
||||||
def instance_variable_get(ivarname)
|
|
||||||
instance_eval(ivarname)
|
|
||||||
end
|
|
||||||
|
|
||||||
def instance_variable_set(ivarname, value)
|
|
||||||
instance_eval("#{ivarname} = value")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.set_instance_vars(obj, values)
|
|
||||||
values.each do |name, value|
|
|
||||||
setter = name + "="
|
|
||||||
if obj.respond_to?(setter)
|
|
||||||
obj.__send__(setter, value)
|
|
||||||
else
|
|
||||||
obj.instance_variable_set('@' + name, value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Allow only (Letter | '_') (Letter | Digit | '-' | '_')* here.
|
# Allow only (Letter | '_') (Letter | Digit | '-' | '_')* here.
|
||||||
# Caution: '.' is not allowed here.
|
# Caution: '.' is not allowed here.
|
||||||
# To follow XML spec., it should be NCName.
|
# To follow XML spec., it should be NCName.
|
||||||
@ -198,28 +177,51 @@ module Mapping
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.class_from_name(name)
|
def self.const_from_name(name, lenient = false)
|
||||||
if /^[A-Z]/ !~ name
|
const = ::Object
|
||||||
|
name.sub(/\A::/, '').split('::').each do |const_str|
|
||||||
|
if XSD::CodeGen::GenSupport.safeconstname?(const_str)
|
||||||
|
if const.const_defined?(const_str)
|
||||||
|
const = const.const_get(const_str)
|
||||||
|
next
|
||||||
|
end
|
||||||
|
elsif lenient
|
||||||
|
const_str = XSD::CodeGen::GenSupport.safeconstname(const_str)
|
||||||
|
if const.const_defined?(const_str)
|
||||||
|
const = const.const_get(const_str)
|
||||||
|
next
|
||||||
|
end
|
||||||
|
end
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
klass = ::Object
|
const
|
||||||
name.split('::').each do |klass_str|
|
end
|
||||||
if klass.const_defined?(klass_str)
|
|
||||||
klass = klass.const_get(klass_str)
|
def self.class_from_name(name, lenient = false)
|
||||||
|
const = const_from_name(name, lenient)
|
||||||
|
if const.is_a?(::Class)
|
||||||
|
const
|
||||||
else
|
else
|
||||||
return nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
klass
|
|
||||||
|
def self.module_from_name(name, lenient = false)
|
||||||
|
const = const_from_name(name, lenient)
|
||||||
|
if const.is_a?(::Module)
|
||||||
|
const
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.class2qname(klass)
|
def self.class2qname(klass)
|
||||||
name = if klass.class_variables.include?("@@schema_type")
|
name = if klass.class_variables.include?('@@schema_type')
|
||||||
klass.class_eval('@@schema_type')
|
klass.class_eval('@@schema_type')
|
||||||
else
|
else
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
namespace = if klass.class_variables.include?("@@schema_ns")
|
namespace = if klass.class_variables.include?('@@schema_ns')
|
||||||
klass.class_eval('@@schema_ns')
|
klass.class_eval('@@schema_ns')
|
||||||
else
|
else
|
||||||
nil
|
nil
|
||||||
@ -250,19 +252,75 @@ module Mapping
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.find_attribute(obj, attr_name)
|
def self.define_singleton_method(obj, name, &block)
|
||||||
|
sclass = (class << obj; self; end)
|
||||||
|
sclass.__send__(:define_method, name, &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_attribute(obj, attr_name)
|
||||||
if obj.is_a?(::Hash)
|
if obj.is_a?(::Hash)
|
||||||
obj[attr_name] || obj[attr_name.intern]
|
obj[attr_name] || obj[attr_name.intern]
|
||||||
else
|
else
|
||||||
name = ::XSD::CodeGen::GenSupport.safevarname(attr_name)
|
name = XSD::CodeGen::GenSupport.safevarname(attr_name)
|
||||||
if obj.respond_to?(name)
|
if obj.instance_variables.include?('@' + name)
|
||||||
obj.__send__(name)
|
|
||||||
else
|
|
||||||
obj.instance_variable_get('@' + name)
|
obj.instance_variable_get('@' + name)
|
||||||
|
elsif ((obj.is_a?(::Struct) or obj.is_a?(Marshallable)) and
|
||||||
|
obj.respond_to?(name))
|
||||||
|
obj.__send__(name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.set_attributes(obj, values)
|
||||||
|
if obj.is_a?(::SOAP::Mapping::Object)
|
||||||
|
values.each do |attr_name, value|
|
||||||
|
obj.__add_xmlele_value(attr_name, value)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
values.each do |attr_name, value|
|
||||||
|
name = XSD::CodeGen::GenSupport.safevarname(attr_name)
|
||||||
|
setter = name + "="
|
||||||
|
if obj.respond_to?(setter)
|
||||||
|
obj.__send__(setter, value)
|
||||||
|
else
|
||||||
|
obj.instance_variable_set('@' + name, value)
|
||||||
|
begin
|
||||||
|
define_attr_accessor(obj, name,
|
||||||
|
proc { instance_variable_get('@' + name) },
|
||||||
|
proc { |value| instance_variable_set('@' + name, value) })
|
||||||
|
rescue TypeError
|
||||||
|
# singleton class may not exist (e.g. Float)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.define_attr_accessor(obj, name, getterproc, setterproc = nil)
|
||||||
|
define_singleton_method(obj, name, &getterproc)
|
||||||
|
define_singleton_method(obj, name + '=', &setterproc) if setterproc
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.schema_element_definition(klass)
|
||||||
|
return nil unless klass.class_variables.include?('@@schema_element')
|
||||||
|
elements = {}
|
||||||
|
as_array = []
|
||||||
|
klass.class_eval('@@schema_element').each do |varname, definition|
|
||||||
|
class_name, name = definition
|
||||||
|
if /\[\]$/ =~ class_name
|
||||||
|
class_name = class_name.sub(/\[\]$/, '')
|
||||||
|
as_array << class_name
|
||||||
|
end
|
||||||
|
elements[name ? name.name : varname] = class_name
|
||||||
|
end
|
||||||
|
[elements, as_array]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.schema_attribute_definition(klass)
|
||||||
|
return nil unless klass.class_variables.include?('@@schema_attribute')
|
||||||
|
klass.class_eval('@@schema_attribute')
|
||||||
|
end
|
||||||
|
|
||||||
class << Mapping
|
class << Mapping
|
||||||
private
|
private
|
||||||
def add_md_ary(md_ary, ary, indices, registry)
|
def add_md_ary(md_ary, ary, indices, registry)
|
||||||
|
@ -64,50 +64,105 @@ end
|
|||||||
# For anyType object: SOAP::Mapping::Object not ::Object
|
# For anyType object: SOAP::Mapping::Object not ::Object
|
||||||
class Object; include Marshallable
|
class Object; include Marshallable
|
||||||
def initialize
|
def initialize
|
||||||
@__soap_value_type = {}
|
@__xmlele_type = {}
|
||||||
@__soap_value = {}
|
@__xmlele = []
|
||||||
|
@__xmlattr = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def [](name)
|
def inspect
|
||||||
@__soap_value[name]
|
sprintf("#<%s:0x%x%s>", self.class.name, __id__,
|
||||||
|
@__xmlele.collect { |name, value| " #{name}=#{value.inspect}" }.join)
|
||||||
end
|
end
|
||||||
|
|
||||||
def []=(name, value)
|
def __xmlattr
|
||||||
@__soap_value[name] = value
|
@__xmlattr
|
||||||
end
|
end
|
||||||
|
|
||||||
def __soap_set_property(name, value)
|
def __xmlele
|
||||||
unless @__soap_value.key?(name)
|
@__xmlele
|
||||||
__define_attr_accessor(name)
|
|
||||||
end
|
|
||||||
__soap_set_property_value(name, value)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
def [](qname)
|
||||||
|
unless qname.is_a?(XSD::QName)
|
||||||
|
qname = XSD::QName.new(nil, qname)
|
||||||
|
end
|
||||||
|
@__xmlele.each do |k, v|
|
||||||
|
return v if k == qname
|
||||||
|
end
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
def __soap_set_property_value(name, value)
|
def []=(qname, value)
|
||||||
org = self[name]
|
unless qname.is_a?(XSD::QName)
|
||||||
case @__soap_value_type[name]
|
qname = XSD::QName.new(nil, qname)
|
||||||
when :single
|
end
|
||||||
self[name] = [org, value]
|
found = false
|
||||||
@__soap_value_type[name] = :multi
|
@__xmlele.each do |pair|
|
||||||
when :multi
|
if pair[0] == qname
|
||||||
org << value
|
found = true
|
||||||
|
pair[1] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
unless found
|
||||||
|
__define_attr_accessor(qname)
|
||||||
|
@__xmlele << [qname, value]
|
||||||
|
end
|
||||||
|
@__xmlele_type[qname] = :single
|
||||||
|
end
|
||||||
|
|
||||||
|
def __add_xmlele_value(qname, value)
|
||||||
|
found = false
|
||||||
|
@__xmlele.map! do |k, v|
|
||||||
|
if k == qname
|
||||||
|
found = true
|
||||||
|
[k, __set_xmlele_value(k, v, value)]
|
||||||
else
|
else
|
||||||
self[name] = value
|
[k, v]
|
||||||
@__soap_value_type[name] = :single
|
end
|
||||||
|
end
|
||||||
|
unless found
|
||||||
|
__define_attr_accessor(qname)
|
||||||
|
@__xmlele << [qname, value]
|
||||||
|
@__xmlele_type[qname] = :single
|
||||||
end
|
end
|
||||||
value
|
value
|
||||||
end
|
end
|
||||||
|
|
||||||
def __define_attr_accessor(name)
|
private
|
||||||
sclass = class << self; self; end
|
|
||||||
sclass.__send__(:define_method, name, proc {
|
if RUBY_VERSION > "1.7.0"
|
||||||
self[name]
|
def __define_attr_accessor(qname)
|
||||||
})
|
name = XSD::CodeGen::GenSupport.safemethodname(qname.name)
|
||||||
sclass.__send__(:define_method, name + '=', proc { |value|
|
Mapping.define_attr_accessor(self, name,
|
||||||
self[name] = value
|
proc { self[qname] },
|
||||||
})
|
proc { |value| self[qname] = value })
|
||||||
|
end
|
||||||
|
else
|
||||||
|
def __define_attr_accessor(qname)
|
||||||
|
name = XSD::CodeGen::GenSupport.safemethodname(qname.name)
|
||||||
|
instance_eval <<-EOS
|
||||||
|
def #{name}
|
||||||
|
self[#{qname.dump}]
|
||||||
|
end
|
||||||
|
|
||||||
|
def #{name}=(value)
|
||||||
|
self[#{qname.dump}] = value
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def __set_xmlele_value(key, org, value)
|
||||||
|
case @__xmlele_type[key]
|
||||||
|
when :multi
|
||||||
|
org << value
|
||||||
|
org
|
||||||
|
when :single
|
||||||
|
@__xmlele_type[key] = :multi
|
||||||
|
[org, value]
|
||||||
|
else
|
||||||
|
raise RuntimeError.new("unknown type")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -123,7 +178,7 @@ class Registry
|
|||||||
@registry = registry
|
@registry = registry
|
||||||
end
|
end
|
||||||
|
|
||||||
def obj2soap(obj, type_qname = nil)
|
def obj2soap(obj)
|
||||||
klass = obj.class
|
klass = obj.class
|
||||||
if map = @obj2soap[klass]
|
if map = @obj2soap[klass]
|
||||||
map.each do |soap_class, factory, info|
|
map.each do |soap_class, factory, info|
|
||||||
@ -131,7 +186,10 @@ class Registry
|
|||||||
return ret if ret
|
return ret if ret
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
ancestors = klass.ancestors[1..-3] # except itself, Object and Kernel
|
ancestors = klass.ancestors
|
||||||
|
ancestors.delete(klass)
|
||||||
|
ancestors.delete(::Object)
|
||||||
|
ancestors.delete(::Kernel)
|
||||||
ancestors.each do |klass|
|
ancestors.each do |klass|
|
||||||
if map = @obj2soap[klass]
|
if map = @obj2soap[klass]
|
||||||
map.each do |soap_class, factory, info|
|
map.each do |soap_class, factory, info|
|
||||||
@ -145,10 +203,10 @@ class Registry
|
|||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def soap2obj(node)
|
def soap2obj(node, klass = nil)
|
||||||
klass = node.class
|
if map = @soap2obj[node.class]
|
||||||
if map = @soap2obj[klass]
|
|
||||||
map.each do |obj_class, factory, info|
|
map.each do |obj_class, factory, info|
|
||||||
|
next if klass and obj_class != klass
|
||||||
conv, obj = factory.soap2obj(obj_class, node, info, @registry)
|
conv, obj = factory.soap2obj(obj_class, node, info, @registry)
|
||||||
return true, obj if conv
|
return true, obj if conv
|
||||||
end
|
end
|
||||||
@ -177,11 +235,13 @@ class Registry
|
|||||||
end
|
end
|
||||||
|
|
||||||
def find_mapped_soap_class(target_obj_class)
|
def find_mapped_soap_class(target_obj_class)
|
||||||
@obj2soap[target_obj_class][0]
|
map = @obj2soap[target_obj_class]
|
||||||
|
map.empty? ? nil : map[0][1]
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_mapped_obj_class(target_soap_class)
|
def find_mapped_obj_class(target_soap_class)
|
||||||
@soap2obj[target_soap_class][0]
|
map = @soap2obj[target_soap_class]
|
||||||
|
map.empty? ? nil : map[0][0]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -202,7 +262,6 @@ class Registry
|
|||||||
[::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory],
|
[::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory],
|
||||||
[::String, ::SOAP::SOAPString, StringFactory],
|
[::String, ::SOAP::SOAPString, StringFactory],
|
||||||
[::DateTime, ::SOAP::SOAPDateTime, DateTimeFactory],
|
[::DateTime, ::SOAP::SOAPDateTime, DateTimeFactory],
|
||||||
[::Date, ::SOAP::SOAPDateTime, DateTimeFactory],
|
|
||||||
[::Date, ::SOAP::SOAPDate, DateTimeFactory],
|
[::Date, ::SOAP::SOAPDate, DateTimeFactory],
|
||||||
[::Time, ::SOAP::SOAPDateTime, DateTimeFactory],
|
[::Time, ::SOAP::SOAPDateTime, DateTimeFactory],
|
||||||
[::Time, ::SOAP::SOAPTime, DateTimeFactory],
|
[::Time, ::SOAP::SOAPTime, DateTimeFactory],
|
||||||
@ -266,7 +325,6 @@ class Registry
|
|||||||
[::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory],
|
[::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory],
|
||||||
[::String, ::SOAP::SOAPString, StringFactory],
|
[::String, ::SOAP::SOAPString, StringFactory],
|
||||||
[::DateTime, ::SOAP::SOAPDateTime, DateTimeFactory],
|
[::DateTime, ::SOAP::SOAPDateTime, DateTimeFactory],
|
||||||
[::Date, ::SOAP::SOAPDateTime, DateTimeFactory],
|
|
||||||
[::Date, ::SOAP::SOAPDate, DateTimeFactory],
|
[::Date, ::SOAP::SOAPDate, DateTimeFactory],
|
||||||
[::Time, ::SOAP::SOAPDateTime, DateTimeFactory],
|
[::Time, ::SOAP::SOAPDateTime, DateTimeFactory],
|
||||||
[::Time, ::SOAP::SOAPTime, DateTimeFactory],
|
[::Time, ::SOAP::SOAPTime, DateTimeFactory],
|
||||||
@ -354,17 +412,17 @@ class Registry
|
|||||||
end
|
end
|
||||||
alias set add
|
alias set add
|
||||||
|
|
||||||
# This mapping registry ignores type hint.
|
# general Registry ignores type_qname
|
||||||
def obj2soap(obj, type_qname = nil)
|
def obj2soap(obj, type_qname = nil)
|
||||||
soap = _obj2soap(obj, type_qname)
|
soap = _obj2soap(obj)
|
||||||
if @allow_original_mapping
|
if @allow_original_mapping
|
||||||
addextend2soap(soap, obj)
|
addextend2soap(soap, obj)
|
||||||
end
|
end
|
||||||
soap
|
soap
|
||||||
end
|
end
|
||||||
|
|
||||||
def soap2obj(node)
|
def soap2obj(node, klass = nil)
|
||||||
obj = _soap2obj(node)
|
obj = _soap2obj(node, klass)
|
||||||
if @allow_original_mapping
|
if @allow_original_mapping
|
||||||
addextend2obj(obj, node.extraattr[RubyExtendName])
|
addextend2obj(obj, node.extraattr[RubyExtendName])
|
||||||
addiv2obj(obj, node.extraattr[RubyIVarName])
|
addiv2obj(obj, node.extraattr[RubyIVarName])
|
||||||
@ -382,7 +440,7 @@ class Registry
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def _obj2soap(obj, type_qname)
|
def _obj2soap(obj)
|
||||||
ret = nil
|
ret = nil
|
||||||
if obj.is_a?(SOAPStruct) or obj.is_a?(SOAPArray)
|
if obj.is_a?(SOAPStruct) or obj.is_a?(SOAPArray)
|
||||||
obj.replace do |ele|
|
obj.replace do |ele|
|
||||||
@ -393,7 +451,7 @@ private
|
|||||||
return obj
|
return obj
|
||||||
end
|
end
|
||||||
begin
|
begin
|
||||||
ret = @map.obj2soap(obj, type_qname) ||
|
ret = @map.obj2soap(obj) ||
|
||||||
@default_factory.obj2soap(nil, obj, nil, self)
|
@default_factory.obj2soap(nil, obj, nil, self)
|
||||||
return ret if ret
|
return ret if ret
|
||||||
rescue MappingError
|
rescue MappingError
|
||||||
@ -408,12 +466,12 @@ private
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Might return nil as a mapping result.
|
# Might return nil as a mapping result.
|
||||||
def _soap2obj(node)
|
def _soap2obj(node, klass = nil)
|
||||||
if node.extraattr.key?(RubyTypeName)
|
if node.extraattr.key?(RubyTypeName)
|
||||||
conv, obj = @rubytype_factory.soap2obj(nil, node, nil, self)
|
conv, obj = @rubytype_factory.soap2obj(nil, node, nil, self)
|
||||||
return obj if conv
|
return obj if conv
|
||||||
else
|
else
|
||||||
conv, obj = @map.soap2obj(node)
|
conv, obj = @map.soap2obj(node, klass)
|
||||||
return obj if conv
|
return obj if conv
|
||||||
conv, obj = @default_factory.soap2obj(nil, node, nil, self)
|
conv, obj = @default_factory.soap2obj(nil, node, nil, self)
|
||||||
return obj if conv
|
return obj if conv
|
||||||
@ -435,14 +493,14 @@ private
|
|||||||
attr.__getobj__.each do |name, value|
|
attr.__getobj__.each do |name, value|
|
||||||
vars[name] = Mapping._soap2obj(value, self)
|
vars[name] = Mapping._soap2obj(value, self)
|
||||||
end
|
end
|
||||||
Mapping.set_instance_vars(obj, vars)
|
Mapping.set_attributes(obj, vars)
|
||||||
end
|
end
|
||||||
|
|
||||||
if RUBY_VERSION >= '1.8.0'
|
if RUBY_VERSION >= '1.8.0'
|
||||||
def addextend2obj(obj, attr)
|
def addextend2obj(obj, attr)
|
||||||
return unless attr
|
return unless attr
|
||||||
attr.split(/ /).reverse_each do |mstr|
|
attr.split(/ /).reverse_each do |mstr|
|
||||||
obj.extend(Mapping.class_from_name(mstr))
|
obj.extend(Mapping.module_from_name(mstr))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -450,8 +508,8 @@ private
|
|||||||
def addextend2obj(obj, attr)
|
def addextend2obj(obj, attr)
|
||||||
return unless attr
|
return unless attr
|
||||||
attr.split(/ /).reverse_each do |mstr|
|
attr.split(/ /).reverse_each do |mstr|
|
||||||
m = Mapping.class_from_name(mstr)
|
m = Mapping.module_from_name(mstr)
|
||||||
obj.extend(m) if m.class == Module
|
obj.extend(m)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# SOAP4R - Ruby type mapping factory.
|
# SOAP4R - Ruby type mapping factory.
|
||||||
# Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 2000-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;
|
||||||
@ -168,7 +168,7 @@ class RubytypeFactory < Factory
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
if obj.to_s[0] == ?#
|
if obj.to_s[0] == ?#
|
||||||
raise TypeError.new("can't dump anonymous class #{ obj }")
|
raise TypeError.new("can't dump anonymous class #{obj}")
|
||||||
end
|
end
|
||||||
param = SOAPStruct.new(TYPE_CLASS)
|
param = SOAPStruct.new(TYPE_CLASS)
|
||||||
mark_marshalled_obj(obj, param)
|
mark_marshalled_obj(obj, param)
|
||||||
@ -179,7 +179,7 @@ class RubytypeFactory < Factory
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
if obj.to_s[0] == ?#
|
if obj.to_s[0] == ?#
|
||||||
raise TypeError.new("can't dump anonymous module #{ obj }")
|
raise TypeError.new("can't dump anonymous module #{obj}")
|
||||||
end
|
end
|
||||||
param = SOAPStruct.new(TYPE_MODULE)
|
param = SOAPStruct.new(TYPE_MODULE)
|
||||||
mark_marshalled_obj(obj, param)
|
mark_marshalled_obj(obj, param)
|
||||||
@ -222,7 +222,12 @@ class RubytypeFactory < Factory
|
|||||||
when ::SOAP::Mapping::Object
|
when ::SOAP::Mapping::Object
|
||||||
param = SOAPStruct.new(XSD::AnyTypeName)
|
param = SOAPStruct.new(XSD::AnyTypeName)
|
||||||
mark_marshalled_obj(obj, param)
|
mark_marshalled_obj(obj, param)
|
||||||
addiv2soapattr(param, obj, map)
|
obj.__xmlele.each do |key, value|
|
||||||
|
param.add(key.name, Mapping._obj2soap(value, map))
|
||||||
|
end
|
||||||
|
obj.__xmlattr.each do |key, value|
|
||||||
|
param.extraattr[key] = value
|
||||||
|
end
|
||||||
when ::Exception
|
when ::Exception
|
||||||
typestr = Mapping.name2elename(obj.class.to_s)
|
typestr = Mapping.name2elename(obj.class.to_s)
|
||||||
param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, typestr))
|
param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, typestr))
|
||||||
@ -258,12 +263,12 @@ private
|
|||||||
|
|
||||||
def unknownobj2soap(soap_class, obj, info, map)
|
def unknownobj2soap(soap_class, obj, info, map)
|
||||||
if obj.class.name.empty?
|
if obj.class.name.empty?
|
||||||
raise TypeError.new("can't dump anonymous class #{ obj }")
|
raise TypeError.new("can't dump anonymous class #{obj}")
|
||||||
end
|
end
|
||||||
singleton_class = class << obj; self; end
|
singleton_class = class << obj; self; end
|
||||||
if !singleton_methods_true(obj).empty? or
|
if !singleton_methods_true(obj).empty? or
|
||||||
!singleton_class.instance_variables.empty?
|
!singleton_class.instance_variables.empty?
|
||||||
raise TypeError.new("singleton can't be dumped #{ obj }")
|
raise TypeError.new("singleton can't be dumped #{obj}")
|
||||||
end
|
end
|
||||||
if !(singleton_class.ancestors - obj.class.ancestors).empty?
|
if !(singleton_class.ancestors - obj.class.ancestors).empty?
|
||||||
typestr = Mapping.name2elename(obj.class.to_s)
|
typestr = Mapping.name2elename(obj.class.to_s)
|
||||||
@ -378,7 +383,11 @@ private
|
|||||||
obj = klass.new
|
obj = klass.new
|
||||||
mark_unmarshalled_obj(node, obj)
|
mark_unmarshalled_obj(node, obj)
|
||||||
node.each do |name, value|
|
node.each do |name, value|
|
||||||
obj.__soap_set_property(name, Mapping._soap2obj(value, map))
|
obj.__add_xmlele_value(XSD::QName.new(nil, name),
|
||||||
|
Mapping._soap2obj(value, map))
|
||||||
|
end
|
||||||
|
unless node.extraattr.empty?
|
||||||
|
obj.instance_variable_set('@__xmlattr', node.extraattr)
|
||||||
end
|
end
|
||||||
return true, obj
|
return true, obj
|
||||||
else
|
else
|
||||||
@ -387,7 +396,12 @@ private
|
|||||||
end
|
end
|
||||||
|
|
||||||
def unknowntype2obj(node, info, map)
|
def unknowntype2obj(node, info, map)
|
||||||
if node.is_a?(SOAPStruct)
|
case node
|
||||||
|
when SOAPBasetype
|
||||||
|
return true, node.data
|
||||||
|
when SOAPArray
|
||||||
|
return @array_factory.soap2obj(Array, node, info, map)
|
||||||
|
when SOAPStruct
|
||||||
obj = unknownstruct2obj(node, info, map)
|
obj = unknownstruct2obj(node, info, map)
|
||||||
return true, obj if obj
|
return true, obj if obj
|
||||||
if !@allow_untyped_struct
|
if !@allow_untyped_struct
|
||||||
@ -406,6 +420,9 @@ private
|
|||||||
end
|
end
|
||||||
typestr = Mapping.elename2name(node.type.name)
|
typestr = Mapping.elename2name(node.type.name)
|
||||||
klass = Mapping.class_from_name(typestr)
|
klass = Mapping.class_from_name(typestr)
|
||||||
|
if klass.nil? and @allow_untyped_struct
|
||||||
|
klass = Mapping.class_from_name(typestr, true) # lenient
|
||||||
|
end
|
||||||
if klass.nil?
|
if klass.nil?
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@ -414,7 +431,13 @@ private
|
|||||||
end
|
end
|
||||||
klass_type = Mapping.class2qname(klass)
|
klass_type = Mapping.class2qname(klass)
|
||||||
return nil unless node.type.match(klass_type)
|
return nil unless node.type.match(klass_type)
|
||||||
|
obj = nil
|
||||||
|
begin
|
||||||
obj = Mapping.create_empty_object(klass)
|
obj = Mapping.create_empty_object(klass)
|
||||||
|
rescue
|
||||||
|
# type name "data" tries Data.new which raises TypeError
|
||||||
|
nil
|
||||||
|
end
|
||||||
mark_unmarshalled_obj(node, obj)
|
mark_unmarshalled_obj(node, obj)
|
||||||
setiv2obj(obj, node, map)
|
setiv2obj(obj, node, map)
|
||||||
obj
|
obj
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
# SOAP4R - WSDL encoded mapping registry.
|
# SOAP4R - WSDL encoded mapping registry.
|
||||||
# Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 2000-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;
|
||||||
# either the dual license version in 2003, or any later version.
|
# either the dual license version in 2003, or any later version.
|
||||||
|
|
||||||
|
|
||||||
|
require 'xsd/qname'
|
||||||
|
require 'xsd/namedelements'
|
||||||
require 'soap/baseData'
|
require 'soap/baseData'
|
||||||
require 'soap/mapping/mapping'
|
require 'soap/mapping/mapping'
|
||||||
require 'soap/mapping/typeMap'
|
require 'soap/mapping/typeMap'
|
||||||
@ -15,35 +17,33 @@ module SOAP
|
|||||||
module Mapping
|
module Mapping
|
||||||
|
|
||||||
|
|
||||||
class WSDLEncodedRegistry
|
class WSDLEncodedRegistry < Registry
|
||||||
include TraverseSupport
|
include TraverseSupport
|
||||||
|
|
||||||
|
attr_reader :definedelements
|
||||||
attr_reader :definedtypes
|
attr_reader :definedtypes
|
||||||
attr_accessor :excn_handler_obj2soap
|
attr_accessor :excn_handler_obj2soap
|
||||||
|
attr_accessor :excn_handler_soap2obj
|
||||||
|
|
||||||
def initialize(definedtypes, config = {})
|
def initialize(definedtypes = XSD::NamedElements::Empty)
|
||||||
@definedtypes = definedtypes
|
@definedtypes = definedtypes
|
||||||
@config = config
|
# @definedelements = definedelements needed?
|
||||||
@excn_handler_obj2soap = nil
|
@excn_handler_obj2soap = nil
|
||||||
|
@excn_handler_soap2obj = nil
|
||||||
# For mapping AnyType element.
|
# For mapping AnyType element.
|
||||||
@rubytype_factory = RubytypeFactory.new(
|
@rubytype_factory = RubytypeFactory.new(
|
||||||
:allow_untyped_struct => true,
|
:allow_untyped_struct => true,
|
||||||
:allow_original_mapping => true
|
:allow_original_mapping => true
|
||||||
)
|
)
|
||||||
|
@schema_element_cache = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def obj2soap(obj, type_qname = nil)
|
def obj2soap(obj, qname = nil)
|
||||||
soap_obj = nil
|
soap_obj = nil
|
||||||
if obj.nil?
|
if type = @definedtypes[qname]
|
||||||
soap_obj = SOAPNil.new
|
soap_obj = obj2typesoap(obj, type)
|
||||||
elsif type_qname.nil? or type_qname == XSD::AnyTypeName
|
else
|
||||||
soap_obj = @rubytype_factory.obj2soap(nil, obj, nil, self)
|
soap_obj = any2soap(obj, qname)
|
||||||
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)
|
|
||||||
end
|
end
|
||||||
return soap_obj if soap_obj
|
return soap_obj if soap_obj
|
||||||
if @excn_handler_obj2soap
|
if @excn_handler_obj2soap
|
||||||
@ -52,15 +52,46 @@ class WSDLEncodedRegistry
|
|||||||
}
|
}
|
||||||
return soap_obj if soap_obj
|
return soap_obj if soap_obj
|
||||||
end
|
end
|
||||||
raise MappingError.new("Cannot map #{ obj.class.name } to SOAP/OM.")
|
if qname
|
||||||
|
raise MappingError.new("cannot map #{obj.class.name} as #{qname}")
|
||||||
|
else
|
||||||
|
raise MappingError.new("cannot map #{obj.class.name} to SOAP/OM")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def soap2obj(node)
|
# map anything for now: must refer WSDL while mapping. [ToDo]
|
||||||
raise RuntimeError.new("#{ self } is for obj2soap only.")
|
def soap2obj(node, obj_class = nil)
|
||||||
|
begin
|
||||||
|
return any2obj(node, obj_class)
|
||||||
|
rescue MappingError
|
||||||
|
end
|
||||||
|
if @excn_handler_soap2obj
|
||||||
|
begin
|
||||||
|
return @excn_handler_soap2obj.call(node) { |yield_node|
|
||||||
|
Mapping._soap2obj(yield_node, self)
|
||||||
|
}
|
||||||
|
rescue Exception
|
||||||
|
end
|
||||||
|
end
|
||||||
|
raise MappingError.new("cannot map #{node.type.name} to Ruby object")
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def any2soap(obj, qname)
|
||||||
|
if obj.nil?
|
||||||
|
SOAPNil.new
|
||||||
|
elsif qname.nil? or qname == XSD::AnyTypeName
|
||||||
|
@rubytype_factory.obj2soap(nil, obj, nil, self)
|
||||||
|
elsif obj.is_a?(XSD::NSDBase)
|
||||||
|
soap2soap(obj, qname)
|
||||||
|
elsif (type = TypeMap[qname])
|
||||||
|
base2soap(obj, type)
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def soap2soap(obj, type_qname)
|
def soap2soap(obj, type_qname)
|
||||||
if obj.is_a?(SOAPBasetype)
|
if obj.is_a?(SOAPBasetype)
|
||||||
obj
|
obj
|
||||||
@ -82,25 +113,22 @@ private
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def obj2type(obj, type)
|
def obj2typesoap(obj, type)
|
||||||
if type.is_a?(::WSDL::XMLSchema::SimpleType)
|
if type.is_a?(::WSDL::XMLSchema::SimpleType)
|
||||||
simple2soap(obj, type)
|
simpleobj2soap(obj, type)
|
||||||
else
|
else
|
||||||
complex2soap(obj, type)
|
complexobj2soap(obj, type)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def simple2soap(obj, type)
|
def simpleobj2soap(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)
|
type.check_lexical_format(obj)
|
||||||
|
return SOAPNil.new if obj.nil? # ToDo: check nillable.
|
||||||
|
o = base2soap(obj, TypeMap[type.base])
|
||||||
o
|
o
|
||||||
end
|
end
|
||||||
|
|
||||||
def complex2soap(obj, type)
|
def complexobj2soap(obj, type)
|
||||||
case type.compoundtype
|
case type.compoundtype
|
||||||
when :TYPE_STRUCT
|
when :TYPE_STRUCT
|
||||||
struct2soap(obj, type.name, type)
|
struct2soap(obj, type.name, type)
|
||||||
@ -108,8 +136,13 @@ private
|
|||||||
array2soap(obj, type.name, type)
|
array2soap(obj, type.name, type)
|
||||||
when :TYPE_MAP
|
when :TYPE_MAP
|
||||||
map2soap(obj, type.name, type)
|
map2soap(obj, type.name, type)
|
||||||
|
when :TYPE_SIMPLE
|
||||||
|
simpleobj2soap(obj, type.simplecontent)
|
||||||
|
when :TYPE_EMPTY
|
||||||
|
raise MappingError.new("should be empty") unless obj.nil?
|
||||||
|
SOAPNil.new
|
||||||
else
|
else
|
||||||
raise MappingError.new("Unknown compound type: #{ type.compoundtype }")
|
raise MappingError.new("unknown compound type: #{type.compoundtype}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -126,28 +159,36 @@ private
|
|||||||
end
|
end
|
||||||
|
|
||||||
def struct2soap(obj, type_qname, type)
|
def struct2soap(obj, type_qname, type)
|
||||||
|
return SOAPNil.new if obj.nil? # ToDo: check nillable.
|
||||||
soap_obj = SOAPStruct.new(type_qname)
|
soap_obj = SOAPStruct.new(type_qname)
|
||||||
|
unless obj.nil?
|
||||||
mark_marshalled_obj(obj, soap_obj)
|
mark_marshalled_obj(obj, soap_obj)
|
||||||
elements2soap(obj, soap_obj, type.content.elements)
|
elements2soap(obj, soap_obj, type.content.elements)
|
||||||
|
end
|
||||||
soap_obj
|
soap_obj
|
||||||
end
|
end
|
||||||
|
|
||||||
def array2soap(obj, type_qname, type)
|
def array2soap(obj, type_qname, type)
|
||||||
|
return SOAPNil.new if obj.nil? # ToDo: check nillable.
|
||||||
arytype = type.child_type
|
arytype = type.child_type
|
||||||
soap_obj = SOAPArray.new(ValueArrayName, 1, arytype)
|
soap_obj = SOAPArray.new(ValueArrayName, 1, arytype)
|
||||||
|
unless obj.nil?
|
||||||
mark_marshalled_obj(obj, soap_obj)
|
mark_marshalled_obj(obj, soap_obj)
|
||||||
obj.each do |item|
|
obj.each do |item|
|
||||||
soap_obj.add(Mapping._obj2soap(item, self, arytype))
|
soap_obj.add(Mapping._obj2soap(item, self, arytype))
|
||||||
end
|
end
|
||||||
|
end
|
||||||
soap_obj
|
soap_obj
|
||||||
end
|
end
|
||||||
|
|
||||||
MapKeyName = XSD::QName.new(nil, "key")
|
MapKeyName = XSD::QName.new(nil, "key")
|
||||||
MapValueName = XSD::QName.new(nil, "value")
|
MapValueName = XSD::QName.new(nil, "value")
|
||||||
def map2soap(obj, type_qname, type)
|
def map2soap(obj, type_qname, type)
|
||||||
|
return SOAPNil.new if obj.nil? # ToDo: check nillable.
|
||||||
keytype = type.child_type(MapKeyName) || XSD::AnyTypeName
|
keytype = type.child_type(MapKeyName) || XSD::AnyTypeName
|
||||||
valuetype = type.child_type(MapValueName) || XSD::AnyTypeName
|
valuetype = type.child_type(MapValueName) || XSD::AnyTypeName
|
||||||
soap_obj = SOAPStruct.new(MapQName)
|
soap_obj = SOAPStruct.new(MapQName)
|
||||||
|
unless obj.nil?
|
||||||
mark_marshalled_obj(obj, soap_obj)
|
mark_marshalled_obj(obj, soap_obj)
|
||||||
obj.each do |key, value|
|
obj.each do |key, value|
|
||||||
elem = SOAPStruct.new
|
elem = SOAPStruct.new
|
||||||
@ -156,16 +197,71 @@ private
|
|||||||
# ApacheAxis allows only 'item' here.
|
# ApacheAxis allows only 'item' here.
|
||||||
soap_obj.add("item", elem)
|
soap_obj.add("item", elem)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
soap_obj
|
soap_obj
|
||||||
end
|
end
|
||||||
|
|
||||||
def elements2soap(obj, soap_obj, elements)
|
def elements2soap(obj, soap_obj, elements)
|
||||||
elements.each do |element|
|
elements.each do |element|
|
||||||
name = element.name.name
|
name = element.name.name
|
||||||
child_obj = obj.instance_variable_get('@' + name)
|
child_obj = Mapping.get_attribute(obj, name)
|
||||||
soap_obj.add(name, Mapping._obj2soap(child_obj, self, element.type))
|
soap_obj.add(name,
|
||||||
|
Mapping._obj2soap(child_obj, self, element.type || element.name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def any2obj(node, obj_class)
|
||||||
|
unless obj_class
|
||||||
|
typestr = XSD::CodeGen::GenSupport.safeconstname(node.elename.name)
|
||||||
|
obj_class = Mapping.class_from_name(typestr)
|
||||||
|
end
|
||||||
|
if obj_class and obj_class.class_variables.include?('@@schema_element')
|
||||||
|
soap2stubobj(node, obj_class)
|
||||||
|
else
|
||||||
|
Mapping._soap2obj(node, Mapping::DefaultRegistry, obj_class)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def soap2stubobj(node, obj_class)
|
||||||
|
obj = Mapping.create_empty_object(obj_class)
|
||||||
|
unless node.is_a?(SOAPNil)
|
||||||
|
add_elements2stubobj(node, obj)
|
||||||
|
end
|
||||||
|
obj
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_elements2stubobj(node, obj)
|
||||||
|
elements, as_array = schema_element_definition(obj.class)
|
||||||
|
vars = {}
|
||||||
|
node.each do |name, value|
|
||||||
|
if class_name = elements[name]
|
||||||
|
if klass = Mapping.class_from_name(class_name)
|
||||||
|
# klass must be a SOAPBasetype or a class
|
||||||
|
if klass.ancestors.include?(::SOAP::SOAPBasetype)
|
||||||
|
if value.respond_to?(:data)
|
||||||
|
child = klass.new(value.data).data
|
||||||
|
else
|
||||||
|
child = klass.new(nil).data
|
||||||
|
end
|
||||||
|
else
|
||||||
|
child = Mapping._soap2obj(value, self, klass)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
raise MappingError.new("unknown class: #{class_name}")
|
||||||
|
end
|
||||||
|
else # untyped element is treated as anyType.
|
||||||
|
child = Mapping._soap2obj(value, self)
|
||||||
|
end
|
||||||
|
vars[name] = child
|
||||||
|
end
|
||||||
|
Mapping.set_attributes(obj, vars)
|
||||||
|
end
|
||||||
|
|
||||||
|
# it caches @@schema_element. this means that @@schema_element must not be
|
||||||
|
# changed while a lifetime of a WSDLLiteralRegistry.
|
||||||
|
def schema_element_definition(klass)
|
||||||
|
@schema_element_cache[klass] ||= Mapping.schema_element_definition(klass)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# SOAP4R - WSDL literal mapping registry.
|
# SOAP4R - WSDL literal mapping registry.
|
||||||
# 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,48 +10,55 @@ require 'soap/baseData'
|
|||||||
require 'soap/mapping/mapping'
|
require 'soap/mapping/mapping'
|
||||||
require 'soap/mapping/typeMap'
|
require 'soap/mapping/typeMap'
|
||||||
require 'xsd/codegen/gensupport'
|
require 'xsd/codegen/gensupport'
|
||||||
|
require 'xsd/namedelements'
|
||||||
|
|
||||||
|
|
||||||
module SOAP
|
module SOAP
|
||||||
module Mapping
|
module Mapping
|
||||||
|
|
||||||
|
|
||||||
class WSDLLiteralRegistry
|
class WSDLLiteralRegistry < Registry
|
||||||
attr_reader :definedelements
|
attr_reader :definedelements
|
||||||
attr_reader :definedtypes
|
attr_reader :definedtypes
|
||||||
attr_accessor :excn_handler_obj2soap
|
attr_accessor :excn_handler_obj2soap
|
||||||
attr_accessor :excn_handler_soap2obj
|
attr_accessor :excn_handler_soap2obj
|
||||||
|
|
||||||
def initialize(definedelements = nil, definedtypes = nil)
|
def initialize(definedtypes = XSD::NamedElements::Empty,
|
||||||
@definedelements = definedelements
|
definedelements = XSD::NamedElements::Empty)
|
||||||
@definedtypes = definedtypes
|
@definedtypes = definedtypes
|
||||||
@rubytype_factory = RubytypeFactory.new(:allow_original_mapping => false)
|
@definedelements = definedelements
|
||||||
|
@excn_handler_obj2soap = nil
|
||||||
|
@excn_handler_soap2obj = nil
|
||||||
@schema_element_cache = {}
|
@schema_element_cache = {}
|
||||||
|
@schema_attribute_cache = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def obj2soap(obj, qname)
|
def obj2soap(obj, qname)
|
||||||
ret = nil
|
soap_obj = nil
|
||||||
if !@definedelements.nil? && ele = @definedelements[qname]
|
if ele = @definedelements[qname]
|
||||||
ret = _obj2soap(obj, ele)
|
soap_obj = obj2elesoap(obj, ele)
|
||||||
elsif !@definedtypes.nil? && type = @definedtypes[qname]
|
elsif type = @definedtypes[qname]
|
||||||
ret = obj2type(obj, type)
|
soap_obj = obj2typesoap(obj, type)
|
||||||
else
|
else
|
||||||
ret = unknownobj2soap(obj, qname)
|
soap_obj = any2soap(obj, qname)
|
||||||
end
|
end
|
||||||
return ret if ret
|
return soap_obj if soap_obj
|
||||||
if @excn_handler_obj2soap
|
if @excn_handler_obj2soap
|
||||||
ret = @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, self)
|
||||||
}
|
}
|
||||||
return ret if ret
|
return soap_obj if soap_obj
|
||||||
end
|
end
|
||||||
raise MappingError.new("Cannot map #{ obj.class.name } to SOAP/OM.")
|
raise MappingError.new("cannot map #{obj.class.name} as #{qname}")
|
||||||
end
|
end
|
||||||
|
|
||||||
# node should be a SOAPElement
|
# node should be a SOAPElement
|
||||||
def soap2obj(node)
|
def soap2obj(node, obj_class = nil)
|
||||||
|
unless obj_class.nil?
|
||||||
|
raise MappingError.new("must not reach here")
|
||||||
|
end
|
||||||
begin
|
begin
|
||||||
return soapele2obj(node)
|
return any2obj(node)
|
||||||
rescue MappingError
|
rescue MappingError
|
||||||
end
|
end
|
||||||
if @excn_handler_soap2obj
|
if @excn_handler_soap2obj
|
||||||
@ -62,84 +69,136 @@ class WSDLLiteralRegistry
|
|||||||
rescue Exception
|
rescue Exception
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
raise MappingError.new("Cannot map #{ node.type.name } to Ruby object.")
|
raise MappingError.new("cannot map #{node.type.name} to Ruby object")
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def _obj2soap(obj, ele)
|
def obj2elesoap(obj, ele)
|
||||||
o = nil
|
o = nil
|
||||||
if ele.type
|
if ele.type
|
||||||
if type = @definedtypes[ele.type]
|
if type = @definedtypes[ele.type]
|
||||||
o = obj2type(obj, type)
|
o = obj2typesoap(obj, type)
|
||||||
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
|
o.elename = ele.name
|
||||||
elsif ele.local_complextype
|
elsif ele.local_complextype
|
||||||
o = SOAPElement.new(ele.name)
|
o = obj2typesoap(obj, ele.local_complextype)
|
||||||
ele.local_complextype.each_element do |child_ele|
|
o.elename = ele.name
|
||||||
o.add(_obj2soap(Mapping.find_attribute(obj, child_ele.name.name),
|
add_attributes2soap(obj, o)
|
||||||
child_ele))
|
elsif ele.local_simpletype
|
||||||
end
|
o = obj2typesoap(obj, ele.local_simpletype)
|
||||||
|
o.elename = ele.name
|
||||||
else
|
else
|
||||||
raise MappingError.new('Illegal schema?')
|
raise MappingError.new('illegal schema?')
|
||||||
end
|
end
|
||||||
o
|
o
|
||||||
end
|
end
|
||||||
|
|
||||||
def obj2type(obj, type)
|
def obj2typesoap(obj, type)
|
||||||
if type.is_a?(::WSDL::XMLSchema::SimpleType)
|
if type.is_a?(::WSDL::XMLSchema::SimpleType)
|
||||||
simple2soap(obj, type)
|
simpleobj2soap(obj, type)
|
||||||
else
|
else
|
||||||
complex2soap(obj, type)
|
complexobj2soap(obj, type)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def simple2soap(obj, type)
|
def simpleobj2soap(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)
|
type.check_lexical_format(obj)
|
||||||
|
return SOAPNil.new if obj.nil? # ToDo: check nillable.
|
||||||
|
o = base2soap(obj, TypeMap[type.base])
|
||||||
o
|
o
|
||||||
end
|
end
|
||||||
|
|
||||||
def complex2soap(obj, type)
|
def complexobj2soap(obj, type)
|
||||||
o = SOAPElement.new(type.name)
|
o = SOAPElement.new(type.name)
|
||||||
type.each_element do |child_ele|
|
type.each_element do |child_ele|
|
||||||
o.add(_obj2soap(Mapping.find_attribute(obj, child_ele.name.name),
|
child = Mapping.get_attribute(obj, child_ele.name.name)
|
||||||
child_ele))
|
if child.nil?
|
||||||
|
if child_ele.nillable
|
||||||
|
# ToDo: test
|
||||||
|
# add empty element
|
||||||
|
o.add(obj2elesoap(nil))
|
||||||
|
elsif Integer(child_ele.minoccurs) == 0
|
||||||
|
# nothing to do
|
||||||
|
else
|
||||||
|
raise MappingError.new("nil not allowed: #{child_ele.name.name}")
|
||||||
|
end
|
||||||
|
elsif child_ele.map_as_array?
|
||||||
|
child.each do |item|
|
||||||
|
o.add(obj2elesoap(item, child_ele))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
o.add(obj2elesoap(child, child_ele))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
o
|
o
|
||||||
end
|
end
|
||||||
|
|
||||||
def unknownobj2soap(obj, name)
|
def any2soap(obj, qname)
|
||||||
if obj.class.class_variables.include?('@@schema_element')
|
if obj.is_a?(SOAPElement)
|
||||||
ele = SOAPElement.new(name)
|
obj
|
||||||
|
elsif obj.class.class_variables.include?('@@schema_element')
|
||||||
|
stubobj2soap(obj, qname)
|
||||||
|
elsif obj.is_a?(SOAP::Mapping::Object)
|
||||||
|
mappingobj2soap(obj, qname)
|
||||||
|
elsif obj.is_a?(Hash)
|
||||||
|
ele = SOAPElement.from_obj(obj)
|
||||||
|
ele.elename = qname
|
||||||
|
ele
|
||||||
|
else
|
||||||
|
# expected to be a basetype or an anyType.
|
||||||
|
# SOAPStruct, etc. is used instead of SOAPElement.
|
||||||
|
begin
|
||||||
|
ele = Mapping.obj2soap(obj)
|
||||||
|
ele.elename = qname
|
||||||
|
ele
|
||||||
|
rescue MappingError
|
||||||
|
ele = SOAPElement.new(qname, obj.to_s)
|
||||||
|
end
|
||||||
|
if obj.respond_to?(:__xmlattr)
|
||||||
|
obj.__xmlattr.each do |key, value|
|
||||||
|
ele.extraattr[key] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ele
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stubobj2soap(obj, qname)
|
||||||
|
ele = SOAPElement.new(qname)
|
||||||
add_elements2soap(obj, ele)
|
add_elements2soap(obj, ele)
|
||||||
add_attributes2soap(obj, ele)
|
add_attributes2soap(obj, ele)
|
||||||
ele
|
ele
|
||||||
elsif obj.is_a?(Hash)
|
|
||||||
ele = SOAPElement.from_obj(obj)
|
|
||||||
ele.elename = name
|
|
||||||
ele
|
|
||||||
else # expected to be a basetype or an anyType.
|
|
||||||
o = Mapping.obj2soap(obj)
|
|
||||||
o.elename = name
|
|
||||||
o
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def mappingobj2soap(obj, qname)
|
||||||
|
ele = SOAPElement.new(qname)
|
||||||
|
obj.__xmlele.each do |key, value|
|
||||||
|
if value.is_a?(::Array)
|
||||||
|
value.each do |item|
|
||||||
|
ele.add(obj2soap(item, key))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
ele.add(obj2soap(value, key))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
obj.__xmlattr.each do |key, value|
|
||||||
|
ele.extraattr[key] = value
|
||||||
|
end
|
||||||
|
ele
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_elements2soap(obj, ele)
|
def add_elements2soap(obj, ele)
|
||||||
elements, as_array = schema_element_definition(obj.class)
|
elements, as_array = schema_element_definition(obj.class)
|
||||||
|
if elements
|
||||||
elements.each do |elename, type|
|
elements.each do |elename, type|
|
||||||
child = Mapping.find_attribute(obj, elename)
|
child = Mapping.get_attribute(obj, elename)
|
||||||
name = ::XSD::QName.new(nil, elename)
|
unless child.nil?
|
||||||
|
name = XSD::QName.new(nil, elename)
|
||||||
if as_array.include?(type)
|
if as_array.include?(type)
|
||||||
child.each do |item|
|
child.each do |item|
|
||||||
ele.add(obj2soap(item, name))
|
ele.add(obj2soap(item, name))
|
||||||
@ -149,21 +208,25 @@ private
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def add_attributes2soap(obj, ele)
|
def add_attributes2soap(obj, ele)
|
||||||
attributes = schema_attribute_definition(obj.class)
|
attributes = schema_attribute_definition(obj.class)
|
||||||
attributes.each do |attrname, param|
|
if attributes
|
||||||
attr = Mapping.find_attribute(obj, 'attr_' + attrname)
|
attributes.each do |qname, param|
|
||||||
ele.extraattr[attrname] = attr
|
attr = obj.__send__('xmlattr_' +
|
||||||
|
XSD::CodeGen::GenSupport.safevarname(qname.name))
|
||||||
|
ele.extraattr[qname] = attr
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
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) ?
|
soap_obj = type.new(XSD::Charset.is_ces(obj, $KCODE) ?
|
||||||
::XSD::Charset.encoding_conv(obj, $KCODE, ::XSD::Charset.encoding) :
|
XSD::Charset.encoding_conv(obj, $KCODE, XSD::Charset.encoding) : obj)
|
||||||
obj)
|
|
||||||
else
|
else
|
||||||
soap_obj = type.new(obj)
|
soap_obj = type.new(obj)
|
||||||
end
|
end
|
||||||
@ -176,35 +239,41 @@ private
|
|||||||
end
|
end
|
||||||
klass = ::SOAP::Mapping::Object
|
klass = ::SOAP::Mapping::Object
|
||||||
obj = klass.new
|
obj = klass.new
|
||||||
node.each do |name, value|
|
|
||||||
obj.__soap_set_property(name, Mapping.soap2obj(value))
|
|
||||||
end
|
|
||||||
obj
|
obj
|
||||||
end
|
end
|
||||||
|
|
||||||
def soapele2obj(node, obj_class = nil)
|
def any2obj(node, obj_class = nil)
|
||||||
unless obj_class
|
unless obj_class
|
||||||
typestr = ::XSD::CodeGen::GenSupport.safeconstname(node.elename.name)
|
typestr = XSD::CodeGen::GenSupport.safeconstname(node.elename.name)
|
||||||
obj_class = Mapping.class_from_name(typestr)
|
obj_class = Mapping.class_from_name(typestr)
|
||||||
end
|
end
|
||||||
if obj_class and obj_class.class_variables.include?('@@schema_element')
|
if obj_class and obj_class.class_variables.include?('@@schema_element')
|
||||||
soapele2definedobj(node, obj_class)
|
soapele2stubobj(node, obj_class)
|
||||||
elsif node.is_a?(SOAPElement)
|
elsif node.is_a?(SOAPElement) or node.is_a?(SOAPStruct)
|
||||||
node.to_obj
|
# SOAPArray for literal?
|
||||||
|
soapele2plainobj(node)
|
||||||
else
|
else
|
||||||
result, obj = @rubytype_factory.soap2obj(nil, node, nil, self)
|
obj = Mapping._soap2obj(node, Mapping::DefaultRegistry, obj_class)
|
||||||
|
add_attributes2plainobj(node, obj)
|
||||||
obj
|
obj
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def soapele2definedobj(node, obj_class)
|
def soapele2stubobj(node, obj_class)
|
||||||
obj = Mapping.create_empty_object(obj_class)
|
obj = Mapping.create_empty_object(obj_class)
|
||||||
add_elements2obj(node, obj)
|
add_elements2stubobj(node, obj)
|
||||||
add_attributes2obj(node, obj)
|
add_attributes2stubobj(node, obj)
|
||||||
obj
|
obj
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_elements2obj(node, obj)
|
def soapele2plainobj(node)
|
||||||
|
obj = anytype2obj(node)
|
||||||
|
add_elements2plainobj(node, obj)
|
||||||
|
add_attributes2plainobj(node, obj)
|
||||||
|
obj
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_elements2stubobj(node, obj)
|
||||||
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|
|
||||||
@ -217,13 +286,13 @@ private
|
|||||||
child = klass.new(nil).data
|
child = klass.new(nil).data
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
child = soapele2obj(value, klass)
|
child = any2obj(value, klass)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise MappingError.new("Unknown class: #{class_name}")
|
raise MappingError.new("unknown class: #{class_name}")
|
||||||
end
|
end
|
||||||
else # untyped element is treated as anyType.
|
else # untyped element is treated as anyType.
|
||||||
child = anytype2obj(value)
|
child = any2obj(value)
|
||||||
end
|
end
|
||||||
if as_array.include?(class_name)
|
if as_array.include?(class_name)
|
||||||
(vars[name] ||= []) << child
|
(vars[name] ||= []) << child
|
||||||
@ -231,15 +300,14 @@ private
|
|||||||
vars[name] = child
|
vars[name] = child
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Mapping.set_instance_vars(obj, vars)
|
Mapping.set_attributes(obj, vars)
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_attributes2obj(node, obj)
|
def add_attributes2stubobj(node, obj)
|
||||||
Mapping.set_instance_vars(obj, {'__soap_attribute' => {}})
|
if attributes = schema_attribute_definition(obj.class)
|
||||||
vars = {}
|
define_xmlattr(obj)
|
||||||
attributes = schema_attribute_definition(obj.class)
|
attributes.each do |qname, class_name|
|
||||||
attributes.each do |attrname, class_name|
|
attr = node.extraattr[qname]
|
||||||
attr = node.extraattr[::XSD::QName.new(nil, attrname)]
|
|
||||||
next if attr.nil? or attr.empty?
|
next if attr.nil? or attr.empty?
|
||||||
klass = Mapping.class_from_name(class_name)
|
klass = Mapping.class_from_name(class_name)
|
||||||
if klass.ancestors.include?(::SOAP::SOAPBasetype)
|
if klass.ancestors.include?(::SOAP::SOAPBasetype)
|
||||||
@ -247,32 +315,77 @@ private
|
|||||||
else
|
else
|
||||||
child = attr
|
child = attr
|
||||||
end
|
end
|
||||||
vars['attr_' + attrname] = child
|
obj.__xmlattr[qname] = child
|
||||||
|
define_xmlattr_accessor(obj, qname)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_elements2plainobj(node, obj)
|
||||||
|
node.each do |name, value|
|
||||||
|
obj.__add_xmlele_value(XSD::QName.new(nil, name), any2obj(value))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_attributes2plainobj(node, obj)
|
||||||
|
return if node.extraattr.empty?
|
||||||
|
define_xmlattr(obj)
|
||||||
|
node.extraattr.each do |qname, value|
|
||||||
|
obj.__xmlattr[qname] = value
|
||||||
|
define_xmlattr_accessor(obj, qname)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if RUBY_VERSION > "1.7.0"
|
||||||
|
def define_xmlattr_accessor(obj, qname)
|
||||||
|
name = XSD::CodeGen::GenSupport.safemethodname(qname.name)
|
||||||
|
Mapping.define_attr_accessor(obj, 'xmlattr_' + name,
|
||||||
|
proc { @__xmlattr[qname] },
|
||||||
|
proc { |value| @__xmlattr[qname] = value })
|
||||||
|
end
|
||||||
|
else
|
||||||
|
def define_xmlattr_accessor(obj, qname)
|
||||||
|
name = XSD::CodeGen::GenSupport.safemethodname(qname.name)
|
||||||
|
obj.instance_eval <<-EOS
|
||||||
|
def #{name}
|
||||||
|
@__xmlattr[#{qname.dump}]
|
||||||
|
end
|
||||||
|
|
||||||
|
def #{name}=(value)
|
||||||
|
@__xmlattr[#{qname.dump}] = value
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if RUBY_VERSION > "1.7.0"
|
||||||
|
def define_xmlattr(obj)
|
||||||
|
obj.instance_variable_set('@__xmlattr', {})
|
||||||
|
unless obj.respond_to?(:__xmlattr)
|
||||||
|
Mapping.define_attr_accessor(obj, :__xmlattr, proc { @__xmlattr })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
def define_xmlattr(obj)
|
||||||
|
obj.instance_variable_set('@__xmlattr', {})
|
||||||
|
unless obj.respond_to?(:__xmlattr)
|
||||||
|
obj.instance_eval <<-EOS
|
||||||
|
def __xmlattr
|
||||||
|
@__xmlattr
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
end
|
||||||
end
|
end
|
||||||
Mapping.set_instance_vars(obj, vars)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# it caches @@schema_element. this means that @@schema_element must not be
|
# it caches @@schema_element. this means that @@schema_element must not be
|
||||||
# changed while a lifetime of a WSDLLiteralRegistry.
|
# changed while a lifetime of a WSDLLiteralRegistry.
|
||||||
def schema_element_definition(klass)
|
def schema_element_definition(klass)
|
||||||
if @schema_element_cache.key?(klass)
|
@schema_element_cache[klass] ||= Mapping.schema_element_definition(klass)
|
||||||
return @schema_element_cache[klass]
|
|
||||||
end
|
|
||||||
elements = {}
|
|
||||||
as_array = []
|
|
||||||
klass.class_eval('@@schema_element').each do |name, class_name|
|
|
||||||
if /\[\]$/ =~ class_name
|
|
||||||
class_name = class_name.sub(/\[\]$/, '')
|
|
||||||
as_array << class_name
|
|
||||||
end
|
|
||||||
elements[name] = class_name
|
|
||||||
end
|
|
||||||
@schema_element_cache[klass] = [elements, as_array]
|
|
||||||
return @schema_element_cache[klass]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def schema_attribute_definition(klass)
|
def schema_attribute_definition(klass)
|
||||||
attributes = klass.class_eval('@@schema_attribute')
|
@schema_attribute_cache[klass] ||= Mapping.schema_attribute_definition(klass)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -14,8 +14,9 @@ module SOAP
|
|||||||
|
|
||||||
|
|
||||||
module Marshal
|
module Marshal
|
||||||
# Trying xsd:dateTime data to be recovered as aTime. aDateTime if it fails.
|
# Trying xsd:dateTime data to be recovered as aTime.
|
||||||
MarshalMappingRegistry = Mapping::Registry.new(:allow_original_mapping => true)
|
MarshalMappingRegistry = Mapping::Registry.new(
|
||||||
|
:allow_original_mapping => true)
|
||||||
MarshalMappingRegistry.add(
|
MarshalMappingRegistry.add(
|
||||||
Time,
|
Time,
|
||||||
::SOAP::SOAPDateTime,
|
::SOAP::SOAPDateTime,
|
||||||
|
@ -43,18 +43,23 @@ class NetHttpClient
|
|||||||
raise NotImplementedError.new("not supported for now")
|
raise NotImplementedError.new("not supported for now")
|
||||||
end
|
end
|
||||||
|
|
||||||
def proxy=(proxy_str)
|
def proxy=(proxy)
|
||||||
if proxy_str.nil?
|
if proxy.nil?
|
||||||
@proxy = nil
|
@proxy = nil
|
||||||
else
|
else
|
||||||
@proxy = URI.parse(proxy_str)
|
if proxy.is_a?(URI)
|
||||||
|
@proxy = proxy
|
||||||
|
else
|
||||||
|
@proxy = URI.parse(proxy)
|
||||||
|
end
|
||||||
if @proxy.scheme == nil or @proxy.scheme.downcase != 'http' or
|
if @proxy.scheme == nil or @proxy.scheme.downcase != 'http' or
|
||||||
@proxy.host == nil or @proxy.port == nil
|
@proxy.host == nil or @proxy.port == nil
|
||||||
raise ArgumentError.new("unsupported proxy `#{proxy_str}'")
|
raise ArgumentError.new("unsupported proxy `#{proxy}'")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
reset_all
|
||||||
@proxy
|
@proxy
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def set_basic_auth(uri, user_id, passwd)
|
def set_basic_auth(uri, user_id, passwd)
|
||||||
# net/http does not handle url.
|
# net/http does not handle url.
|
||||||
@ -79,7 +84,9 @@ class NetHttpClient
|
|||||||
end
|
end
|
||||||
|
|
||||||
def post(url, req_body, header = {})
|
def post(url, req_body, header = {})
|
||||||
|
unless url.is_a?(URI)
|
||||||
url = URI.parse(url)
|
url = URI.parse(url)
|
||||||
|
end
|
||||||
extra = header.dup
|
extra = header.dup
|
||||||
extra['User-Agent'] = @agent if @agent
|
extra['User-Agent'] = @agent if @agent
|
||||||
res = start(url) { |http|
|
res = start(url) { |http|
|
||||||
@ -89,7 +96,9 @@ class NetHttpClient
|
|||||||
end
|
end
|
||||||
|
|
||||||
def get_content(url, header = {})
|
def get_content(url, header = {})
|
||||||
|
unless url.is_a?(URI)
|
||||||
url = URI.parse(url)
|
url = URI.parse(url)
|
||||||
|
end
|
||||||
extra = header.dup
|
extra = header.dup
|
||||||
extra['User-Agent'] = @agent if @agent
|
extra['User-Agent'] = @agent if @agent
|
||||||
res = start(url) { |http|
|
res = start(url) { |http|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# SOAP4R - CGI stub library
|
# SOAP4R - CGI/mod_ruby stub library
|
||||||
# Copyright (C) 2001, 2003, 2004 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 @@ require 'soap/streamHandler'
|
|||||||
require 'webrick/httpresponse'
|
require 'webrick/httpresponse'
|
||||||
require 'webrick/httpstatus'
|
require 'webrick/httpstatus'
|
||||||
require 'logger'
|
require 'logger'
|
||||||
require 'soap/rpc/router'
|
require 'soap/rpc/soaplet'
|
||||||
|
|
||||||
|
|
||||||
module SOAP
|
module SOAP
|
||||||
@ -26,57 +26,51 @@ module RPC
|
|||||||
#
|
#
|
||||||
class CGIStub < Logger::Application
|
class CGIStub < Logger::Application
|
||||||
include SOAP
|
include SOAP
|
||||||
|
include WEBrick
|
||||||
# There is a client which does not accept the media-type which is defined in
|
|
||||||
# SOAP spec.
|
|
||||||
attr_accessor :mediatype
|
|
||||||
|
|
||||||
class CGIError < Error; end
|
|
||||||
|
|
||||||
class SOAPRequest
|
class SOAPRequest
|
||||||
ALLOWED_LENGTH = 1024 * 1024
|
attr_reader :body
|
||||||
|
|
||||||
def initialize(stream = $stdin)
|
def [](var); end
|
||||||
@method = ENV['REQUEST_METHOD']
|
|
||||||
@size = ENV['CONTENT_LENGTH'].to_i || 0
|
def meta_vars; end
|
||||||
@contenttype = ENV['CONTENT_TYPE']
|
|
||||||
@soapaction = ENV['HTTP_SOAPAction']
|
|
||||||
@source = stream
|
|
||||||
@body = nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def init
|
class SOAPStdinRequest < SOAPRequest
|
||||||
validate
|
attr_reader :body
|
||||||
@body = @source.read(@size)
|
|
||||||
self
|
def initialize(stream)
|
||||||
|
size = ENV['CONTENT_LENGTH'].to_i || 0
|
||||||
|
@body = stream.read(size)
|
||||||
end
|
end
|
||||||
|
|
||||||
def dump
|
def [](var)
|
||||||
@body.dup
|
ENV[var.gsub(/-/, '_').upcase]
|
||||||
end
|
end
|
||||||
|
|
||||||
def soapaction
|
def meta_vars
|
||||||
@soapaction
|
{
|
||||||
|
'HTTP_SOAPACTION' => ENV['HTTP_SOAPAction']
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def contenttype
|
class SOAPFCGIRequest < SOAPRequest
|
||||||
@contenttype
|
attr_reader :body
|
||||||
|
|
||||||
|
def initialize(request)
|
||||||
|
@request = request
|
||||||
|
@body = @request.in.read
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_s
|
def [](var)
|
||||||
"method: #{ @method }, size: #{ @size }"
|
@request.env[var.gsub(/-/, '_').upcase]
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
def meta_vars
|
||||||
|
{
|
||||||
def validate # raise CGIError
|
'HTTP_SOAPACTION' => @request.env['HTTP_SOAPAction']
|
||||||
if @method != 'POST'
|
}
|
||||||
raise CGIError.new("Method '#{ @method }' not allowed.")
|
|
||||||
end
|
|
||||||
|
|
||||||
if @size > ALLOWED_LENGTH
|
|
||||||
raise CGIError.new("Content-length too long.")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -85,33 +79,14 @@ class CGIStub < Logger::Application
|
|||||||
set_log(STDERR)
|
set_log(STDERR)
|
||||||
self.level = ERROR
|
self.level = ERROR
|
||||||
@default_namespace = default_namespace
|
@default_namespace = default_namespace
|
||||||
@router = SOAP::RPC::Router.new(appname)
|
|
||||||
@remote_user = ENV['REMOTE_USER'] || 'anonymous'
|
|
||||||
@remote_host = ENV['REMOTE_HOST'] || ENV['REMOTE_ADDR'] || 'unknown'
|
@remote_host = ENV['REMOTE_HOST'] || ENV['REMOTE_ADDR'] || 'unknown'
|
||||||
@request = nil
|
@router = ::SOAP::RPC::Router.new(self.class.name)
|
||||||
@response = nil
|
@soaplet = ::SOAP::RPC::SOAPlet.new(@router)
|
||||||
@mediatype = MediaType
|
|
||||||
on_init
|
on_init
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_rpc_servant(obj, namespace = @default_namespace, soapaction = nil)
|
|
||||||
RPC.defined_methods(obj).each do |name|
|
|
||||||
qname = XSD::QName.new(namespace, name)
|
|
||||||
param_size = obj.method(name).arity.abs
|
|
||||||
params = (1..param_size).collect { |i| "p#{i}" }
|
|
||||||
param_def = SOAP::RPC::SOAPMethod.create_param_def(params)
|
|
||||||
@router.add_method(obj, qname, soapaction, name, param_def)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
alias add_servant add_rpc_servant
|
|
||||||
|
|
||||||
def add_rpc_headerhandler(obj)
|
|
||||||
@router.headerhandler << obj
|
|
||||||
end
|
|
||||||
alias add_headerhandler add_rpc_headerhandler
|
|
||||||
|
|
||||||
def on_init
|
def on_init
|
||||||
# Override this method in derived class to call 'add_method' to add methods.
|
# do extra initialization in a derived class if needed.
|
||||||
end
|
end
|
||||||
|
|
||||||
def mapping_registry
|
def mapping_registry
|
||||||
@ -122,83 +97,108 @@ class CGIStub < Logger::Application
|
|||||||
@router.mapping_registry = value
|
@router.mapping_registry = value
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_method(receiver, name, *param)
|
def generate_explicit_type
|
||||||
add_method_with_namespace_as(@default_namespace, receiver,
|
@router.generate_explicit_type
|
||||||
name, name, *param)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_method_as(receiver, name, name_as, *param)
|
def generate_explicit_type=(generate_explicit_type)
|
||||||
add_method_with_namespace_as(@default_namespace, receiver,
|
@router.generate_explicit_type = generate_explicit_type
|
||||||
name, name_as, *param)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_method_with_namespace(namespace, receiver, name, *param)
|
# servant entry interface
|
||||||
add_method_with_namespace_as(namespace, receiver, name, name, *param)
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_method_with_namespace_as(namespace, receiver, name, name_as, *param)
|
def add_rpc_servant(obj, namespace = @default_namespace)
|
||||||
param_def = if param.size == 1 and param[0].is_a?(Array)
|
@router.add_rpc_servant(obj, namespace)
|
||||||
param[0]
|
|
||||||
else
|
|
||||||
SOAP::RPC::SOAPMethod.create_param_def(param)
|
|
||||||
end
|
end
|
||||||
|
alias add_servant add_rpc_servant
|
||||||
|
|
||||||
|
def add_headerhandler(obj)
|
||||||
|
@router.add_headerhandler(obj)
|
||||||
|
end
|
||||||
|
alias add_rpc_headerhandler add_headerhandler
|
||||||
|
|
||||||
|
# method entry interface
|
||||||
|
|
||||||
|
def add_rpc_method(obj, name, *param)
|
||||||
|
add_rpc_method_with_namespace_as(@default_namespace, obj, name, name, *param)
|
||||||
|
end
|
||||||
|
alias add_method add_rpc_method
|
||||||
|
|
||||||
|
def add_rpc_method_as(obj, name, name_as, *param)
|
||||||
|
add_rpc_method_with_namespace_as(@default_namespace, obj, name, name_as, *param)
|
||||||
|
end
|
||||||
|
alias add_method_as add_rpc_method_as
|
||||||
|
|
||||||
|
def add_rpc_method_with_namespace(namespace, obj, name, *param)
|
||||||
|
add_rpc_method_with_namespace_as(namespace, obj, name, name, *param)
|
||||||
|
end
|
||||||
|
alias add_method_with_namespace add_rpc_method_with_namespace
|
||||||
|
|
||||||
|
def add_rpc_method_with_namespace_as(namespace, obj, name, name_as, *param)
|
||||||
qname = XSD::QName.new(namespace, name_as)
|
qname = XSD::QName.new(namespace, name_as)
|
||||||
@router.add_method(receiver, qname, nil, name, param_def)
|
soapaction = nil
|
||||||
|
param_def = SOAPMethod.derive_rpc_param_def(obj, name, *param)
|
||||||
|
@router.add_rpc_operation(obj, qname, soapaction, name, param_def)
|
||||||
|
end
|
||||||
|
alias add_method_with_namespace_as add_rpc_method_with_namespace_as
|
||||||
|
|
||||||
|
def add_rpc_operation(receiver, qname, soapaction, name, param_def, opt = {})
|
||||||
|
@router.add_rpc_operation(receiver, qname, soapaction, name, param_def, opt)
|
||||||
end
|
end
|
||||||
|
|
||||||
def route(conn_data)
|
def add_document_operation(receiver, soapaction, name, param_def, opt = {})
|
||||||
@router.route(conn_data)
|
@router.add_document_operation(receiver, soapaction, name, param_def, opt)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_fault_response(e)
|
def set_fcgi_request(request)
|
||||||
@router.create_fault_response(e)
|
@fcgi = request
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
HTTPVersion = WEBrick::HTTPVersion.new('1.0') # dummy; ignored
|
||||||
|
|
||||||
def run
|
def run
|
||||||
prologue
|
res = WEBrick::HTTPResponse.new({:HTTPVersion => HTTPVersion})
|
||||||
|
|
||||||
httpversion = WEBrick::HTTPVersion.new('1.0')
|
|
||||||
@response = WEBrick::HTTPResponse.new({:HTTPVersion => httpversion})
|
|
||||||
conn_data = nil
|
|
||||||
begin
|
begin
|
||||||
@log.info { "Received a request from '#{ @remote_user }@#{ @remote_host }'." }
|
@log.info { "received a request from '#{ @remote_host }'" }
|
||||||
# SOAP request parsing.
|
if @fcgi
|
||||||
@request = SOAPRequest.new.init
|
req = SOAPFCGIRequest.new(@fcgi)
|
||||||
@response['Status'] = 200
|
else
|
||||||
conn_data = ::SOAP::StreamHandler::ConnectionData.new
|
req = SOAPStdinRequest.new($stdin)
|
||||||
conn_data.receive_string = @request.dump
|
|
||||||
conn_data.receive_contenttype = @request.contenttype
|
|
||||||
@log.debug { "XML Request: #{conn_data.receive_string}" }
|
|
||||||
conn_data = route(conn_data)
|
|
||||||
@log.debug { "XML Response: #{conn_data.send_string}" }
|
|
||||||
if conn_data.is_fault
|
|
||||||
@response['Status'] = 500
|
|
||||||
end
|
end
|
||||||
@response['Cache-Control'] = 'private'
|
@soaplet.do_POST(req, res)
|
||||||
@response.body = conn_data.send_string
|
rescue HTTPStatus::EOFError, HTTPStatus::RequestTimeout => ex
|
||||||
@response['content-type'] = conn_data.send_contenttype
|
res.set_error(ex)
|
||||||
rescue Exception
|
rescue HTTPStatus::Error => ex
|
||||||
conn_data = create_fault_response($!)
|
res.set_error(ex)
|
||||||
@response['Cache-Control'] = 'private'
|
rescue HTTPStatus::Status => ex
|
||||||
@response['Status'] = 500
|
res.status = ex.code
|
||||||
@response.body = conn_data.send_string
|
rescue StandardError, NameError => ex # for Ruby 1.6
|
||||||
@response['content-type'] = conn_data.send_contenttype || @mediatype
|
res.set_error(ex, true)
|
||||||
ensure
|
ensure
|
||||||
|
if defined?(MOD_RUBY)
|
||||||
|
r = Apache.request
|
||||||
|
r.status = res.status
|
||||||
|
r.content_type = res.content_type
|
||||||
|
r.send_http_header
|
||||||
|
buf = res.body
|
||||||
|
else
|
||||||
buf = ''
|
buf = ''
|
||||||
@response.send_response(buf)
|
res.send_response(buf)
|
||||||
buf.sub!(/^[^\r]+\r\n/, '') # Trim status line.
|
buf.sub!(/^[^\r]+\r\n/, '') # Trim status line.
|
||||||
@log.debug { "SOAP CGI Response:\n#{ buf }" }
|
|
||||||
print buf
|
|
||||||
epilogue
|
|
||||||
end
|
end
|
||||||
|
@log.debug { "SOAP CGI Response:\n#{ buf }" }
|
||||||
|
if @fcgi
|
||||||
|
@fcgi.out.print buf
|
||||||
|
@fcgi.finish
|
||||||
|
@fcgi = nil
|
||||||
|
else
|
||||||
|
print buf
|
||||||
|
end
|
||||||
|
end
|
||||||
0
|
0
|
||||||
end
|
end
|
||||||
|
|
||||||
def prologue; end
|
|
||||||
def epilogue; end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# SOAP4R - SOAP RPC driver
|
# SOAP4R - SOAP RPC driver
|
||||||
# Copyright (C) 2000, 2001, 2003, 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 2000, 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;
|
||||||
@ -22,32 +22,55 @@ module RPC
|
|||||||
|
|
||||||
|
|
||||||
class Driver
|
class Driver
|
||||||
class EmptyResponseError < Error; end
|
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
|
if RUBY_VERSION >= "1.7.0"
|
||||||
def __attr_proxy(symbol, assignable = false)
|
def __attr_proxy(symbol, assignable = false)
|
||||||
name = symbol.to_s
|
name = symbol.to_s
|
||||||
self.__send__(:define_method, name, proc {
|
self.__send__(:define_method, name, proc {
|
||||||
@servant.__send__(name)
|
@proxy.__send__(name)
|
||||||
})
|
})
|
||||||
if assignable
|
if assignable
|
||||||
self.__send__(:define_method, name + '=', proc { |rhs|
|
self.__send__(:define_method, name + '=', proc { |rhs|
|
||||||
@servant.__send__(name + '=', rhs)
|
@proxy.__send__(name + '=', rhs)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
def __attr_proxy(symbol, assignable = false)
|
||||||
|
name = symbol.to_s
|
||||||
|
module_eval <<-EOS
|
||||||
|
def #{name}
|
||||||
|
@proxy.#{name}
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
if assignable
|
||||||
|
module_eval <<-EOS
|
||||||
|
def #{name}=(value)
|
||||||
|
@proxy.#{name} = value
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
__attr_proxy :options
|
|
||||||
__attr_proxy :headerhandler
|
|
||||||
__attr_proxy :streamhandler
|
|
||||||
__attr_proxy :test_loopback_response
|
|
||||||
__attr_proxy :endpoint_url, true
|
__attr_proxy :endpoint_url, true
|
||||||
__attr_proxy :mapping_registry, true
|
__attr_proxy :mapping_registry, true
|
||||||
__attr_proxy :soapaction, true
|
|
||||||
__attr_proxy :default_encodingstyle, true
|
__attr_proxy :default_encodingstyle, true
|
||||||
__attr_proxy :generate_explicit_type, true
|
__attr_proxy :generate_explicit_type, true
|
||||||
__attr_proxy :allow_unqualified_element, true
|
__attr_proxy :allow_unqualified_element, true
|
||||||
|
__attr_proxy :headerhandler
|
||||||
|
__attr_proxy :streamhandler
|
||||||
|
__attr_proxy :test_loopback_response
|
||||||
|
__attr_proxy :reset_stream
|
||||||
|
|
||||||
|
attr_reader :proxy
|
||||||
|
attr_reader :options
|
||||||
|
attr_accessor :soapaction
|
||||||
|
|
||||||
|
def inspect
|
||||||
|
"#<#{self.class}:#{@proxy.inspect}>"
|
||||||
|
end
|
||||||
|
|
||||||
def httpproxy
|
def httpproxy
|
||||||
options["protocol.http.proxy"]
|
options["protocol.http.proxy"]
|
||||||
@ -81,10 +104,12 @@ class Driver
|
|||||||
options["protocol.wiredump_file_base"] = wiredump_file_base
|
options["protocol.wiredump_file_base"] = wiredump_file_base
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(endpoint_url, namespace, soapaction = nil)
|
def initialize(endpoint_url, namespace = nil, soapaction = nil)
|
||||||
@servant = Servant__.new(self, endpoint_url, namespace)
|
@namespace = namespace
|
||||||
@servant.soapaction = soapaction
|
@soapaction = soapaction
|
||||||
@proxy = @servant.proxy
|
@options = setup_options
|
||||||
|
@wiredump_file_base = nil
|
||||||
|
@proxy = Proxy.new(endpoint_url, @soapaction, @options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def loadproperty(propertyname)
|
def loadproperty(propertyname)
|
||||||
@ -93,28 +118,23 @@ class Driver
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def inspect
|
|
||||||
"#<#{self.class}:#{@servant.inspect}>"
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_rpc_method(name, *params)
|
def add_rpc_method(name, *params)
|
||||||
param_def = create_rpc_param_def(params)
|
add_rpc_method_with_soapaction_as(name, name, @soapaction, *params)
|
||||||
@servant.add_rpc_method(name, @servant.soapaction, name, param_def)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_rpc_method_as(name, name_as, *params)
|
def add_rpc_method_as(name, name_as, *params)
|
||||||
param_def = create_rpc_param_def(params)
|
add_rpc_method_with_soapaction_as(name, name_as, @soapaction, *params)
|
||||||
@servant.add_rpc_method(name_as, @servant.soapaction, name, param_def)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_rpc_method_with_soapaction(name, soapaction, *params)
|
def add_rpc_method_with_soapaction(name, soapaction, *params)
|
||||||
param_def = create_rpc_param_def(params)
|
add_rpc_method_with_soapaction_as(name, name, soapaction, *params)
|
||||||
@servant.add_rpc_method(name, soapaction, name, param_def)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_rpc_method_with_soapaction_as(name, name_as, soapaction, *params)
|
def add_rpc_method_with_soapaction_as(name, name_as, soapaction, *params)
|
||||||
param_def = create_rpc_param_def(params)
|
param_def = SOAPMethod.create_rpc_param_def(params)
|
||||||
@servant.add_rpc_method(name_as, soapaction, name, param_def)
|
qname = XSD::QName.new(@namespace, name_as)
|
||||||
|
@proxy.add_rpc_method(qname, soapaction, name, param_def)
|
||||||
|
add_rpc_method_interface(name, param_def)
|
||||||
end
|
end
|
||||||
|
|
||||||
# add_method is for shortcut of typical rpc/encoded method definition.
|
# add_method is for shortcut of typical rpc/encoded method definition.
|
||||||
@ -123,138 +143,20 @@ class Driver
|
|||||||
alias add_method_with_soapaction add_rpc_method_with_soapaction
|
alias add_method_with_soapaction add_rpc_method_with_soapaction
|
||||||
alias add_method_with_soapaction_as add_rpc_method_with_soapaction_as
|
alias add_method_with_soapaction_as add_rpc_method_with_soapaction_as
|
||||||
|
|
||||||
def add_document_method(name, req_qname, res_qname)
|
def add_document_method(name, soapaction, req_qname, res_qname)
|
||||||
param_def = create_document_param_def(name, req_qname, res_qname)
|
param_def = SOAPMethod.create_doc_param_def(req_qname, res_qname)
|
||||||
@servant.add_document_method(name, @servant.soapaction, name, param_def)
|
@proxy.add_document_method(soapaction, name, param_def)
|
||||||
|
add_document_method_interface(name, param_def)
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_document_method_as(name, name_as, req_qname, res_qname)
|
def add_rpc_operation(qname, soapaction, name, param_def, opt = {})
|
||||||
param_def = create_document_param_def(name, req_qname, res_qname)
|
@proxy.add_rpc_operation(qname, soapaction, name, param_def, opt)
|
||||||
@servant.add_document_method(name_as, @servant.soapaction, name, param_def)
|
add_rpc_method_interface(name, param_def)
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_document_method_with_soapaction(name, soapaction, req_qname,
|
def add_document_operation(soapaction, name, param_def, opt = {})
|
||||||
res_qname)
|
@proxy.add_document_operation(soapaction, name, param_def, opt)
|
||||||
param_def = create_document_param_def(name, req_qname, res_qname)
|
add_document_method_interface(name, param_def)
|
||||||
@servant.add_document_method(name, soapaction, name, param_def)
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_document_method_with_soapaction_as(name, name_as, soapaction,
|
|
||||||
req_qname, res_qname)
|
|
||||||
param_def = create_document_param_def(name, req_qname, res_qname)
|
|
||||||
@servant.add_document_method(name_as, soapaction, name, param_def)
|
|
||||||
end
|
|
||||||
|
|
||||||
def reset_stream
|
|
||||||
@servant.reset_stream
|
|
||||||
end
|
|
||||||
|
|
||||||
def invoke(headers, body)
|
|
||||||
@servant.invoke(headers, body)
|
|
||||||
end
|
|
||||||
|
|
||||||
def call(name, *params)
|
|
||||||
@servant.call(name, *params)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def create_rpc_param_def(params)
|
|
||||||
if params.size == 1 and params[0].is_a?(Array)
|
|
||||||
params[0]
|
|
||||||
else
|
|
||||||
SOAPMethod.create_param_def(params)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_document_param_def(name, req_qname, res_qname)
|
|
||||||
[
|
|
||||||
['input', name, [nil, req_qname.namespace, req_qname.name]],
|
|
||||||
['output', name, [nil, res_qname.namespace, res_qname.name]]
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_rpc_method_interface(name, param_def)
|
|
||||||
@servant.add_rpc_method_interface(name, param_def)
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_document_method_interface(name, paramname)
|
|
||||||
@servant.add_document_method_interface(name, paramname)
|
|
||||||
end
|
|
||||||
|
|
||||||
class Servant__
|
|
||||||
attr_reader :proxy
|
|
||||||
attr_reader :options
|
|
||||||
attr_accessor :soapaction
|
|
||||||
|
|
||||||
def initialize(host, endpoint_url, namespace)
|
|
||||||
@host = host
|
|
||||||
@namespace = namespace
|
|
||||||
@soapaction = nil
|
|
||||||
@options = setup_options
|
|
||||||
@wiredump_file_base = nil
|
|
||||||
@endpoint_url = endpoint_url
|
|
||||||
@proxy = Proxy.new(endpoint_url, @soapaction, @options)
|
|
||||||
end
|
|
||||||
|
|
||||||
def inspect
|
|
||||||
"#<#{self.class}:#{@proxy.inspect}>"
|
|
||||||
end
|
|
||||||
|
|
||||||
def endpoint_url
|
|
||||||
@proxy.endpoint_url
|
|
||||||
end
|
|
||||||
|
|
||||||
def endpoint_url=(endpoint_url)
|
|
||||||
@proxy.endpoint_url = endpoint_url
|
|
||||||
end
|
|
||||||
|
|
||||||
def mapping_registry
|
|
||||||
@proxy.mapping_registry
|
|
||||||
end
|
|
||||||
|
|
||||||
def mapping_registry=(mapping_registry)
|
|
||||||
@proxy.mapping_registry = mapping_registry
|
|
||||||
end
|
|
||||||
|
|
||||||
def default_encodingstyle
|
|
||||||
@proxy.default_encodingstyle
|
|
||||||
end
|
|
||||||
|
|
||||||
def default_encodingstyle=(encodingstyle)
|
|
||||||
@proxy.default_encodingstyle = encodingstyle
|
|
||||||
end
|
|
||||||
|
|
||||||
def generate_explicit_type
|
|
||||||
@proxy.generate_explicit_type
|
|
||||||
end
|
|
||||||
|
|
||||||
def generate_explicit_type=(generate_explicit_type)
|
|
||||||
@proxy.generate_explicit_type = generate_explicit_type
|
|
||||||
end
|
|
||||||
|
|
||||||
def allow_unqualified_element
|
|
||||||
@proxy.allow_unqualified_element
|
|
||||||
end
|
|
||||||
|
|
||||||
def allow_unqualified_element=(allow_unqualified_element)
|
|
||||||
@proxy.allow_unqualified_element = allow_unqualified_element
|
|
||||||
end
|
|
||||||
|
|
||||||
def headerhandler
|
|
||||||
@proxy.headerhandler
|
|
||||||
end
|
|
||||||
|
|
||||||
def streamhandler
|
|
||||||
@proxy.streamhandler
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_loopback_response
|
|
||||||
@proxy.test_loopback_response
|
|
||||||
end
|
|
||||||
|
|
||||||
def reset_stream
|
|
||||||
@proxy.reset_stream
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def invoke(headers, body)
|
def invoke(headers, body)
|
||||||
@ -275,48 +177,11 @@ private
|
|||||||
@proxy.call(name, *params)
|
@proxy.call(name, *params)
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_rpc_method(name_as, soapaction, name, param_def)
|
private
|
||||||
qname = XSD::QName.new(@namespace, name_as)
|
|
||||||
@proxy.add_rpc_method(qname, soapaction, name, param_def)
|
|
||||||
add_rpc_method_interface(name, param_def)
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_document_method(name_as, soapaction, name, param_def)
|
|
||||||
qname = XSD::QName.new(@namespace, name_as)
|
|
||||||
@proxy.add_document_method(qname, soapaction, name, param_def)
|
|
||||||
add_document_method_interface(name, param_def)
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_rpc_method_interface(name, param_def)
|
|
||||||
param_count = 0
|
|
||||||
@proxy.operation[name].each_param_name(RPC::SOAPMethod::IN,
|
|
||||||
RPC::SOAPMethod::INOUT) do |param_name|
|
|
||||||
param_count += 1
|
|
||||||
end
|
|
||||||
sclass = class << @host; self; end
|
|
||||||
sclass.__send__(:define_method, name, proc { |*arg|
|
|
||||||
unless arg.size == param_count
|
|
||||||
raise ArgumentError.new(
|
|
||||||
"wrong number of arguments (#{arg.size} for #{param_count})")
|
|
||||||
end
|
|
||||||
@servant.call(name, *arg)
|
|
||||||
})
|
|
||||||
@host.method(name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_document_method_interface(name, paramname)
|
|
||||||
sclass = class << @host; self; end
|
|
||||||
sclass.__send__(:define_method, name, proc { |param|
|
|
||||||
@servant.call(name, param)
|
|
||||||
})
|
|
||||||
@host.method(name)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_wiredump_file_base(name)
|
def set_wiredump_file_base(name)
|
||||||
if @wiredump_file_base
|
if @wiredump_file_base
|
||||||
@proxy.set_wiredump_file_base(@wiredump_file_base + "_#{ name }")
|
@proxy.set_wiredump_file_base("#{@wiredump_file_base}_#{name}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -344,6 +209,42 @@ private
|
|||||||
opt["protocol.http.no_proxy"] ||= Env::NO_PROXY
|
opt["protocol.http.no_proxy"] ||= Env::NO_PROXY
|
||||||
opt
|
opt
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_rpc_method_interface(name, param_def)
|
||||||
|
param_count = RPC::SOAPMethod.param_count(param_def,
|
||||||
|
RPC::SOAPMethod::IN, RPC::SOAPMethod::INOUT)
|
||||||
|
add_method_interface(name, param_count)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_document_method_interface(name, param_def)
|
||||||
|
param_count = RPC::SOAPMethod.param_count(param_def, RPC::SOAPMethod::IN)
|
||||||
|
add_method_interface(name, param_count)
|
||||||
|
end
|
||||||
|
|
||||||
|
if RUBY_VERSION > "1.7.0"
|
||||||
|
def add_method_interface(name, param_count)
|
||||||
|
::SOAP::Mapping.define_singleton_method(self, name) do |*arg|
|
||||||
|
unless arg.size == param_count
|
||||||
|
raise ArgumentError.new(
|
||||||
|
"wrong number of arguments (#{arg.size} for #{param_count})")
|
||||||
|
end
|
||||||
|
call(name, *arg)
|
||||||
|
end
|
||||||
|
self.method(name)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
def add_method_interface(name, param_count)
|
||||||
|
instance_eval <<-EOS
|
||||||
|
def #{name}(*arg)
|
||||||
|
unless arg.size == #{param_count}
|
||||||
|
raise ArgumentError.new(
|
||||||
|
"wrong number of arguments (\#{arg.size} for #{param_count})")
|
||||||
|
end
|
||||||
|
call(#{name.dump}, *arg)
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
self.method(name)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# SOAP4R - RPC element definition.
|
# SOAP4R - RPC element definition.
|
||||||
# Copyright (C) 2000, 2001, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 2000, 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;
|
||||||
@ -77,6 +77,8 @@ class SOAPMethod < SOAPStruct
|
|||||||
attr_reader :param_def
|
attr_reader :param_def
|
||||||
attr_reader :inparam
|
attr_reader :inparam
|
||||||
attr_reader :outparam
|
attr_reader :outparam
|
||||||
|
attr_reader :retval_name
|
||||||
|
attr_reader :retval_class_name
|
||||||
|
|
||||||
def initialize(qname, param_def = nil)
|
def initialize(qname, param_def = nil)
|
||||||
super(nil)
|
super(nil)
|
||||||
@ -93,6 +95,7 @@ class SOAPMethod < SOAPStruct
|
|||||||
@inparam = {}
|
@inparam = {}
|
||||||
@outparam = {}
|
@outparam = {}
|
||||||
@retval_name = nil
|
@retval_name = nil
|
||||||
|
@retval_class_name = nil
|
||||||
|
|
||||||
init_param(@param_def) if @param_def
|
init_param(@param_def) if @param_def
|
||||||
end
|
end
|
||||||
@ -101,12 +104,12 @@ class SOAPMethod < SOAPStruct
|
|||||||
@outparam_names.size > 0
|
@outparam_names.size > 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def each_param_name(*type)
|
def input_params
|
||||||
@signature.each do |io_type, name, param_type|
|
collect_params(IN, INOUT)
|
||||||
if type.include?(io_type)
|
|
||||||
yield(name)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def output_params
|
||||||
|
collect_params(OUT, INOUT)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_param(params)
|
def set_param(params)
|
||||||
@ -124,7 +127,30 @@ class SOAPMethod < SOAPStruct
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def SOAPMethod.create_param_def(param_names)
|
def SOAPMethod.param_count(param_def, *type)
|
||||||
|
count = 0
|
||||||
|
param_def.each do |io_type, name, param_type|
|
||||||
|
if type.include?(io_type)
|
||||||
|
count += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
count
|
||||||
|
end
|
||||||
|
|
||||||
|
def SOAPMethod.derive_rpc_param_def(obj, name, *param)
|
||||||
|
if param.size == 1 and param[0].is_a?(Array)
|
||||||
|
return param[0]
|
||||||
|
end
|
||||||
|
if param.empty?
|
||||||
|
method = obj.method(name)
|
||||||
|
param_names = (1..method.arity.abs).collect { |i| "p#{i}" }
|
||||||
|
else
|
||||||
|
param_names = param
|
||||||
|
end
|
||||||
|
create_rpc_param_def(param_names)
|
||||||
|
end
|
||||||
|
|
||||||
|
def SOAPMethod.create_rpc_param_def(param_names)
|
||||||
param_def = []
|
param_def = []
|
||||||
param_names.each do |param_name|
|
param_names.each do |param_name|
|
||||||
param_def.push([IN, param_name, nil])
|
param_def.push([IN, param_name, nil])
|
||||||
@ -133,8 +159,29 @@ class SOAPMethod < SOAPStruct
|
|||||||
param_def
|
param_def
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def SOAPMethod.create_doc_param_def(req_qnames, res_qnames)
|
||||||
|
req_qnames = [req_qnames] if req_qnames.is_a?(XSD::QName)
|
||||||
|
res_qnames = [res_qnames] if res_qnames.is_a?(XSD::QName)
|
||||||
|
param_def = []
|
||||||
|
req_qnames.each do |qname|
|
||||||
|
param_def << [IN, qname.name, [nil, qname.namespace, qname.name]]
|
||||||
|
end
|
||||||
|
res_qnames.each do |qname|
|
||||||
|
param_def << [OUT, qname.name, [nil, qname.namespace, qname.name]]
|
||||||
|
end
|
||||||
|
param_def
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def collect_params(*type)
|
||||||
|
names = []
|
||||||
|
@signature.each do |io_type, name, param_type|
|
||||||
|
names << name if type.include?(io_type)
|
||||||
|
end
|
||||||
|
names
|
||||||
|
end
|
||||||
|
|
||||||
def init_param(param_def)
|
def init_param(param_def)
|
||||||
param_def.each do |io_type, name, param_type|
|
param_def.each do |io_type, name, param_type|
|
||||||
case io_type
|
case io_type
|
||||||
@ -148,12 +195,20 @@ private
|
|||||||
@signature.push([INOUT, name, param_type])
|
@signature.push([INOUT, name, param_type])
|
||||||
@inoutparam_names.push(name)
|
@inoutparam_names.push(name)
|
||||||
when RETVAL
|
when RETVAL
|
||||||
if (@retval_name)
|
if @retval_name
|
||||||
raise MethodDefinitionError.new('Duplicated retval')
|
raise MethodDefinitionError.new('duplicated retval')
|
||||||
end
|
end
|
||||||
@retval_name = name
|
@retval_name = name
|
||||||
|
@retval_class_name = nil
|
||||||
|
if param_type
|
||||||
|
if param_type[0].is_a?(String)
|
||||||
|
@retval_class_name = Mapping.class_from_name(param_type[0])
|
||||||
else
|
else
|
||||||
raise MethodDefinitionError.new("Unknown type: #{ io_type }")
|
@retval_class_name = param_type[0]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
raise MethodDefinitionError.new("unknown type: #{io_type}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -168,7 +223,7 @@ class SOAPMethodRequest < SOAPMethod
|
|||||||
param_value = []
|
param_value = []
|
||||||
i = 0
|
i = 0
|
||||||
params.each do |param|
|
params.each do |param|
|
||||||
param_name = "p#{ i }"
|
param_name = "p#{i}"
|
||||||
i += 1
|
i += 1
|
||||||
param_def << [IN, param_name, nil]
|
param_def << [IN, param_name, nil]
|
||||||
param_value << [param_name, param]
|
param_value << [param_name, param]
|
||||||
@ -186,9 +241,9 @@ class SOAPMethodRequest < SOAPMethod
|
|||||||
end
|
end
|
||||||
|
|
||||||
def each
|
def each
|
||||||
each_param_name(IN, INOUT) do |name|
|
input_params.each do |name|
|
||||||
unless @inparam[name]
|
unless @inparam[name]
|
||||||
raise ParameterError.new("Parameter: #{ name } was not given.")
|
raise ParameterError.new("parameter: #{name} was not given")
|
||||||
end
|
end
|
||||||
yield(name, @inparam[name])
|
yield(name, @inparam[name])
|
||||||
end
|
end
|
||||||
@ -200,10 +255,10 @@ class SOAPMethodRequest < SOAPMethod
|
|||||||
req
|
req
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_method_response
|
def create_method_response(response_name = nil)
|
||||||
SOAPMethodResponse.new(
|
response_name ||=
|
||||||
XSD::QName.new(@elename.namespace, @elename.name + 'Response'),
|
XSD::QName.new(@elename.namespace, @elename.name + 'Response')
|
||||||
@param_def)
|
SOAPMethodResponse.new(response_name, @param_def)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -211,7 +266,7 @@ private
|
|||||||
def check_elename(qname)
|
def check_elename(qname)
|
||||||
# NCName & ruby's method name
|
# NCName & ruby's method name
|
||||||
unless /\A[\w_][\w\d_\-]*\z/ =~ qname.name
|
unless /\A[\w_][\w\d_\-]*\z/ =~ qname.name
|
||||||
raise MethodDefinitionError.new("Element name '#{qname.name}' not allowed")
|
raise MethodDefinitionError.new("element name '#{qname.name}' not allowed")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -236,11 +291,11 @@ class SOAPMethodResponse < SOAPMethod
|
|||||||
yield(@retval_name, @retval)
|
yield(@retval_name, @retval)
|
||||||
end
|
end
|
||||||
|
|
||||||
each_param_name(OUT, INOUT) do |param_name|
|
output_params.each do |name|
|
||||||
unless @outparam[param_name]
|
unless @outparam[name]
|
||||||
raise ParameterError.new("Parameter: #{ param_name } was not given.")
|
raise ParameterError.new("parameter: #{name} was not given")
|
||||||
end
|
end
|
||||||
yield(param_name, @outparam[param_name])
|
yield(name, @outparam[name])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -24,23 +24,22 @@ class HTTPServer < Logger::Application
|
|||||||
super(config[:SOAPHTTPServerApplicationName] || self.class.name)
|
super(config[:SOAPHTTPServerApplicationName] || self.class.name)
|
||||||
@default_namespace = config[:SOAPDefaultNamespace]
|
@default_namespace = config[:SOAPDefaultNamespace]
|
||||||
@webrick_config = config.dup
|
@webrick_config = config.dup
|
||||||
|
self.level = Logger::Severity::ERROR # keep silent by default
|
||||||
@webrick_config[:Logger] ||= @log
|
@webrick_config[:Logger] ||= @log
|
||||||
@server = nil
|
@log = @webrick_config[:Logger] # sync logger of App and HTTPServer
|
||||||
@soaplet = ::SOAP::RPC::SOAPlet.new
|
@router = ::SOAP::RPC::Router.new(self.class.name)
|
||||||
self.level = Logger::Severity::INFO
|
@soaplet = ::SOAP::RPC::SOAPlet.new(@router)
|
||||||
on_init
|
on_init
|
||||||
|
@server = WEBrick::HTTPServer.new(@webrick_config)
|
||||||
|
@server.mount('/', @soaplet)
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_init
|
def on_init
|
||||||
# define extra methods in derived class.
|
# do extra initialization in a derived class if needed.
|
||||||
end
|
end
|
||||||
|
|
||||||
def status
|
def status
|
||||||
if @server
|
@server.status if @server
|
||||||
@server.status
|
|
||||||
else
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def shutdown
|
def shutdown
|
||||||
@ -48,31 +47,39 @@ class HTTPServer < Logger::Application
|
|||||||
end
|
end
|
||||||
|
|
||||||
def mapping_registry
|
def mapping_registry
|
||||||
@soaplet.app_scope_router.mapping_registry
|
@router.mapping_registry
|
||||||
end
|
end
|
||||||
|
|
||||||
def mapping_registry=(mapping_registry)
|
def mapping_registry=(mapping_registry)
|
||||||
@soaplet.app_scope_router.mapping_registry = mapping_registry
|
@router.mapping_registry = mapping_registry
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_explicit_type
|
||||||
|
@router.generate_explicit_type
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_explicit_type=(generate_explicit_type)
|
||||||
|
@router.generate_explicit_type = generate_explicit_type
|
||||||
end
|
end
|
||||||
|
|
||||||
# servant entry interface
|
# servant entry interface
|
||||||
|
|
||||||
def add_rpc_request_servant(factory, namespace = @default_namespace,
|
def add_rpc_request_servant(factory, namespace = @default_namespace)
|
||||||
mapping_registry = nil)
|
@router.add_rpc_request_servant(factory, namespace)
|
||||||
@soaplet.add_rpc_request_servant(factory, namespace, mapping_registry)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_rpc_servant(obj, namespace = @default_namespace)
|
def add_rpc_servant(obj, namespace = @default_namespace)
|
||||||
@soaplet.add_rpc_servant(obj, namespace)
|
@router.add_rpc_servant(obj, namespace)
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_rpc_request_headerhandler(factory)
|
def add_request_headerhandler(factory)
|
||||||
@soaplet.add_rpc_request_headerhandler(factory)
|
@router.add_request_headerhandler(factory)
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_rpc_headerhandler(obj)
|
def add_headerhandler(obj)
|
||||||
@soaplet.add_rpc_headerhandler(obj)
|
@router.add_headerhandler(obj)
|
||||||
end
|
end
|
||||||
|
alias add_rpc_headerhandler add_headerhandler
|
||||||
|
|
||||||
# method entry interface
|
# method entry interface
|
||||||
|
|
||||||
@ -81,52 +88,38 @@ class HTTPServer < Logger::Application
|
|||||||
end
|
end
|
||||||
alias add_method add_rpc_method
|
alias add_method add_rpc_method
|
||||||
|
|
||||||
def add_document_method(obj, name, req_qname, res_qname)
|
|
||||||
opt = {}
|
|
||||||
opt[:request_style] = opt[:response_style] = :document
|
|
||||||
opt[:request_use] = opt[:response_use] = :literal
|
|
||||||
param_def = [
|
|
||||||
['input', req_qname.name, [nil, req_qname.namespace, req_qname.name]],
|
|
||||||
['output', req_qname.name, [nil, res_qname.namespace, res_qname.name]]
|
|
||||||
]
|
|
||||||
@soaplet.app_scope_router.add_operation(req_qname, nil, obj, name,
|
|
||||||
param_def, opt)
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_rpc_method_as(obj, name, name_as, *param)
|
def add_rpc_method_as(obj, name, name_as, *param)
|
||||||
qname = XSD::QName.new(@default_namespace, name_as)
|
qname = XSD::QName.new(@default_namespace, name_as)
|
||||||
soapaction = nil
|
soapaction = nil
|
||||||
param_def = create_param_def(obj, name, param)
|
param_def = SOAPMethod.derive_rpc_param_def(obj, name, *param)
|
||||||
add_operation(qname, soapaction, obj, name, param_def)
|
@router.add_rpc_operation(obj, qname, soapaction, name, param_def)
|
||||||
end
|
end
|
||||||
alias add_method_as add_rpc_method_as
|
alias add_method_as add_rpc_method_as
|
||||||
|
|
||||||
def add_operation(qname, soapaction, obj, name, param_def, opt = {})
|
def add_document_method(obj, soapaction, name, req_qnames, res_qnames)
|
||||||
opt[:request_style] ||= :rpc
|
param_def = SOAPMethod.create_doc_param_def(req_qnames, res_qnames)
|
||||||
opt[:response_style] ||= :rpc
|
@router.add_document_operation(obj, soapaction, name, param_def)
|
||||||
opt[:request_use] ||= :encoded
|
|
||||||
opt[:response_use] ||= :encoded
|
|
||||||
@soaplet.app_scope_router.add_operation(qname, soapaction, obj, name,
|
|
||||||
param_def, opt)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_param_def(obj, name, param = nil)
|
def add_rpc_operation(receiver, qname, soapaction, name, param_def, opt = {})
|
||||||
if param.nil? or param.empty?
|
@router.add_rpc_operation(receiver, qname, soapaction, name, param_def, opt)
|
||||||
method = obj.method(name)
|
|
||||||
::SOAP::RPC::SOAPMethod.create_param_def(
|
|
||||||
(1..method.arity.abs).collect { |i| "p#{i}" })
|
|
||||||
elsif param.size == 1 and param[0].is_a?(Array)
|
|
||||||
param[0]
|
|
||||||
else
|
|
||||||
::SOAP::RPC::SOAPMethod.create_param_def(param)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_rpc_request_operation(factory, qname, soapaction, name, param_def, opt = {})
|
||||||
|
@router.add_rpc_request_operation(factory, qname, soapaction, name, param_def, opt)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_document_operation(receiver, soapaction, name, param_def, opt = {})
|
||||||
|
@router.add_document_operation(receiver, soapaction, name, param_def, opt)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_document_request_operation(factory, soapaction, name, param_def, opt = {})
|
||||||
|
@router.add_document_request_operation(factory, soapaction, name, param_def, opt)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def run
|
def run
|
||||||
@server = WEBrick::HTTPServer.new(@webrick_config)
|
|
||||||
@server.mount('/', @soaplet)
|
|
||||||
@server.start
|
@server.start
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# SOAP4R - RPC Proxy library.
|
# SOAP4R - RPC Proxy library.
|
||||||
# Copyright (C) 2000, 2003, 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 2000, 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;
|
||||||
@ -78,30 +78,62 @@ public
|
|||||||
@streamhandler.test_loopback_response
|
@streamhandler.test_loopback_response
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_rpc_method(qname, soapaction, name, param_def, opt = {})
|
def add_rpc_operation(qname, soapaction, name, param_def, opt = {})
|
||||||
|
opt[:request_qname] = qname
|
||||||
opt[:request_style] ||= :rpc
|
opt[:request_style] ||= :rpc
|
||||||
opt[:response_style] ||= :rpc
|
opt[:response_style] ||= :rpc
|
||||||
opt[:request_use] ||= :encoded
|
opt[:request_use] ||= :encoded
|
||||||
opt[:response_use] ||= :encoded
|
opt[:response_use] ||= :encoded
|
||||||
@operation[name] = Operation.new(qname, soapaction, name, param_def, opt)
|
@operation[name] = Operation.new(soapaction, param_def, opt)
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_document_method(qname, soapaction, name, param_def, opt = {})
|
def add_document_operation(soapaction, name, param_def, opt = {})
|
||||||
opt[:request_style] ||= :document
|
opt[:request_style] ||= :document
|
||||||
opt[:response_style] ||= :document
|
opt[:response_style] ||= :document
|
||||||
opt[:request_use] ||= :literal
|
opt[:request_use] ||= :literal
|
||||||
opt[:response_use] ||= :literal
|
opt[:response_use] ||= :literal
|
||||||
@operation[name] = Operation.new(qname, soapaction, name, param_def, opt)
|
@operation[name] = Operation.new(soapaction, param_def, opt)
|
||||||
end
|
end
|
||||||
|
|
||||||
# add_method is for shortcut of typical rpc/encoded method definition.
|
# add_method is for shortcut of typical rpc/encoded method definition.
|
||||||
alias add_method add_rpc_method
|
alias add_method add_rpc_operation
|
||||||
|
alias add_rpc_method add_rpc_operation
|
||||||
|
alias add_document_method add_document_operation
|
||||||
|
|
||||||
def invoke(req_header, req_body, opt = create_options)
|
def invoke(req_header, req_body, opt = nil)
|
||||||
|
opt ||= create_options
|
||||||
|
route(req_header, req_body, opt, opt)
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(name, *params)
|
||||||
|
unless op_info = @operation[name]
|
||||||
|
raise MethodDefinitionError, "method: #{name} not defined"
|
||||||
|
end
|
||||||
|
req_header = create_request_header
|
||||||
|
req_body = SOAPBody.new(
|
||||||
|
op_info.request_body(params, @mapping_registry, @literal_mapping_registry)
|
||||||
|
)
|
||||||
|
reqopt = create_options({
|
||||||
|
:soapaction => op_info.soapaction || @soapaction,
|
||||||
|
:default_encodingstyle => op_info.request_default_encodingstyle})
|
||||||
|
resopt = create_options({
|
||||||
|
:default_encodingstyle => op_info.response_default_encodingstyle})
|
||||||
|
env = route(req_header, req_body, reqopt, resopt)
|
||||||
|
raise EmptyResponseError unless env
|
||||||
|
receive_headers(env.header)
|
||||||
|
begin
|
||||||
|
check_fault(env.body)
|
||||||
|
rescue ::SOAP::FaultError => e
|
||||||
|
op_info.raise_fault(e, @mapping_registry, @literal_mapping_registry)
|
||||||
|
end
|
||||||
|
op_info.response_obj(env.body, @mapping_registry, @literal_mapping_registry)
|
||||||
|
end
|
||||||
|
|
||||||
|
def route(req_header, req_body, reqopt, resopt)
|
||||||
req_env = SOAPEnvelope.new(req_header, req_body)
|
req_env = SOAPEnvelope.new(req_header, req_body)
|
||||||
opt[:external_content] = nil
|
reqopt[:external_content] = nil
|
||||||
conn_data = marshal(req_env, opt)
|
conn_data = marshal(req_env, reqopt)
|
||||||
if ext = opt[:external_content]
|
if ext = reqopt[:external_content]
|
||||||
mime = MIMEMessage.new
|
mime = MIMEMessage.new
|
||||||
ext.each do |k, v|
|
ext.each do |k, v|
|
||||||
mime.add_attachment(v.data)
|
mime.add_attachment(v.data)
|
||||||
@ -111,33 +143,12 @@ public
|
|||||||
conn_data.send_string = mime.content_str
|
conn_data.send_string = mime.content_str
|
||||||
conn_data.send_contenttype = mime.headers['content-type'].str
|
conn_data.send_contenttype = mime.headers['content-type'].str
|
||||||
end
|
end
|
||||||
conn_data = @streamhandler.send(@endpoint_url, conn_data, opt[:soapaction])
|
conn_data = @streamhandler.send(@endpoint_url, conn_data,
|
||||||
|
reqopt[:soapaction])
|
||||||
if conn_data.receive_string.empty?
|
if conn_data.receive_string.empty?
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
unmarshal(conn_data, opt)
|
unmarshal(conn_data, resopt)
|
||||||
end
|
|
||||||
|
|
||||||
def call(name, *params)
|
|
||||||
unless op_info = @operation[name]
|
|
||||||
raise MethodDefinitionError, "Method: #{name} not defined."
|
|
||||||
end
|
|
||||||
req_header = create_request_header
|
|
||||||
req_body = op_info.create_request_body(params, @mapping_registry,
|
|
||||||
@literal_mapping_registry)
|
|
||||||
opt = create_options({
|
|
||||||
:soapaction => op_info.soapaction || @soapaction,
|
|
||||||
:default_encodingstyle => op_info.response_default_encodingstyle})
|
|
||||||
env = invoke(req_header, req_body, opt)
|
|
||||||
receive_headers(env.header)
|
|
||||||
raise EmptyResponseError.new("Empty response.") unless env
|
|
||||||
begin
|
|
||||||
check_fault(env.body)
|
|
||||||
rescue ::SOAP::FaultError => e
|
|
||||||
Mapping.fault2exception(e)
|
|
||||||
end
|
|
||||||
op_info.create_response_obj(env, @mapping_registry,
|
|
||||||
@literal_mapping_registry)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_fault(body)
|
def check_fault(body)
|
||||||
@ -217,98 +228,203 @@ private
|
|||||||
attr_reader :request_use
|
attr_reader :request_use
|
||||||
attr_reader :response_use
|
attr_reader :response_use
|
||||||
|
|
||||||
def initialize(qname, soapaction, name, param_def, opt)
|
def initialize(soapaction, param_def, opt)
|
||||||
@soapaction = soapaction
|
@soapaction = soapaction
|
||||||
@request_style = opt[:request_style]
|
@request_style = opt[:request_style]
|
||||||
@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]
|
||||||
@rpc_method_factory = @document_method_name = nil
|
|
||||||
check_style(@request_style)
|
check_style(@request_style)
|
||||||
check_style(@response_style)
|
check_style(@response_style)
|
||||||
|
check_use(@request_use)
|
||||||
|
check_use(@response_use)
|
||||||
if @request_style == :rpc
|
if @request_style == :rpc
|
||||||
@rpc_method_factory = SOAPMethodRequest.new(qname, param_def,
|
@rpc_request_qname = opt[:request_qname]
|
||||||
@soapaction)
|
if @rpc_request_qname.nil?
|
||||||
|
raise MethodDefinitionError.new("rpc_request_qname must be given")
|
||||||
|
end
|
||||||
|
@rpc_method_factory =
|
||||||
|
RPC::SOAPMethodRequest.new(@rpc_request_qname, param_def, @soapaction)
|
||||||
else
|
else
|
||||||
@document_method_name = {}
|
@doc_request_qnames = []
|
||||||
|
@doc_response_qnames = []
|
||||||
param_def.each do |inout, paramname, typeinfo|
|
param_def.each do |inout, paramname, typeinfo|
|
||||||
klass, namespace, name = typeinfo
|
klass_not_used, nsdef, namedef = typeinfo
|
||||||
case inout.to_s
|
if namedef.nil?
|
||||||
when "input"
|
raise MethodDefinitionError.new("qname must be given")
|
||||||
@document_method_name[:input] = ::XSD::QName.new(namespace, name)
|
end
|
||||||
when "output"
|
case inout
|
||||||
@document_method_name[:output] = ::XSD::QName.new(namespace, name)
|
when SOAPMethod::IN
|
||||||
|
@doc_request_qnames << XSD::QName.new(nsdef, namedef)
|
||||||
|
when SOAPMethod::OUT
|
||||||
|
@doc_response_qnames << XSD::QName.new(nsdef, namedef)
|
||||||
else
|
else
|
||||||
raise MethodDefinitionError, "unknown type: " + inout
|
raise MethodDefinitionError.new(
|
||||||
|
"illegal inout definition for document style: #{inout}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def request_default_encodingstyle
|
def request_default_encodingstyle
|
||||||
(@request_style == :rpc) ? EncodingNamespace : LiteralNamespace
|
(@request_use == :encoded) ? EncodingNamespace : LiteralNamespace
|
||||||
end
|
end
|
||||||
|
|
||||||
def response_default_encodingstyle
|
def response_default_encodingstyle
|
||||||
(@response_style == :rpc) ? EncodingNamespace : LiteralNamespace
|
(@response_use == :encoded) ? EncodingNamespace : LiteralNamespace
|
||||||
end
|
end
|
||||||
|
|
||||||
# for rpc
|
def request_body(values, mapping_registry, literal_mapping_registry)
|
||||||
def each_param_name(*target)
|
|
||||||
if @request_style == :rpc
|
if @request_style == :rpc
|
||||||
@rpc_method_factory.each_param_name(*target) do |name|
|
request_rpc(values, mapping_registry, literal_mapping_registry)
|
||||||
yield(name)
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
yield(@document_method_name[:input].name)
|
request_doc(values, mapping_registry, literal_mapping_registry)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_request_body(values, mapping_registry, literal_mapping_registry)
|
def response_obj(body, mapping_registry, literal_mapping_registry)
|
||||||
if @request_style == :rpc
|
|
||||||
values = Mapping.obj2soap(values, mapping_registry).to_a
|
|
||||||
method = @rpc_method_factory.dup
|
|
||||||
params = {}
|
|
||||||
idx = 0
|
|
||||||
method.each_param_name(::SOAP::RPC::SOAPMethod::IN,
|
|
||||||
::SOAP::RPC::SOAPMethod::INOUT) do |name|
|
|
||||||
params[name] = values[idx] || SOAPNil.new
|
|
||||||
idx += 1
|
|
||||||
end
|
|
||||||
method.set_param(params)
|
|
||||||
SOAPBody.new(method)
|
|
||||||
else
|
|
||||||
name = @document_method_name[:input]
|
|
||||||
document = literal_mapping_registry.obj2soap(values[0], name)
|
|
||||||
SOAPBody.new(document)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_response_obj(env, mapping_registry, literal_mapping_registry)
|
|
||||||
if @response_style == :rpc
|
if @response_style == :rpc
|
||||||
ret = env.body.response ?
|
response_rpc(body, mapping_registry, literal_mapping_registry)
|
||||||
Mapping.soap2obj(env.body.response, mapping_registry) : nil
|
|
||||||
if env.body.outparams
|
|
||||||
outparams = env.body.outparams.collect { |outparam|
|
|
||||||
Mapping.soap2obj(outparam)
|
|
||||||
}
|
|
||||||
[ret].concat(outparams)
|
|
||||||
else
|
else
|
||||||
ret
|
response_doc(body, mapping_registry, literal_mapping_registry)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def raise_fault(e, mapping_registry, literal_mapping_registry)
|
||||||
|
if @response_style == :rpc
|
||||||
|
Mapping.fault2exception(e, mapping_registry)
|
||||||
else
|
else
|
||||||
Mapping.soap2obj(env.body.root_node, literal_mapping_registry)
|
Mapping.fault2exception(e, literal_mapping_registry)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
ALLOWED_STYLE = [:rpc, :document]
|
|
||||||
def check_style(style)
|
def check_style(style)
|
||||||
unless ALLOWED_STYLE.include?(style)
|
unless [:rpc, :document].include?(style)
|
||||||
raise MethodDefinitionError, "unknown style: " + style
|
raise MethodDefinitionError.new("unknown style: #{style}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_use(use)
|
||||||
|
unless [:encoded, :literal].include?(use)
|
||||||
|
raise MethodDefinitionError.new("unknown use: #{use}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_rpc(values, mapping_registry, literal_mapping_registry)
|
||||||
|
if @request_use == :encoded
|
||||||
|
request_rpc_enc(values, mapping_registry)
|
||||||
|
else
|
||||||
|
request_rpc_lit(values, literal_mapping_registry)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_doc(values, mapping_registry, literal_mapping_registry)
|
||||||
|
if @request_use == :encoded
|
||||||
|
request_doc_enc(values, mapping_registry)
|
||||||
|
else
|
||||||
|
request_doc_lit(values, literal_mapping_registry)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_rpc_enc(values, mapping_registry)
|
||||||
|
method = @rpc_method_factory.dup
|
||||||
|
names = method.input_params
|
||||||
|
obj = create_request_obj(names, values)
|
||||||
|
soap = Mapping.obj2soap(obj, mapping_registry, @rpc_request_qname)
|
||||||
|
method.set_param(soap)
|
||||||
|
method
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_rpc_lit(values, mapping_registry)
|
||||||
|
method = @rpc_method_factory.dup
|
||||||
|
params = {}
|
||||||
|
idx = 0
|
||||||
|
method.input_params.each do |name|
|
||||||
|
params[name] = Mapping.obj2soap(values[idx], mapping_registry,
|
||||||
|
XSD::QName.new(nil, name))
|
||||||
|
idx += 1
|
||||||
|
end
|
||||||
|
method.set_param(params)
|
||||||
|
method
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_doc_enc(values, mapping_registry)
|
||||||
|
(0...values.size).collect { |idx|
|
||||||
|
ele = Mapping.obj2soap(values[idx], mapping_registry)
|
||||||
|
ele.elename = @doc_request_qnames[idx]
|
||||||
|
ele
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_doc_lit(values, mapping_registry)
|
||||||
|
(0...values.size).collect { |idx|
|
||||||
|
ele = Mapping.obj2soap(values[idx], mapping_registry,
|
||||||
|
@doc_request_qnames[idx])
|
||||||
|
ele.encodingstyle = LiteralNamespace
|
||||||
|
ele
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_rpc(body, mapping_registry, literal_mapping_registry)
|
||||||
|
if @response_use == :encoded
|
||||||
|
response_rpc_enc(body, mapping_registry)
|
||||||
|
else
|
||||||
|
response_rpc_lit(body, literal_mapping_registry)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_doc(body, mapping_registry, literal_mapping_registry)
|
||||||
|
if @response_use == :encoded
|
||||||
|
return *response_doc_enc(body, mapping_registry)
|
||||||
|
else
|
||||||
|
return *response_doc_lit(body, literal_mapping_registry)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_rpc_enc(body, mapping_registry)
|
||||||
|
ret = nil
|
||||||
|
if body.response
|
||||||
|
ret = Mapping.soap2obj(body.response, mapping_registry,
|
||||||
|
@rpc_method_factory.retval_class_name)
|
||||||
|
end
|
||||||
|
if body.outparams
|
||||||
|
outparams = body.outparams.collect { |outparam|
|
||||||
|
Mapping.soap2obj(outparam, mapping_regisry)
|
||||||
|
}
|
||||||
|
[ret].concat(outparams)
|
||||||
|
else
|
||||||
|
ret
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_rpc_lit(body, mapping_registry)
|
||||||
|
body.root_node.collect { |key, value|
|
||||||
|
Mapping.soap2obj(value, mapping_registry,
|
||||||
|
@rpc_method_factory.retval_class_name)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_doc_enc(body, mapping_registry)
|
||||||
|
body.collect { |key, value|
|
||||||
|
Mapping.soap2obj(value, mapping_registry)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_doc_lit(body, mapping_registry)
|
||||||
|
body.collect { |key, value|
|
||||||
|
Mapping.soap2obj(value, mapping_registry)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_request_obj(names, params)
|
||||||
|
o = Object.new
|
||||||
|
for idx in 0 ... params.length
|
||||||
|
o.instance_variable_set('@' + names[idx], params[idx])
|
||||||
|
end
|
||||||
|
o
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# SOAP4R - RPC Routing library
|
# SOAP4R - RPC Routing library
|
||||||
# Copyright (C) 2001, 2002 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 2001, 2002, 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;
|
||||||
@ -25,101 +25,229 @@ class Router
|
|||||||
include SOAP
|
include SOAP
|
||||||
|
|
||||||
attr_reader :actor
|
attr_reader :actor
|
||||||
attr_accessor :allow_unqualified_element
|
|
||||||
attr_accessor :default_encodingstyle
|
|
||||||
attr_accessor :mapping_registry
|
attr_accessor :mapping_registry
|
||||||
attr_accessor :literal_mapping_registry
|
attr_accessor :literal_mapping_registry
|
||||||
attr_reader :headerhandler
|
attr_accessor :generate_explicit_type
|
||||||
|
|
||||||
def initialize(actor)
|
def initialize(actor)
|
||||||
@actor = actor
|
@actor = actor
|
||||||
@allow_unqualified_element = false
|
|
||||||
@default_encodingstyle = nil
|
|
||||||
@mapping_registry = nil
|
@mapping_registry = nil
|
||||||
@headerhandler = Header::HandlerSet.new
|
@headerhandler = Header::HandlerSet.new
|
||||||
@literal_mapping_registry = ::SOAP::Mapping::WSDLLiteralRegistry.new
|
@literal_mapping_registry = ::SOAP::Mapping::WSDLLiteralRegistry.new
|
||||||
@operation = {}
|
@generate_explicit_type = true
|
||||||
|
@operation_by_soapaction = {}
|
||||||
|
@operation_by_qname = {}
|
||||||
|
@headerhandlerfactory = []
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_rpc_method(receiver, qname, soapaction, name, param_def, opt = {})
|
###
|
||||||
opt[:request_style] ||= :rpc
|
## header handler interface
|
||||||
opt[:response_style] ||= :rpc
|
#
|
||||||
opt[:request_use] ||= :encoded
|
def add_request_headerhandler(factory)
|
||||||
opt[:response_use] ||= :encoded
|
unless factory.respond_to?(:create)
|
||||||
add_operation(qname, soapaction, receiver, name, param_def, opt)
|
raise TypeError.new("factory must respond to 'create'")
|
||||||
|
end
|
||||||
|
@headerhandlerfactory << factory
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_document_method(receiver, qname, soapaction, name, param_def, opt = {})
|
def add_headerhandler(handler)
|
||||||
opt[:request_style] ||= :document
|
@headerhandler.add(handler)
|
||||||
opt[:response_style] ||= :document
|
|
||||||
opt[:request_use] ||= :encoded
|
|
||||||
opt[:response_use] ||= :encoded
|
|
||||||
if opt[:request_style] == :document
|
|
||||||
inputdef = param_def.find { |inout, paramname, typeinfo| inout == "input" }
|
|
||||||
klass, nsdef, namedef = inputdef[2]
|
|
||||||
qname = ::XSD::QName.new(nsdef, namedef)
|
|
||||||
end
|
|
||||||
add_operation(qname, soapaction, receiver, name, param_def, opt)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_operation(qname, soapaction, receiver, name, param_def, opt)
|
###
|
||||||
@operation[fqname(qname)] = Operation.new(qname, soapaction, receiver,
|
## servant definition interface
|
||||||
name, param_def, opt)
|
#
|
||||||
|
def add_rpc_request_servant(factory, namespace)
|
||||||
|
unless factory.respond_to?(:create)
|
||||||
|
raise TypeError.new("factory must respond to 'create'")
|
||||||
|
end
|
||||||
|
obj = factory.create # a dummy instance for introspection
|
||||||
|
::SOAP::RPC.defined_methods(obj).each do |name|
|
||||||
|
begin
|
||||||
|
qname = XSD::QName.new(namespace, name)
|
||||||
|
param_def = ::SOAP::RPC::SOAPMethod.derive_rpc_param_def(obj, name)
|
||||||
|
opt = create_styleuse_option(:rpc, :encoded)
|
||||||
|
add_rpc_request_operation(factory, qname, nil, name, param_def, opt)
|
||||||
|
rescue SOAP::RPC::MethodDefinitionError => e
|
||||||
|
p e if $DEBUG
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# add_method is for shortcut of typical use="encoded" method definition.
|
def add_rpc_servant(obj, namespace)
|
||||||
alias add_method add_rpc_method
|
::SOAP::RPC.defined_methods(obj).each do |name|
|
||||||
|
begin
|
||||||
|
qname = XSD::QName.new(namespace, name)
|
||||||
|
param_def = ::SOAP::RPC::SOAPMethod.derive_rpc_param_def(obj, name)
|
||||||
|
opt = create_styleuse_option(:rpc, :encoded)
|
||||||
|
add_rpc_operation(obj, qname, nil, name, param_def, opt)
|
||||||
|
rescue SOAP::RPC::MethodDefinitionError => e
|
||||||
|
p e if $DEBUG
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
alias add_servant add_rpc_servant
|
||||||
|
|
||||||
|
###
|
||||||
|
## operation definition interface
|
||||||
|
#
|
||||||
|
def add_rpc_operation(receiver, qname, soapaction, name, param_def, opt = {})
|
||||||
|
ensure_styleuse_option(opt, :rpc, :encoded)
|
||||||
|
opt[:request_qname] = qname
|
||||||
|
op = ApplicationScopeOperation.new(soapaction, receiver, name, param_def,
|
||||||
|
opt)
|
||||||
|
if opt[:request_style] != :rpc
|
||||||
|
raise RPCRoutingError.new("illegal request_style given")
|
||||||
|
end
|
||||||
|
assign_operation(soapaction, qname, op)
|
||||||
|
end
|
||||||
|
alias add_method add_rpc_operation
|
||||||
|
alias add_rpc_method add_rpc_operation
|
||||||
|
|
||||||
|
def add_rpc_request_operation(factory, qname, soapaction, name, param_def, opt = {})
|
||||||
|
ensure_styleuse_option(opt, :rpc, :encoded)
|
||||||
|
opt[:request_qname] = qname
|
||||||
|
op = RequestScopeOperation.new(soapaction, factory, name, param_def, opt)
|
||||||
|
if opt[:request_style] != :rpc
|
||||||
|
raise RPCRoutingError.new("illegal request_style given")
|
||||||
|
end
|
||||||
|
assign_operation(soapaction, qname, op)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_document_operation(receiver, soapaction, name, param_def, opt = {})
|
||||||
|
#
|
||||||
|
# adopt workaround for doc/lit wrapper method
|
||||||
|
# (you should consider to simply use rpc/lit service)
|
||||||
|
#
|
||||||
|
#unless soapaction
|
||||||
|
# raise RPCRoutingError.new("soapaction is a must for document method")
|
||||||
|
#end
|
||||||
|
ensure_styleuse_option(opt, :document, :literal)
|
||||||
|
op = ApplicationScopeOperation.new(soapaction, receiver, name, param_def,
|
||||||
|
opt)
|
||||||
|
if opt[:request_style] != :document
|
||||||
|
raise RPCRoutingError.new("illegal request_style given")
|
||||||
|
end
|
||||||
|
assign_operation(soapaction, first_input_part_qname(param_def), op)
|
||||||
|
end
|
||||||
|
alias add_document_method add_document_operation
|
||||||
|
|
||||||
|
def add_document_request_operation(factory, soapaction, name, param_def, opt = {})
|
||||||
|
#
|
||||||
|
# adopt workaround for doc/lit wrapper method
|
||||||
|
# (you should consider to simply use rpc/lit service)
|
||||||
|
#
|
||||||
|
#unless soapaction
|
||||||
|
# raise RPCRoutingError.new("soapaction is a must for document method")
|
||||||
|
#end
|
||||||
|
ensure_styleuse_option(opt, :document, :literal)
|
||||||
|
op = RequestScopeOperation.new(soapaction, receiver, name, param_def, opt)
|
||||||
|
if opt[:request_style] != :document
|
||||||
|
raise RPCRoutingError.new("illegal request_style given")
|
||||||
|
end
|
||||||
|
assign_operation(soapaction, first_input_part_qname(param_def), op)
|
||||||
|
end
|
||||||
|
|
||||||
def route(conn_data)
|
def route(conn_data)
|
||||||
soap_response = nil
|
# we cannot set request_default_encodingsyle before parsing the content.
|
||||||
begin
|
|
||||||
env = unmarshal(conn_data)
|
env = unmarshal(conn_data)
|
||||||
if env.nil?
|
if env.nil?
|
||||||
raise ArgumentError.new("Illegal SOAP marshal format.")
|
raise ArgumentError.new("illegal SOAP marshal format")
|
||||||
end
|
end
|
||||||
receive_headers(env.header)
|
op = lookup_operation(conn_data.soapaction, env.body)
|
||||||
request = env.body.request
|
headerhandler = @headerhandler.dup
|
||||||
op = @operation[fqname(request.elename)]
|
@headerhandlerfactory.each do |f|
|
||||||
unless op
|
headerhandler.add(f.create)
|
||||||
raise RPCRoutingError.new("Method: #{request.elename} not supported.")
|
|
||||||
end
|
end
|
||||||
soap_response = op.call(request, @mapping_registry, @literal_mapping_registry)
|
receive_headers(headerhandler, env.header)
|
||||||
|
soap_response = default_encodingstyle = nil
|
||||||
|
begin
|
||||||
|
soap_response =
|
||||||
|
op.call(env.body, @mapping_registry, @literal_mapping_registry)
|
||||||
|
default_encodingstyle = op.response_default_encodingstyle
|
||||||
rescue Exception
|
rescue Exception
|
||||||
soap_response = fault($!)
|
soap_response = fault($!)
|
||||||
conn_data.is_fault = true
|
default_encodingstyle = nil
|
||||||
end
|
end
|
||||||
marshal(conn_data, op, soap_response)
|
conn_data.is_fault = true if soap_response.is_a?(SOAPFault)
|
||||||
conn_data
|
header = call_headers(headerhandler)
|
||||||
|
body = SOAPBody.new(soap_response)
|
||||||
|
env = SOAPEnvelope.new(header, body)
|
||||||
|
marshal(conn_data, env, default_encodingstyle)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Create fault response string.
|
# Create fault response string.
|
||||||
def create_fault_response(e, charset = nil)
|
def create_fault_response(e)
|
||||||
header = SOAPHeader.new
|
env = SOAPEnvelope.new(SOAPHeader.new, SOAPBody.new(fault(e)))
|
||||||
body = SOAPBody.new(fault(e))
|
opt = {}
|
||||||
env = SOAPEnvelope.new(header, body)
|
|
||||||
opt = options
|
|
||||||
opt[:external_content] = nil
|
opt[:external_content] = nil
|
||||||
opt[:charset] = charset
|
|
||||||
response_string = Processor.marshal(env, opt)
|
response_string = Processor.marshal(env, opt)
|
||||||
conn_data = StreamHandler::ConnectionData.new(response_string)
|
conn_data = StreamHandler::ConnectionData.new(response_string)
|
||||||
conn_data.is_fault = true
|
conn_data.is_fault = true
|
||||||
if ext = opt[:external_content]
|
if ext = opt[:external_content]
|
||||||
mime = MIMEMessage.new
|
mimeize(conn_data, ext)
|
||||||
ext.each do |k, v|
|
|
||||||
mime.add_attachment(v.data)
|
|
||||||
end
|
|
||||||
mime.add_part(conn_data.send_string + "\r\n")
|
|
||||||
mime.close
|
|
||||||
conn_data.send_string = mime.content_str
|
|
||||||
conn_data.send_contenttype = mime.headers['content-type'].str
|
|
||||||
end
|
end
|
||||||
conn_data
|
conn_data
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def call_headers
|
def first_input_part_qname(param_def)
|
||||||
headers = @headerhandler.on_outbound
|
param_def.each do |inout, paramname, typeinfo|
|
||||||
|
if inout == SOAPMethod::IN
|
||||||
|
klass, nsdef, namedef = typeinfo
|
||||||
|
return XSD::QName.new(nsdef, namedef)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_styleuse_option(style, use)
|
||||||
|
opt = {}
|
||||||
|
opt[:request_style] = opt[:response_style] = style
|
||||||
|
opt[:request_use] = opt[:response_use] = use
|
||||||
|
opt
|
||||||
|
end
|
||||||
|
|
||||||
|
def ensure_styleuse_option(opt, style, use)
|
||||||
|
opt[:request_style] ||= style
|
||||||
|
opt[:response_style] ||= style
|
||||||
|
opt[:request_use] ||= use
|
||||||
|
opt[:response_use] ||= use
|
||||||
|
end
|
||||||
|
|
||||||
|
def assign_operation(soapaction, qname, op)
|
||||||
|
assigned = false
|
||||||
|
if soapaction and !soapaction.empty?
|
||||||
|
@operation_by_soapaction[soapaction] = op
|
||||||
|
assigned = true
|
||||||
|
end
|
||||||
|
if qname
|
||||||
|
@operation_by_qname[qname] = op
|
||||||
|
assigned = true
|
||||||
|
end
|
||||||
|
unless assigned
|
||||||
|
raise RPCRoutingError.new("cannot assign operation")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def lookup_operation(soapaction, body)
|
||||||
|
if op = @operation_by_soapaction[soapaction]
|
||||||
|
return op
|
||||||
|
end
|
||||||
|
qname = body.root_node.elename
|
||||||
|
if op = @operation_by_qname[qname]
|
||||||
|
return op
|
||||||
|
end
|
||||||
|
if soapaction
|
||||||
|
raise RPCRoutingError.new("operation: #{soapaction} not supported")
|
||||||
|
else
|
||||||
|
raise RPCRoutingError.new("operation: #{qname} not supported")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def call_headers(headerhandler)
|
||||||
|
headers = headerhandler.on_outbound
|
||||||
if headers.empty?
|
if headers.empty?
|
||||||
nil
|
nil
|
||||||
else
|
else
|
||||||
@ -131,12 +259,12 @@ private
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def receive_headers(headers)
|
def receive_headers(headerhandler, headers)
|
||||||
@headerhandler.on_inbound(headers) if headers
|
headerhandler.on_inbound(headers) if headers
|
||||||
end
|
end
|
||||||
|
|
||||||
def unmarshal(conn_data)
|
def unmarshal(conn_data)
|
||||||
opt = options
|
opt = {}
|
||||||
contenttype = conn_data.receive_contenttype
|
contenttype = conn_data.receive_contenttype
|
||||||
if /#{MIMEMessage::MultipartContentType}/i =~ contenttype
|
if /#{MIMEMessage::MultipartContentType}/i =~ contenttype
|
||||||
opt[:external_content] = {}
|
opt[:external_content] = {}
|
||||||
@ -160,19 +288,20 @@ private
|
|||||||
env
|
env
|
||||||
end
|
end
|
||||||
|
|
||||||
def marshal(conn_data, op, soap_response)
|
def marshal(conn_data, env, default_encodingstyle = nil)
|
||||||
response_opt = options
|
opt = {}
|
||||||
response_opt[:external_content] = nil
|
opt[:external_content] = nil
|
||||||
if op and !conn_data.is_fault and op.response_use == :document
|
opt[:default_encodingstyle] = default_encodingstyle
|
||||||
response_opt[:default_encodingstyle] =
|
opt[:generate_explicit_type] = @generate_explicit_type
|
||||||
::SOAP::EncodingStyle::ASPDotNetHandler::Namespace
|
response_string = Processor.marshal(env, opt)
|
||||||
end
|
|
||||||
header = call_headers
|
|
||||||
body = SOAPBody.new(soap_response)
|
|
||||||
env = SOAPEnvelope.new(header, body)
|
|
||||||
response_string = Processor.marshal(env, response_opt)
|
|
||||||
conn_data.send_string = response_string
|
conn_data.send_string = response_string
|
||||||
if ext = response_opt[:external_content]
|
if ext = opt[:external_content]
|
||||||
|
mimeize(conn_data, ext)
|
||||||
|
end
|
||||||
|
conn_data
|
||||||
|
end
|
||||||
|
|
||||||
|
def mimeize(conn_data, ext)
|
||||||
mime = MIMEMessage.new
|
mime = MIMEMessage.new
|
||||||
ext.each do |k, v|
|
ext.each do |k, v|
|
||||||
mime.add_attachment(v.data)
|
mime.add_attachment(v.data)
|
||||||
@ -181,7 +310,7 @@ private
|
|||||||
mime.close
|
mime.close
|
||||||
conn_data.send_string = mime.content_str
|
conn_data.send_string = mime.content_str
|
||||||
conn_data.send_contenttype = mime.headers['content-type'].str
|
conn_data.send_contenttype = mime.headers['content-type'].str
|
||||||
end
|
conn_data
|
||||||
end
|
end
|
||||||
|
|
||||||
# Create fault response.
|
# Create fault response.
|
||||||
@ -194,21 +323,7 @@ private
|
|||||||
Mapping.obj2soap(detail, @mapping_registry))
|
Mapping.obj2soap(detail, @mapping_registry))
|
||||||
end
|
end
|
||||||
|
|
||||||
def fqname(qname)
|
|
||||||
"#{ qname.namespace }:#{ qname.name }"
|
|
||||||
end
|
|
||||||
|
|
||||||
def options
|
|
||||||
opt = {}
|
|
||||||
opt[:default_encodingstyle] = @default_encodingstyle
|
|
||||||
if @allow_unqualified_element
|
|
||||||
opt[:allow_unqualified_element] = true
|
|
||||||
end
|
|
||||||
opt
|
|
||||||
end
|
|
||||||
|
|
||||||
class Operation
|
class Operation
|
||||||
attr_reader :receiver
|
|
||||||
attr_reader :name
|
attr_reader :name
|
||||||
attr_reader :soapaction
|
attr_reader :soapaction
|
||||||
attr_reader :request_style
|
attr_reader :request_style
|
||||||
@ -216,62 +331,148 @@ private
|
|||||||
attr_reader :request_use
|
attr_reader :request_use
|
||||||
attr_reader :response_use
|
attr_reader :response_use
|
||||||
|
|
||||||
def initialize(qname, soapaction, receiver, name, param_def, opt)
|
def initialize(soapaction, name, param_def, opt)
|
||||||
@soapaction = soapaction
|
@soapaction = soapaction
|
||||||
@receiver = receiver
|
|
||||||
@name = name
|
@name = name
|
||||||
@request_style = opt[:request_style]
|
@request_style = opt[:request_style]
|
||||||
@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]
|
||||||
|
check_style(@request_style)
|
||||||
|
check_style(@response_style)
|
||||||
|
check_use(@request_use)
|
||||||
|
check_use(@response_use)
|
||||||
if @response_style == :rpc
|
if @response_style == :rpc
|
||||||
@rpc_response_factory =
|
request_qname = opt[:request_qname] or raise
|
||||||
RPC::SOAPMethodRequest.new(qname, param_def, @soapaction)
|
@rpc_method_factory =
|
||||||
|
RPC::SOAPMethodRequest.new(request_qname, param_def, @soapaction)
|
||||||
|
@rpc_response_qname = opt[:response_qname]
|
||||||
else
|
else
|
||||||
outputdef = param_def.find { |inout, paramname, typeinfo| inout == "output" }
|
@doc_request_qnames = []
|
||||||
klass, nsdef, namedef = outputdef[2]
|
@doc_response_qnames = []
|
||||||
@document_response_qname = ::XSD::QName.new(nsdef, namedef)
|
param_def.each do |inout, paramname, typeinfo|
|
||||||
|
klass, nsdef, namedef = typeinfo
|
||||||
|
case inout
|
||||||
|
when SOAPMethod::IN
|
||||||
|
@doc_request_qnames << XSD::QName.new(nsdef, namedef)
|
||||||
|
when SOAPMethod::OUT
|
||||||
|
@doc_response_qnames << XSD::QName.new(nsdef, namedef)
|
||||||
|
else
|
||||||
|
raise ArgumentError.new(
|
||||||
|
"illegal inout definition for document style: #{inout}")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(request, mapping_registry, literal_mapping_registry)
|
def request_default_encodingstyle
|
||||||
if @request_style == :rpc
|
(@request_use == :encoded) ? EncodingNamespace : LiteralNamespace
|
||||||
param = Mapping.soap2obj(request, mapping_registry)
|
|
||||||
result = rpc_call(request, param)
|
|
||||||
else
|
|
||||||
param = Mapping.soap2obj(request, literal_mapping_registry)
|
|
||||||
result = document_call(request, param)
|
|
||||||
end
|
end
|
||||||
if @response_style == :rpc
|
|
||||||
rpc_response(result, mapping_registry)
|
def response_default_encodingstyle
|
||||||
|
(@response_use == :encoded) ? EncodingNamespace : LiteralNamespace
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(body, mapping_registry, literal_mapping_registry)
|
||||||
|
if @request_style == :rpc
|
||||||
|
values = request_rpc(body, mapping_registry, literal_mapping_registry)
|
||||||
else
|
else
|
||||||
document_response(result, literal_mapping_registry)
|
values = request_document(body, mapping_registry, literal_mapping_registry)
|
||||||
|
end
|
||||||
|
result = receiver.method(@name.intern).call(*values)
|
||||||
|
return result if result.is_a?(SOAPFault)
|
||||||
|
if @response_style == :rpc
|
||||||
|
response_rpc(result, mapping_registry, literal_mapping_registry)
|
||||||
|
else
|
||||||
|
response_doc(result, mapping_registry, literal_mapping_registry)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def rpc_call(request, param)
|
def receiver
|
||||||
|
raise NotImplementedError.new('must be defined in derived class')
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_rpc(body, mapping_registry, literal_mapping_registry)
|
||||||
|
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
|
||||||
|
if @request_use == :encoded
|
||||||
|
request_rpc_enc(request, mapping_registry)
|
||||||
|
else
|
||||||
|
request_rpc_lit(request, literal_mapping_registry)
|
||||||
end
|
end
|
||||||
values = request.collect { |key, value| param[key] }
|
|
||||||
@receiver.method(@name.intern).call(*values)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def document_call(request, param)
|
def request_document(body, mapping_registry, literal_mapping_registry)
|
||||||
@receiver.method(@name.intern).call(param)
|
# ToDo: compare names with @doc_request_qnames
|
||||||
|
if @request_use == :encoded
|
||||||
|
request_doc_enc(body, mapping_registry)
|
||||||
|
else
|
||||||
|
request_doc_lit(body, literal_mapping_registry)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def rpc_response(result, mapping_registry)
|
def request_rpc_enc(request, mapping_registry)
|
||||||
soap_response = @rpc_response_factory.create_method_response
|
param = Mapping.soap2obj(request, mapping_registry)
|
||||||
|
request.collect { |key, value|
|
||||||
|
param[key]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_rpc_lit(request, mapping_registry)
|
||||||
|
request.collect { |key, value|
|
||||||
|
Mapping.soap2obj(value, mapping_registry)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_doc_enc(body, mapping_registry)
|
||||||
|
body.collect { |key, value|
|
||||||
|
Mapping.soap2obj(value, mapping_registry)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_doc_lit(body, mapping_registry)
|
||||||
|
body.collect { |key, value|
|
||||||
|
Mapping.soap2obj(value, mapping_registry)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_rpc(result, mapping_registry, literal_mapping_registry)
|
||||||
|
if @response_use == :encoded
|
||||||
|
response_rpc_enc(result, mapping_registry)
|
||||||
|
else
|
||||||
|
response_rpc_lit(result, literal_mapping_registry)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_doc(result, mapping_registry, literal_mapping_registry)
|
||||||
|
if @doc_response_qnames.size == 1 and !result.is_a?(Array)
|
||||||
|
result = [result]
|
||||||
|
end
|
||||||
|
if result.size != @doc_response_qnames.size
|
||||||
|
raise "required #{@doc_response_qnames.size} responses " +
|
||||||
|
"but #{result.size} given"
|
||||||
|
end
|
||||||
|
if @response_use == :encoded
|
||||||
|
response_doc_enc(result, mapping_registry)
|
||||||
|
else
|
||||||
|
response_doc_lit(result, literal_mapping_registry)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_rpc_enc(result, mapping_registry)
|
||||||
|
soap_response =
|
||||||
|
@rpc_method_factory.create_method_response(@rpc_response_qname)
|
||||||
if soap_response.have_outparam?
|
if soap_response.have_outparam?
|
||||||
unless result.is_a?(Array)
|
unless result.is_a?(Array)
|
||||||
raise RPCRoutingError.new("Out parameter was not returned.")
|
raise RPCRoutingError.new("out parameter was not returned")
|
||||||
end
|
end
|
||||||
outparams = {}
|
outparams = {}
|
||||||
i = 1
|
i = 1
|
||||||
soap_response.each_param_name('out', 'inout') 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)
|
||||||
i += 1
|
i += 1
|
||||||
end
|
end
|
||||||
@ -283,8 +484,83 @@ private
|
|||||||
soap_response
|
soap_response
|
||||||
end
|
end
|
||||||
|
|
||||||
def document_response(result, literal_mapping_registry)
|
def response_rpc_lit(result, mapping_registry)
|
||||||
literal_mapping_registry.obj2soap(result, @document_response_qname)
|
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))
|
||||||
|
i += 1
|
||||||
|
end
|
||||||
|
soap_response.set_outparam(outparams)
|
||||||
|
soap_response.retval = Mapping.obj2soap(result[0], mapping_registry,
|
||||||
|
XSD::QName.new(nil, soap_response.elename))
|
||||||
|
else
|
||||||
|
soap_response.retval = Mapping.obj2soap(result, mapping_registry,
|
||||||
|
XSD::QName.new(nil, soap_response.elename))
|
||||||
|
end
|
||||||
|
soap_response
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_doc_enc(result, mapping_registry)
|
||||||
|
(0...result.size).collect { |idx|
|
||||||
|
ele = Mapping.obj2soap(result[idx], mapping_registry)
|
||||||
|
ele.elename = @doc_response_qnames[idx]
|
||||||
|
ele
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_doc_lit(result, mapping_registry)
|
||||||
|
(0...result.size).collect { |idx|
|
||||||
|
mapping_registry.obj2soap(result[idx], @doc_response_qnames[idx])
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_style(style)
|
||||||
|
unless [:rpc, :document].include?(style)
|
||||||
|
raise ArgumentError.new("unknown style: #{style}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_use(use)
|
||||||
|
unless [:encoded, :literal].include?(use)
|
||||||
|
raise ArgumentError.new("unknown use: #{use}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class ApplicationScopeOperation < Operation
|
||||||
|
def initialize(soapaction, receiver, name, param_def, opt)
|
||||||
|
super(soapaction, name, param_def, opt)
|
||||||
|
@receiver = receiver
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def receiver
|
||||||
|
@receiver
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class RequestScopeOperation < Operation
|
||||||
|
def initialize(soapaction, receiver_factory, name, param_def, opt)
|
||||||
|
super(soapaction, name, param_def, opt)
|
||||||
|
unless receiver_factory.respond_to?(:create)
|
||||||
|
raise TypeError.new("factory must respond to 'create'")
|
||||||
|
end
|
||||||
|
@receiver_factory = receiver_factory
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def receiver
|
||||||
|
@receiver_factory.create
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# SOAP4R - SOAP handler servlet for WEBrick
|
# SOAP4R - SOAP handler servlet for WEBrick
|
||||||
# Copyright (C) 2001, 2002, 2003, 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 2001-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;
|
||||||
@ -14,7 +14,23 @@ begin
|
|||||||
require 'stringio'
|
require 'stringio'
|
||||||
require 'zlib'
|
require 'zlib'
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
STDERR.puts "Loading stringio or zlib failed. No gzipped response support." if $DEBUG
|
warn("Loading stringio or zlib failed. No gzipped response supported.") if $DEBUG
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
warn("Overriding WEBrick::Log#debug") if $DEBUG
|
||||||
|
require 'webrick/log'
|
||||||
|
module WEBrick
|
||||||
|
class Log < BasicLog
|
||||||
|
alias __debug debug
|
||||||
|
def debug(msg = nil)
|
||||||
|
if block_given? and msg.nil?
|
||||||
|
__debug(yield)
|
||||||
|
else
|
||||||
|
__debug(msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -24,61 +40,28 @@ module RPC
|
|||||||
|
|
||||||
class SOAPlet < WEBrick::HTTPServlet::AbstractServlet
|
class SOAPlet < WEBrick::HTTPServlet::AbstractServlet
|
||||||
public
|
public
|
||||||
attr_reader :app_scope_router
|
|
||||||
attr_reader :options
|
attr_reader :options
|
||||||
|
|
||||||
def initialize
|
def initialize(router = nil)
|
||||||
@rpc_router_map = {}
|
@router = router || ::SOAP::RPC::Router.new(self.class.name)
|
||||||
@app_scope_router = ::SOAP::RPC::Router.new(self.class.name)
|
|
||||||
@headerhandlerfactory = []
|
|
||||||
@app_scope_headerhandler = nil
|
|
||||||
@options = {}
|
@options = {}
|
||||||
|
@config = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
# for backward compatibility
|
||||||
|
def app_scope_router
|
||||||
|
@router
|
||||||
|
end
|
||||||
|
|
||||||
|
# for backward compatibility
|
||||||
|
def add_servant(obj, namespace)
|
||||||
|
@router.add_rpc_servant(obj, namespace)
|
||||||
end
|
end
|
||||||
|
|
||||||
def allow_content_encoding_gzip=(allow)
|
def allow_content_encoding_gzip=(allow)
|
||||||
@options[:allow_content_encoding_gzip] = allow
|
@options[:allow_content_encoding_gzip] = allow
|
||||||
end
|
end
|
||||||
|
|
||||||
# Add servant factory whose object has request scope. A servant object is
|
|
||||||
# instanciated for each request.
|
|
||||||
#
|
|
||||||
# Bear in mind that servant factories are distinguished by HTTP SOAPAction
|
|
||||||
# header in request. Client which calls request-scoped servant must have a
|
|
||||||
# SOAPAction header which is a namespace of the servant factory.
|
|
||||||
# I mean, use Driver#add_method_with_soapaction instead of Driver#add_method
|
|
||||||
# at client side.
|
|
||||||
#
|
|
||||||
# A factory must respond to :create.
|
|
||||||
#
|
|
||||||
def add_rpc_request_servant(factory, namespace, mapping_registry = nil)
|
|
||||||
unless factory.respond_to?(:create)
|
|
||||||
raise TypeError.new("factory must respond to 'create'")
|
|
||||||
end
|
|
||||||
router = setup_rpc_request_router(namespace)
|
|
||||||
router.factory = factory
|
|
||||||
router.mapping_registry = mapping_registry
|
|
||||||
end
|
|
||||||
|
|
||||||
# Add servant object which has application scope.
|
|
||||||
def add_rpc_servant(obj, namespace)
|
|
||||||
router = @app_scope_router
|
|
||||||
SOAPlet.add_rpc_servant_to_router(router, obj, namespace)
|
|
||||||
add_rpc_router(namespace, router)
|
|
||||||
end
|
|
||||||
alias add_servant add_rpc_servant
|
|
||||||
|
|
||||||
def add_rpc_request_headerhandler(factory)
|
|
||||||
unless factory.respond_to?(:create)
|
|
||||||
raise TypeError.new("factory must respond to 'create'")
|
|
||||||
end
|
|
||||||
@headerhandlerfactory << factory
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_rpc_headerhandler(obj)
|
|
||||||
@app_scope_headerhandler = obj
|
|
||||||
end
|
|
||||||
alias add_headerhandler add_rpc_headerhandler
|
|
||||||
|
|
||||||
###
|
###
|
||||||
## Servlet interfaces for WEBrick.
|
## Servlet interfaces for WEBrick.
|
||||||
#
|
#
|
||||||
@ -93,19 +76,43 @@ public
|
|||||||
|
|
||||||
def do_GET(req, res)
|
def do_GET(req, res)
|
||||||
res.header['Allow'] = 'POST'
|
res.header['Allow'] = 'POST'
|
||||||
raise WEBrick::HTTPStatus::MethodNotAllowed, "GET request not allowed."
|
raise WEBrick::HTTPStatus::MethodNotAllowed, "GET request not allowed"
|
||||||
end
|
end
|
||||||
|
|
||||||
def do_POST(req, res)
|
def do_POST(req, res)
|
||||||
@config[:Logger].debug { "SOAP request: " + req.body }
|
logger.debug { "SOAP request: " + req.body } if logger
|
||||||
soapaction = parse_soapaction(req.meta_vars['HTTP_SOAPACTION'])
|
|
||||||
router = lookup_router(soapaction)
|
|
||||||
with_headerhandler(router) do |router|
|
|
||||||
begin
|
begin
|
||||||
conn_data = ::SOAP::StreamHandler::ConnectionData.new
|
conn_data = ::SOAP::StreamHandler::ConnectionData.new
|
||||||
|
setup_req(conn_data, req)
|
||||||
|
conn_data = @router.route(conn_data)
|
||||||
|
setup_res(conn_data, req, res)
|
||||||
|
rescue Exception => e
|
||||||
|
conn_data = @router.create_fault_response(e)
|
||||||
|
res.status = WEBrick::HTTPStatus::RC_INTERNAL_SERVER_ERROR
|
||||||
|
res.body = conn_data.send_string
|
||||||
|
res['content-type'] = conn_data.send_contenttype || "text/xml"
|
||||||
|
end
|
||||||
|
if res.body.is_a?(IO)
|
||||||
|
res.chunked = true
|
||||||
|
logger.debug { "SOAP response: (chunked response not logged)" } if logger
|
||||||
|
else
|
||||||
|
logger.debug { "SOAP response: " + res.body } if logger
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def logger
|
||||||
|
@config[:Logger]
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup_req(conn_data, req)
|
||||||
conn_data.receive_string = req.body
|
conn_data.receive_string = req.body
|
||||||
conn_data.receive_contenttype = req['content-type']
|
conn_data.receive_contenttype = req['content-type']
|
||||||
conn_data = router.route(conn_data)
|
conn_data.soapaction = parse_soapaction(req.meta_vars['HTTP_SOAPACTION'])
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup_res(conn_data, req, res)
|
||||||
res['content-type'] = conn_data.send_contenttype
|
res['content-type'] = conn_data.send_contenttype
|
||||||
if conn_data.is_fault
|
if conn_data.is_fault
|
||||||
res.status = WEBrick::HTTPStatus::RC_INTERNAL_SERVER_ERROR
|
res.status = WEBrick::HTTPStatus::RC_INTERNAL_SERVER_ERROR
|
||||||
@ -117,87 +124,15 @@ public
|
|||||||
else
|
else
|
||||||
res.body = conn_data.send_string
|
res.body = conn_data.send_string
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
|
||||||
conn_data = router.create_fault_response(e)
|
|
||||||
res.status = WEBrick::HTTPStatus::RC_INTERNAL_SERVER_ERROR
|
|
||||||
res.body = conn_data.send_string
|
|
||||||
res['content-type'] = conn_data.send_contenttype || "text/xml"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if res.body.is_a?(IO)
|
|
||||||
res.chunked = true
|
|
||||||
@config[:Logger].debug { "SOAP response: (chunked response not logged)" }
|
|
||||||
else
|
|
||||||
@config[:Logger].debug { "SOAP response: " + res.body }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
class RequestRouter < ::SOAP::RPC::Router
|
|
||||||
attr_accessor :factory
|
|
||||||
|
|
||||||
def initialize(style = :rpc, namespace = nil)
|
|
||||||
super(namespace)
|
|
||||||
@style = style
|
|
||||||
@namespace = namespace
|
|
||||||
@factory = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def route(soap_string)
|
|
||||||
obj = @factory.create
|
|
||||||
namespace = self.actor
|
|
||||||
router = ::SOAP::RPC::Router.new(@namespace)
|
|
||||||
if @style == :rpc
|
|
||||||
SOAPlet.add_rpc_servant_to_router(router, obj, namespace)
|
|
||||||
else
|
|
||||||
raise RuntimeError.new("'document' style not supported.")
|
|
||||||
end
|
|
||||||
router.route(soap_string)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def setup_rpc_request_router(namespace)
|
|
||||||
router = @rpc_router_map[namespace] || RequestRouter.new(:rpc, namespace)
|
|
||||||
add_rpc_router(namespace, router)
|
|
||||||
router
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_rpc_router(namespace, router)
|
|
||||||
@rpc_router_map[namespace] = router
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_soapaction(soapaction)
|
def parse_soapaction(soapaction)
|
||||||
if /^"(.*)"$/ =~ soapaction
|
if !soapaction.nil? and !soapaction.empty?
|
||||||
soapaction = $1
|
if /^"(.+)"$/ =~ soapaction
|
||||||
end
|
return $1
|
||||||
if soapaction.empty?
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
soapaction
|
|
||||||
end
|
|
||||||
|
|
||||||
def lookup_router(namespace)
|
|
||||||
if namespace
|
|
||||||
@rpc_router_map[namespace] || @app_scope_router
|
|
||||||
else
|
|
||||||
@app_scope_router
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
nil
|
||||||
def with_headerhandler(router)
|
|
||||||
if @app_scope_headerhandler and
|
|
||||||
!router.headerhandler.include?(@app_scope_headerhandler)
|
|
||||||
router.headerhandler.add(@app_scope_headerhandler)
|
|
||||||
end
|
|
||||||
handlers = @headerhandlerfactory.collect { |f| f.create }
|
|
||||||
begin
|
|
||||||
handlers.each { |h| router.headerhandler.add(h) }
|
|
||||||
yield(router)
|
|
||||||
ensure
|
|
||||||
handlers.each { |h| router.headerhandler.delete(h) }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def encode_gzip(req, outstring)
|
def encode_gzip(req, outstring)
|
||||||
@ -219,32 +154,6 @@ private
|
|||||||
req['accept-encoding'] and
|
req['accept-encoding'] and
|
||||||
req['accept-encoding'].split(/,\s*/).include?('gzip')
|
req['accept-encoding'].split(/,\s*/).include?('gzip')
|
||||||
end
|
end
|
||||||
|
|
||||||
class << self
|
|
||||||
public
|
|
||||||
def add_rpc_servant_to_router(router, obj, namespace)
|
|
||||||
::SOAP::RPC.defined_methods(obj).each do |name|
|
|
||||||
begin
|
|
||||||
add_rpc_servant_method_to_router(router, obj, namespace, name)
|
|
||||||
rescue SOAP::RPC::MethodDefinitionError => e
|
|
||||||
p e if $DEBUG
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_rpc_servant_method_to_router(router, obj, namespace, name,
|
|
||||||
style = :rpc, use = :encoded)
|
|
||||||
qname = XSD::QName.new(namespace, name)
|
|
||||||
soapaction = nil
|
|
||||||
method = obj.method(name)
|
|
||||||
param_def = ::SOAP::RPC::SOAPMethod.create_param_def(
|
|
||||||
(1..method.arity.abs).collect { |i| "p#{ i }" })
|
|
||||||
opt = {}
|
|
||||||
opt[:request_style] = opt[:response_style] = style
|
|
||||||
opt[:request_use] = opt[:response_use] = use
|
|
||||||
router.add_operation(qname, soapaction, obj, name, param_def, opt)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ require 'xsd/charset'
|
|||||||
module SOAP
|
module SOAP
|
||||||
|
|
||||||
|
|
||||||
Version = '1.5.3-ruby1.8.2'
|
VERSION = Version = '1.5.4'
|
||||||
PropertyName = 'soap/property'
|
PropertyName = 'soap/property'
|
||||||
|
|
||||||
EnvelopeNamespace = 'http://schemas.xmlsoap.org/soap/envelope/'
|
EnvelopeNamespace = 'http://schemas.xmlsoap.org/soap/envelope/'
|
||||||
@ -75,6 +75,7 @@ class ArrayIndexOutOfBoundsError < Error; end
|
|||||||
class ArrayStoreError < Error; end
|
class ArrayStoreError < Error; end
|
||||||
|
|
||||||
class RPCRoutingError < Error; end
|
class RPCRoutingError < Error; end
|
||||||
|
class EmptyResponseError < Error; end
|
||||||
|
|
||||||
class UnhandledMustUnderstandHeaderError < Error; end
|
class UnhandledMustUnderstandHeaderError < Error; end
|
||||||
|
|
||||||
@ -101,6 +102,7 @@ class FaultError < Error
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
module Env
|
module Env
|
||||||
def self.getenv(name)
|
def self.getenv(name)
|
||||||
ENV[name.downcase] || ENV[name.upcase]
|
ENV[name.downcase] || ENV[name.upcase]
|
||||||
@ -113,3 +115,25 @@ end
|
|||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
unless Object.respond_to?(:instance_variable_get)
|
||||||
|
class Object
|
||||||
|
def instance_variable_get(ivarname)
|
||||||
|
instance_eval(ivarname)
|
||||||
|
end
|
||||||
|
|
||||||
|
def instance_variable_set(ivarname, value)
|
||||||
|
instance_eval("#{ivarname} = value")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
unless Kernel.respond_to?(:warn)
|
||||||
|
module Kernel
|
||||||
|
def warn(msg)
|
||||||
|
STDERR.puts(msg + "\n") unless $VERBOSE.nil?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
|
|
||||||
require 'soap/soap'
|
require 'soap/soap'
|
||||||
require 'soap/property'
|
require 'soap/httpconfigloader'
|
||||||
begin
|
begin
|
||||||
require 'stringio'
|
require 'stringio'
|
||||||
require 'zlib'
|
require 'zlib'
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
STDERR.puts "Loading stringio or zlib failed. No gzipped response support." if $DEBUG
|
warn("Loading stringio or zlib failed. No gzipped response support.") if $DEBUG
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ class StreamHandler
|
|||||||
end
|
end
|
||||||
HTTPAccess2::Client
|
HTTPAccess2::Client
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
STDERR.puts "Loading http-access2 failed. Net/http is used." if $DEBUG
|
warn("Loading http-access2 failed. Net/http is used.") if $DEBUG
|
||||||
require 'soap/netHttpClient'
|
require 'soap/netHttpClient'
|
||||||
SOAP::NetHttpClient
|
SOAP::NetHttpClient
|
||||||
end
|
end
|
||||||
@ -40,6 +40,7 @@ class StreamHandler
|
|||||||
attr_accessor :receive_string
|
attr_accessor :receive_string
|
||||||
attr_accessor :receive_contenttype
|
attr_accessor :receive_contenttype
|
||||||
attr_accessor :is_fault
|
attr_accessor :is_fault
|
||||||
|
attr_accessor :soapaction
|
||||||
|
|
||||||
def initialize(send_string = nil)
|
def initialize(send_string = nil)
|
||||||
@send_string = send_string
|
@send_string = send_string
|
||||||
@ -47,6 +48,7 @@ class StreamHandler
|
|||||||
@receive_string = nil
|
@receive_string = nil
|
||||||
@receive_contenttype = nil
|
@receive_contenttype = nil
|
||||||
@is_fault = false
|
@is_fault = false
|
||||||
|
@soapaction = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -79,7 +81,7 @@ public
|
|||||||
super()
|
super()
|
||||||
@client = Client.new(nil, "SOAP4R/#{ Version }")
|
@client = Client.new(nil, "SOAP4R/#{ Version }")
|
||||||
@wiredump_file_base = nil
|
@wiredump_file_base = nil
|
||||||
@charset = @wiredump_dev = @nil
|
@charset = @wiredump_dev = nil
|
||||||
@options = options
|
@options = options
|
||||||
set_options
|
set_options
|
||||||
@client.debug_dev = @wiredump_dev
|
@client.debug_dev = @wiredump_dev
|
||||||
@ -100,7 +102,8 @@ public
|
|||||||
end
|
end
|
||||||
|
|
||||||
def send(endpoint_url, conn_data, soapaction = nil, charset = @charset)
|
def send(endpoint_url, conn_data, soapaction = nil, charset = @charset)
|
||||||
send_post(endpoint_url, conn_data, soapaction, charset)
|
conn_data.soapaction ||= soapaction # for backward conpatibility
|
||||||
|
send_post(endpoint_url, conn_data, charset)
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset(endpoint_url = nil)
|
def reset(endpoint_url = nil)
|
||||||
@ -115,24 +118,7 @@ public
|
|||||||
private
|
private
|
||||||
|
|
||||||
def set_options
|
def set_options
|
||||||
@client.proxy = @options["proxy"]
|
HTTPConfigLoader.set_options(@client, @options)
|
||||||
@options.add_hook("proxy") do |key, value|
|
|
||||||
@client.proxy = value
|
|
||||||
end
|
|
||||||
@client.no_proxy = @options["no_proxy"]
|
|
||||||
@options.add_hook("no_proxy") do |key, value|
|
|
||||||
@client.no_proxy = value
|
|
||||||
end
|
|
||||||
if @client.respond_to?(:protocol_version=)
|
|
||||||
@client.protocol_version = @options["protocol_version"]
|
|
||||||
@options.add_hook("protocol_version") do |key, value|
|
|
||||||
@client.protocol_version = value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
set_cookie_store_file(@options["cookie_store_file"])
|
|
||||||
@options.add_hook("cookie_store_file") do |key, value|
|
|
||||||
set_cookie_store_file(value)
|
|
||||||
end
|
|
||||||
@charset = @options["charset"] || XSD::Charset.charset_label($KCODE)
|
@charset = @options["charset"] || XSD::Charset.charset_label($KCODE)
|
||||||
@options.add_hook("charset") do |key, value|
|
@options.add_hook("charset") do |key, value|
|
||||||
@charset = value
|
@charset = value
|
||||||
@ -142,96 +128,23 @@ private
|
|||||||
@wiredump_dev = value
|
@wiredump_dev = value
|
||||||
@client.debug_dev = @wiredump_dev
|
@client.debug_dev = @wiredump_dev
|
||||||
end
|
end
|
||||||
ssl_config = @options["ssl_config"] ||= ::SOAP::Property.new
|
set_cookie_store_file(@options["cookie_store_file"])
|
||||||
set_ssl_config(ssl_config)
|
@options.add_hook("cookie_store_file") do |key, value|
|
||||||
ssl_config.add_hook(true) do |key, value|
|
set_cookie_store_file(value)
|
||||||
set_ssl_config(ssl_config)
|
|
||||||
end
|
|
||||||
basic_auth = @options["basic_auth"] ||= ::SOAP::Property.new
|
|
||||||
set_basic_auth(basic_auth)
|
|
||||||
basic_auth.add_hook do |key, value|
|
|
||||||
set_basic_auth(basic_auth)
|
|
||||||
end
|
|
||||||
@options.add_hook("connect_timeout") do |key, value|
|
|
||||||
@client.connect_timeout = value
|
|
||||||
end
|
|
||||||
@options.add_hook("send_timeout") do |key, value|
|
|
||||||
@client.send_timeout = value
|
|
||||||
end
|
|
||||||
@options.add_hook("receive_timeout") do |key, value|
|
|
||||||
@client.receive_timeout = value
|
|
||||||
end
|
end
|
||||||
|
ssl_config = @options["ssl_config"]
|
||||||
|
basic_auth = @options["basic_auth"]
|
||||||
@options.lock(true)
|
@options.lock(true)
|
||||||
ssl_config.unlock
|
ssl_config.unlock
|
||||||
basic_auth.unlock
|
basic_auth.unlock
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_basic_auth(basic_auth)
|
|
||||||
basic_auth.values.each do |url, userid, passwd|
|
|
||||||
@client.set_basic_auth(url, userid, passwd)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_cookie_store_file(value)
|
def set_cookie_store_file(value)
|
||||||
@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
|
||||||
|
|
||||||
def set_ssl_config(ssl_config)
|
def send_post(endpoint_url, conn_data, charset)
|
||||||
ssl_config.each do |key, value|
|
|
||||||
cfg = @client.ssl_config
|
|
||||||
case key
|
|
||||||
when 'client_cert'
|
|
||||||
cfg.client_cert = cert_from_file(value)
|
|
||||||
when 'client_key'
|
|
||||||
cfg.client_key = key_from_file(value)
|
|
||||||
when 'client_ca'
|
|
||||||
cfg.client_ca = value
|
|
||||||
when 'ca_path'
|
|
||||||
cfg.set_trust_ca(value)
|
|
||||||
when 'ca_file'
|
|
||||||
cfg.set_trust_ca(value)
|
|
||||||
when 'crl'
|
|
||||||
cfg.set_crl(value)
|
|
||||||
when 'verify_mode'
|
|
||||||
cfg.verify_mode = ssl_config_int(value)
|
|
||||||
when 'verify_depth'
|
|
||||||
cfg.verify_depth = ssl_config_int(value)
|
|
||||||
when 'options'
|
|
||||||
cfg.options = value
|
|
||||||
when 'ciphers'
|
|
||||||
cfg.ciphers = value
|
|
||||||
when 'verify_callback'
|
|
||||||
cfg.verify_callback = value
|
|
||||||
when 'cert_store'
|
|
||||||
cfg.cert_store = value
|
|
||||||
else
|
|
||||||
raise ArgumentError.new("unknown ssl_config property #{key}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def ssl_config_int(value)
|
|
||||||
if value.nil? or value.empty?
|
|
||||||
nil
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
Integer(value)
|
|
||||||
rescue ArgumentError
|
|
||||||
::SOAP::Property::Util.const_from_name(value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def cert_from_file(filename)
|
|
||||||
OpenSSL::X509::Certificate.new(File.open(filename) { |f| f.read })
|
|
||||||
end
|
|
||||||
|
|
||||||
def key_from_file(filename)
|
|
||||||
OpenSSL::PKey::RSA.new(File.open(filename) { |f| f.read })
|
|
||||||
end
|
|
||||||
|
|
||||||
def send_post(endpoint_url, conn_data, soapaction, charset)
|
|
||||||
conn_data.send_contenttype ||= StreamHandler.create_media_type(charset)
|
conn_data.send_contenttype ||= StreamHandler.create_media_type(charset)
|
||||||
|
|
||||||
if @wiredump_file_base
|
if @wiredump_file_base
|
||||||
@ -243,7 +156,7 @@ private
|
|||||||
|
|
||||||
extra = {}
|
extra = {}
|
||||||
extra['Content-Type'] = conn_data.send_contenttype
|
extra['Content-Type'] = conn_data.send_contenttype
|
||||||
extra['SOAPAction'] = "\"#{ soapaction }\""
|
extra['SOAPAction'] = "\"#{ conn_data.soapaction }\""
|
||||||
extra['Accept-Encoding'] = 'gzip' if send_accept_encoding_gzip?
|
extra['Accept-Encoding'] = 'gzip' if send_accept_encoding_gzip?
|
||||||
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
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# SOAP4R - SOAP WSDL driver
|
# SOAP4R - SOAP WSDL driver
|
||||||
# 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;
|
||||||
@ -9,19 +9,11 @@
|
|||||||
require 'wsdl/parser'
|
require 'wsdl/parser'
|
||||||
require 'wsdl/importer'
|
require 'wsdl/importer'
|
||||||
require 'xsd/qname'
|
require 'xsd/qname'
|
||||||
require 'soap/element'
|
require 'xsd/codegen/gensupport'
|
||||||
require 'soap/baseData'
|
|
||||||
require 'soap/streamHandler'
|
|
||||||
require 'soap/mimemessage'
|
|
||||||
require 'soap/mapping'
|
|
||||||
require 'soap/mapping/wsdlencodedregistry'
|
require 'soap/mapping/wsdlencodedregistry'
|
||||||
require 'soap/mapping/wsdlliteralregistry'
|
require 'soap/mapping/wsdlliteralregistry'
|
||||||
require 'soap/rpc/rpc'
|
require 'soap/rpc/driver'
|
||||||
require 'soap/rpc/element'
|
require 'wsdl/soap/methodDefCreator'
|
||||||
require 'soap/rpc/proxy'
|
|
||||||
require 'soap/processor'
|
|
||||||
require 'soap/header/handlerset'
|
|
||||||
require 'xsd/codegen/gensupport'
|
|
||||||
|
|
||||||
|
|
||||||
module SOAP
|
module SOAP
|
||||||
@ -32,35 +24,27 @@ class WSDLDriverFactory
|
|||||||
|
|
||||||
attr_reader :wsdl
|
attr_reader :wsdl
|
||||||
|
|
||||||
def initialize(wsdl, logdev = nil)
|
def initialize(wsdl)
|
||||||
@logdev = logdev
|
|
||||||
@wsdl = import(wsdl)
|
@wsdl = import(wsdl)
|
||||||
|
@methoddefcreator = WSDL::SOAP::MethodDefCreator.new(@wsdl)
|
||||||
end
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
"#<#{self.class}:#{@wsdl.name}>"
|
"#<#{self.class}:#{@wsdl.name}>"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create_rpc_driver(servicename = nil, portname = nil)
|
||||||
|
port = find_port(servicename, portname)
|
||||||
|
drv = SOAP::RPC::Driver.new(port.soap_address.location)
|
||||||
|
init_driver(drv, port)
|
||||||
|
add_operation(drv, port)
|
||||||
|
drv
|
||||||
|
end
|
||||||
|
|
||||||
|
# depricated old interface
|
||||||
def create_driver(servicename = nil, portname = nil)
|
def create_driver(servicename = nil, portname = nil)
|
||||||
service = if servicename
|
warn("WSDLDriverFactory#create_driver is depricated. Use create_rpc_driver instead.")
|
||||||
@wsdl.service(XSD::QName.new(@wsdl.targetnamespace, servicename))
|
port = find_port(servicename, portname)
|
||||||
else
|
|
||||||
@wsdl.services[0]
|
|
||||||
end
|
|
||||||
if service.nil?
|
|
||||||
raise FactoryError.new("Service #{ servicename } not found in WSDL.")
|
|
||||||
end
|
|
||||||
port = if portname
|
|
||||||
service.ports[XSD::QName.new(@wsdl.targetnamespace, portname)]
|
|
||||||
else
|
|
||||||
service.ports[0]
|
|
||||||
end
|
|
||||||
if port.nil?
|
|
||||||
raise FactoryError.new("Port #{ portname } not found in WSDL.")
|
|
||||||
end
|
|
||||||
if port.soap_address.nil?
|
|
||||||
raise FactoryError.new("soap:address element not found in WSDL.")
|
|
||||||
end
|
|
||||||
WSDLDriver.new(@wsdl, port, @logdev)
|
WSDLDriver.new(@wsdl, port, @logdev)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -69,14 +53,110 @@ class WSDLDriverFactory
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def find_port(servicename = nil, portname = nil)
|
||||||
|
service = port = nil
|
||||||
|
if servicename
|
||||||
|
service = @wsdl.service(
|
||||||
|
XSD::QName.new(@wsdl.targetnamespace, servicename))
|
||||||
|
else
|
||||||
|
service = @wsdl.services[0]
|
||||||
|
end
|
||||||
|
if service.nil?
|
||||||
|
raise FactoryError.new("service #{servicename} not found in WSDL")
|
||||||
|
end
|
||||||
|
if portname
|
||||||
|
port = service.ports[XSD::QName.new(@wsdl.targetnamespace, portname)]
|
||||||
|
else
|
||||||
|
port = service.ports[0]
|
||||||
|
end
|
||||||
|
if port.nil?
|
||||||
|
raise FactoryError.new("port #{portname} not found in WSDL")
|
||||||
|
end
|
||||||
|
if port.soap_address.nil?
|
||||||
|
raise FactoryError.new("soap:address element not found in WSDL")
|
||||||
|
end
|
||||||
|
port
|
||||||
|
end
|
||||||
|
|
||||||
|
def init_driver(drv, port)
|
||||||
|
wsdl_elements = @wsdl.collect_elements
|
||||||
|
wsdl_types = @wsdl.collect_complextypes + @wsdl.collect_simpletypes
|
||||||
|
rpc_decode_typemap = wsdl_types +
|
||||||
|
@wsdl.soap_rpc_complextypes(port.find_binding)
|
||||||
|
drv.proxy.mapping_registry =
|
||||||
|
Mapping::WSDLEncodedRegistry.new(rpc_decode_typemap)
|
||||||
|
drv.proxy.literal_mapping_registry =
|
||||||
|
Mapping::WSDLLiteralRegistry.new(wsdl_types, wsdl_elements)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_operation(drv, port)
|
||||||
|
port.find_binding.operations.each do |op_bind|
|
||||||
|
op_name = op_bind.soapoperation_name
|
||||||
|
soapaction = op_bind.soapaction || ''
|
||||||
|
orgname = op_name.name
|
||||||
|
name = XSD::CodeGen::GenSupport.safemethodname(orgname)
|
||||||
|
param_def = create_param_def(op_bind)
|
||||||
|
opt = {}
|
||||||
|
opt[:request_style] = opt[:response_style] = op_bind.soapoperation_style
|
||||||
|
opt[:request_use] = (op_bind.input.soapbody.use || 'literal').intern
|
||||||
|
opt[:response_use] = (op_bind.output.soapbody.use || 'literal').intern
|
||||||
|
if op_bind.soapoperation_style == :rpc
|
||||||
|
drv.add_rpc_operation(op_name, soapaction, name, param_def, opt)
|
||||||
|
else
|
||||||
|
drv.add_document_operation(soapaction, name, param_def, opt)
|
||||||
|
end
|
||||||
|
if orgname != name and orgname.capitalize == name.capitalize
|
||||||
|
::SOAP::Mapping.define_singleton_method(drv, orgname) do |*arg|
|
||||||
|
__send__(name, *arg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def import(location)
|
def import(location)
|
||||||
WSDL::Importer.import(location)
|
WSDL::Importer.import(location)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create_param_def(op_bind)
|
||||||
|
op = op_bind.find_operation
|
||||||
|
if op_bind.soapoperation_style == :rpc
|
||||||
|
param_def = @methoddefcreator.collect_rpcparameter(op)
|
||||||
|
else
|
||||||
|
param_def = @methoddefcreator.collect_documentparameter(op)
|
||||||
|
end
|
||||||
|
# the first element of typedef in param_def is a String like
|
||||||
|
# "::SOAP::SOAPStruct". turn this String to a class.
|
||||||
|
param_def.collect { |io, typedef, name|
|
||||||
|
typedef[0] = Mapping.class_from_name(typedef[0])
|
||||||
|
[io, name, typedef]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def partqname(part)
|
||||||
|
if part.type
|
||||||
|
part.type
|
||||||
|
else
|
||||||
|
part.element
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def param_def(type, name, klass, partqname)
|
||||||
|
[type, name, [klass, partqname.namespace, partqname.name]]
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter_parts(partsdef, partssource)
|
||||||
|
parts = partsdef.split(/\s+/)
|
||||||
|
partssource.find_all { |part| parts.include?(part.name) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
class WSDLDriver
|
class WSDLDriver
|
||||||
class << self
|
class << self
|
||||||
|
def __attr_proxy(symbol, assignable = false)
|
||||||
|
end
|
||||||
|
|
||||||
|
if RUBY_VERSION >= "1.7.0"
|
||||||
def __attr_proxy(symbol, assignable = false)
|
def __attr_proxy(symbol, assignable = false)
|
||||||
name = symbol.to_s
|
name = symbol.to_s
|
||||||
self.__send__(:define_method, name, proc {
|
self.__send__(:define_method, name, proc {
|
||||||
@ -88,6 +168,23 @@ class WSDLDriver
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
def __attr_proxy(symbol, assignable = false)
|
||||||
|
name = symbol.to_s
|
||||||
|
module_eval <<-EOS
|
||||||
|
def #{name}
|
||||||
|
@servant.#{name}
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
if assignable
|
||||||
|
module_eval <<-EOS
|
||||||
|
def #{name}=(value)
|
||||||
|
@servant.#{name} = value
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
__attr_proxy :options
|
__attr_proxy :options
|
||||||
@ -179,8 +276,10 @@ class WSDLDriver
|
|||||||
@wsdl_types = @wsdl.collect_complextypes + @wsdl.collect_simpletypes
|
@wsdl_types = @wsdl.collect_complextypes + @wsdl.collect_simpletypes
|
||||||
@rpc_decode_typemap = @wsdl_types +
|
@rpc_decode_typemap = @wsdl_types +
|
||||||
@wsdl.soap_rpc_complextypes(port.find_binding)
|
@wsdl.soap_rpc_complextypes(port.find_binding)
|
||||||
@wsdl_mapping_registry = Mapping::WSDLEncodedRegistry.new(@rpc_decode_typemap)
|
@wsdl_mapping_registry = Mapping::WSDLEncodedRegistry.new(
|
||||||
@doc_mapper = Mapping::WSDLLiteralRegistry.new(@wsdl_elements, @wsdl_types)
|
@rpc_decode_typemap)
|
||||||
|
@doc_mapper = Mapping::WSDLLiteralRegistry.new(
|
||||||
|
@wsdl_types, @wsdl_elements)
|
||||||
endpoint_url = @port.soap_address.location
|
endpoint_url = @port.soap_address.location
|
||||||
# Convert a map which key is QName, to a Hash which key is String.
|
# Convert a map which key is QName, to a Hash which key is String.
|
||||||
@operation = {}
|
@operation = {}
|
||||||
@ -222,15 +321,16 @@ class WSDLDriver
|
|||||||
def rpc_call(name, *values)
|
def rpc_call(name, *values)
|
||||||
set_wiredump_file_base(name)
|
set_wiredump_file_base(name)
|
||||||
unless op_info = @operation[name]
|
unless op_info = @operation[name]
|
||||||
raise MethodDefinitionError, "Method: #{name} not defined."
|
raise RuntimeError, "method: #{name} not defined"
|
||||||
end
|
end
|
||||||
req_header = create_request_header
|
req_header = create_request_header
|
||||||
req_body = create_request_body(op_info, *values)
|
req_body = create_request_body(op_info, *values)
|
||||||
opt = create_options({
|
reqopt = create_options({
|
||||||
:soapaction => op_info.soapaction || @soapaction,
|
:soapaction => op_info.soapaction || @soapaction})
|
||||||
|
resopt = create_options({
|
||||||
:decode_typemap => @rpc_decode_typemap})
|
:decode_typemap => @rpc_decode_typemap})
|
||||||
env = @proxy.invoke(req_header, req_body, opt)
|
env = @proxy.route(req_header, req_body, reqopt, resopt)
|
||||||
raise EmptyResponseError.new("Empty response.") unless env
|
raise EmptyResponseError unless env
|
||||||
receive_headers(env.header)
|
receive_headers(env.header)
|
||||||
begin
|
begin
|
||||||
@proxy.check_fault(env.body)
|
@proxy.check_fault(env.body)
|
||||||
@ -249,21 +349,6 @@ class WSDLDriver
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def document_call(name, param)
|
|
||||||
set_wiredump_file_base(name)
|
|
||||||
op_info = @operation[name]
|
|
||||||
req_header = header_from_obj(header_obj, op_info)
|
|
||||||
req_body = body_from_obj(body_obj, op_info)
|
|
||||||
env = @proxy.invoke(req_header, req_body, op_info.soapaction || @soapaction, @wsdl_types)
|
|
||||||
raise EmptyResponseError.new("Empty response.") unless env
|
|
||||||
if env.body.fault
|
|
||||||
raise ::SOAP::FaultError.new(env.body.fault)
|
|
||||||
end
|
|
||||||
res_body_obj = env.body.response ?
|
|
||||||
Mapping.soap2obj(env.body.response, @mapping_registry) : nil
|
|
||||||
return env.header, res_body_obj
|
|
||||||
end
|
|
||||||
|
|
||||||
# req_header: [[element, mustunderstand, encodingstyle(QName/String)], ...]
|
# req_header: [[element, mustunderstand, encodingstyle(QName/String)], ...]
|
||||||
# req_body: SOAPBasetype/SOAPCompoundtype
|
# req_body: SOAPBasetype/SOAPCompoundtype
|
||||||
def document_send(name, header_obj, body_obj)
|
def document_send(name, header_obj, body_obj)
|
||||||
@ -275,7 +360,7 @@ class WSDLDriver
|
|||||||
:soapaction => op_info.soapaction || @soapaction,
|
:soapaction => op_info.soapaction || @soapaction,
|
||||||
:decode_typemap => @wsdl_types})
|
:decode_typemap => @wsdl_types})
|
||||||
env = @proxy.invoke(req_header, req_body, opt)
|
env = @proxy.invoke(req_header, req_body, opt)
|
||||||
raise EmptyResponseError.new("Empty response.") unless env
|
raise EmptyResponseError unless env
|
||||||
if env.body.fault
|
if env.body.fault
|
||||||
raise ::SOAP::FaultError.new(env.body.fault)
|
raise ::SOAP::FaultError.new(env.body.fault)
|
||||||
end
|
end
|
||||||
@ -297,7 +382,7 @@ class WSDLDriver
|
|||||||
|
|
||||||
def set_wiredump_file_base(name)
|
def set_wiredump_file_base(name)
|
||||||
if @wiredump_file_base
|
if @wiredump_file_base
|
||||||
@proxy.set_wiredump_file_base(@wiredump_file_base + "_#{ name }")
|
@proxy.set_wiredump_file_base(@wiredump_file_base + "_#{name}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -326,7 +411,7 @@ class WSDLDriver
|
|||||||
def create_method_struct(op_info, *params)
|
def create_method_struct(op_info, *params)
|
||||||
parts_names = op_info.bodyparts.collect { |part| part.name }
|
parts_names = op_info.bodyparts.collect { |part| part.name }
|
||||||
obj = create_method_obj(parts_names, params)
|
obj = create_method_obj(parts_names, params)
|
||||||
method = Mapping.obj2soap(obj, @wsdl_mapping_registry, op_info.optype_name)
|
method = Mapping.obj2soap(obj, @wsdl_mapping_registry, op_info.op_name)
|
||||||
if method.members.size != parts_names.size
|
if method.members.size != parts_names.size
|
||||||
new_method = SOAPStruct.new
|
new_method = SOAPStruct.new
|
||||||
method.each do |key, value|
|
method.each do |key, value|
|
||||||
@ -356,7 +441,7 @@ class WSDLDriver
|
|||||||
if obj.nil?
|
if obj.nil?
|
||||||
nil
|
nil
|
||||||
else
|
else
|
||||||
raise RuntimeError.new("No header definition in schema.")
|
raise RuntimeError.new("no header definition in schema: #{obj}")
|
||||||
end
|
end
|
||||||
elsif op_info.headerparts.size == 1
|
elsif op_info.headerparts.size == 1
|
||||||
part = op_info.headerparts[0]
|
part = op_info.headerparts[0]
|
||||||
@ -366,7 +451,7 @@ class WSDLDriver
|
|||||||
else
|
else
|
||||||
header = SOAPHeader.new()
|
header = SOAPHeader.new()
|
||||||
op_info.headerparts.each do |part|
|
op_info.headerparts.each do |part|
|
||||||
child = Mapping.find_attribute(obj, part.name)
|
child = Mapping.get_attribute(obj, part.name)
|
||||||
ele = headeritem_from_obj(child, part.element || part.eletype)
|
ele = headeritem_from_obj(child, part.element || part.eletype)
|
||||||
header.add(part.name, ele)
|
header.add(part.name, ele)
|
||||||
end
|
end
|
||||||
@ -391,7 +476,7 @@ class WSDLDriver
|
|||||||
if obj.nil?
|
if obj.nil?
|
||||||
nil
|
nil
|
||||||
else
|
else
|
||||||
raise RuntimeError.new("No body found in schema.")
|
raise RuntimeError.new("no body found in schema")
|
||||||
end
|
end
|
||||||
elsif op_info.bodyparts.size == 1
|
elsif op_info.bodyparts.size == 1
|
||||||
part = op_info.bodyparts[0]
|
part = op_info.bodyparts[0]
|
||||||
@ -400,7 +485,7 @@ class WSDLDriver
|
|||||||
else
|
else
|
||||||
body = SOAPBody.new
|
body = SOAPBody.new
|
||||||
op_info.bodyparts.each do |part|
|
op_info.bodyparts.each do |part|
|
||||||
child = Mapping.find_attribute(obj, part.name)
|
child = Mapping.get_attribute(obj, part.name)
|
||||||
ele = bodyitem_from_obj(child, part.element || part.type)
|
ele = bodyitem_from_obj(child, part.element || part.type)
|
||||||
body.add(ele.elename.name, ele)
|
body.add(ele.elename.name, ele)
|
||||||
end
|
end
|
||||||
@ -419,39 +504,40 @@ class WSDLDriver
|
|||||||
end
|
end
|
||||||
|
|
||||||
def add_method_interface(op_info)
|
def add_method_interface(op_info)
|
||||||
name = ::XSD::CodeGen::GenSupport.safemethodname(op_info.op_name.name)
|
name = XSD::CodeGen::GenSupport.safemethodname(op_info.op_name.name)
|
||||||
|
orgname = op_info.op_name.name
|
||||||
|
parts_names = op_info.bodyparts.collect { |part| part.name }
|
||||||
case op_info.style
|
case op_info.style
|
||||||
when :document
|
when :document
|
||||||
add_document_method_interface(name)
|
if orgname != name and orgname.capitalize == name.capitalize
|
||||||
|
add_document_method_interface(orgname, parts_names)
|
||||||
|
end
|
||||||
|
add_document_method_interface(name, parts_names)
|
||||||
when :rpc
|
when :rpc
|
||||||
parts_names = op_info.bodyparts.collect { |part| part.name }
|
|
||||||
orgname = op_info.op_name.name
|
|
||||||
if orgname != name and orgname.capitalize == name.capitalize
|
if orgname != name and orgname.capitalize == name.capitalize
|
||||||
add_rpc_method_interface(orgname, parts_names)
|
add_rpc_method_interface(orgname, parts_names)
|
||||||
end
|
end
|
||||||
add_rpc_method_interface(name, parts_names)
|
add_rpc_method_interface(name, parts_names)
|
||||||
else
|
else
|
||||||
raise RuntimeError.new("Unknown style: #{op_info.style}")
|
raise RuntimeError.new("unknown style: #{op_info.style}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_rpc_method_interface(name, parts_names)
|
def add_rpc_method_interface(name, parts_names)
|
||||||
sclass = class << @host; self; end
|
::SOAP::Mapping.define_singleton_method(@host, name) do |*arg|
|
||||||
sclass.__send__(:define_method, name, proc { |*arg|
|
|
||||||
unless arg.size == parts_names.size
|
unless arg.size == parts_names.size
|
||||||
raise ArgumentError.new(
|
raise ArgumentError.new(
|
||||||
"wrong number of arguments (#{arg.size} for #{parts_names.size})")
|
"wrong number of arguments (#{arg.size} for #{parts_names.size})")
|
||||||
end
|
end
|
||||||
@servant.rpc_call(name, *arg)
|
@servant.rpc_call(name, *arg)
|
||||||
})
|
end
|
||||||
@host.method(name)
|
@host.method(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_document_method_interface(name)
|
def add_document_method_interface(name, parts_names)
|
||||||
sclass = class << @host; self; end
|
::SOAP::Mapping.define_singleton_method(@host, name) do |*arg|
|
||||||
sclass.__send__(:define_method, name, proc { |h, b|
|
|
||||||
@servant.document_send(name, h, b)
|
@servant.document_send(name, h, b)
|
||||||
})
|
end
|
||||||
@host.method(name)
|
@host.method(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -476,5 +562,3 @@ end
|
|||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,19 +18,16 @@ class Definitions < Info
|
|||||||
attr_reader :targetnamespace
|
attr_reader :targetnamespace
|
||||||
attr_reader :imports
|
attr_reader :imports
|
||||||
|
|
||||||
# Overrides Info#root
|
attr_accessor :location
|
||||||
def root
|
attr_reader :importedschema
|
||||||
@root
|
|
||||||
end
|
|
||||||
|
|
||||||
def root=(root)
|
|
||||||
@root = root
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
@name = nil
|
@name = nil
|
||||||
@targetnamespace = nil
|
@targetnamespace = nil
|
||||||
|
@location = nil
|
||||||
|
@importedschema = {}
|
||||||
|
|
||||||
@types = nil
|
@types = nil
|
||||||
@imports = []
|
@imports = []
|
||||||
@messages = XSD::NamedElements.new
|
@messages = XSD::NamedElements.new
|
||||||
@ -53,6 +50,19 @@ class Definitions < Info
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def collect_attributes
|
||||||
|
result = XSD::NamedElements.new
|
||||||
|
if @types
|
||||||
|
@types.schemas.each do |schema|
|
||||||
|
result.concat(schema.collect_attributes)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@imports.each do |import|
|
||||||
|
result.concat(import.content.collect_attributes)
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
def collect_elements
|
def collect_elements
|
||||||
result = XSD::NamedElements.new
|
result = XSD::NamedElements.new
|
||||||
if @types
|
if @types
|
||||||
|
@ -45,7 +45,15 @@ class Import < Info
|
|||||||
end
|
end
|
||||||
@namespace
|
@namespace
|
||||||
when LocationAttrName
|
when LocationAttrName
|
||||||
@location = value.source
|
@location = URI.parse(value.source)
|
||||||
|
if @location.relative? and !parent.location.nil? and
|
||||||
|
!parent.location.relative?
|
||||||
|
@location = parent.location + @location
|
||||||
|
end
|
||||||
|
if root.importedschema.key?(@location)
|
||||||
|
@content = root.importedschema[@location]
|
||||||
|
else
|
||||||
|
root.importedschema[@location] = nil # placeholder
|
||||||
@content = import(@location)
|
@content = import(@location)
|
||||||
if @content.is_a?(Definitions)
|
if @content.is_a?(Definitions)
|
||||||
@content.root = root
|
@content.root = root
|
||||||
@ -53,6 +61,8 @@ class Import < Info
|
|||||||
@content.targetnamespace = @namespace
|
@content.targetnamespace = @namespace
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
root.importedschema[@location] = @content
|
||||||
|
end
|
||||||
@location
|
@location
|
||||||
else
|
else
|
||||||
nil
|
nil
|
||||||
@ -62,7 +72,7 @@ class Import < Info
|
|||||||
private
|
private
|
||||||
|
|
||||||
def import(location)
|
def import(location)
|
||||||
Importer.import(location)
|
Importer.import(location, root)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,69 +1,37 @@
|
|||||||
# WSDL4R - WSDL importer library.
|
# WSDL4R - WSDL importer library.
|
||||||
# Copyright (C) 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 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;
|
||||||
# either the dual license version in 2003, or any later version.
|
# either the dual license version in 2003, or any later version.
|
||||||
|
|
||||||
|
|
||||||
require 'wsdl/info'
|
require 'wsdl/xmlSchema/importer'
|
||||||
require 'wsdl/parser'
|
require 'wsdl/parser'
|
||||||
require 'soap/soap'
|
|
||||||
require 'soap/property'
|
|
||||||
|
|
||||||
|
|
||||||
module WSDL
|
module WSDL
|
||||||
|
|
||||||
|
|
||||||
class Importer
|
class Importer < WSDL::XMLSchema::Importer
|
||||||
def self.import(location)
|
def self.import(location, originalroot = nil)
|
||||||
new.import(location)
|
new.import(location, originalroot)
|
||||||
end
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
@web_client = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def import(location)
|
|
||||||
STDERR.puts("importing: #{location}") if $DEBUG
|
|
||||||
content = nil
|
|
||||||
if FileTest.exist?(location)
|
|
||||||
content = File.open(location).read
|
|
||||||
else
|
|
||||||
client = web_client.new(nil, "WSDL4R")
|
|
||||||
if opt = ::SOAP::Property.loadproperty(::SOAP::PropertyName)
|
|
||||||
client.proxy = opt["client.protocol.http.proxy"]
|
|
||||||
client.no_proxy = opt["client.protocol.http.no_proxy"]
|
|
||||||
end
|
|
||||||
client.proxy ||= ::SOAP::Env::HTTP_PROXY
|
|
||||||
client.no_proxy ||= ::SOAP::Env::NO_PROXY
|
|
||||||
content = client.get_content(location)
|
|
||||||
end
|
|
||||||
opt = {}
|
|
||||||
begin
|
|
||||||
WSDL::Parser.new(opt).parse(content)
|
|
||||||
rescue WSDL::Parser::ParseError => orgexcn
|
|
||||||
require 'wsdl/xmlSchema/parser'
|
|
||||||
WSDL::XMLSchema::Parser.new(opt).parse(content)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def web_client
|
def parse(content, location, originalroot)
|
||||||
@web_client ||= begin
|
opt = {
|
||||||
require 'http-access2'
|
:location => location,
|
||||||
if HTTPAccess2::VERSION < "2.0"
|
:originalroot => originalroot
|
||||||
raise LoadError.new("http-access/2.0 or later is required.")
|
}
|
||||||
|
begin
|
||||||
|
WSDL::Parser.new(opt).parse(content)
|
||||||
|
rescue WSDL::Parser::ParseError
|
||||||
|
super(content, location, originalroot)
|
||||||
end
|
end
|
||||||
HTTPAccess2::Client
|
|
||||||
rescue LoadError
|
|
||||||
STDERR.puts "Loading http-access2 failed. Net/http is used." if $DEBUG
|
|
||||||
require 'soap/netHttpClient'
|
|
||||||
::SOAP::NetHttpClient
|
|
||||||
end
|
|
||||||
@web_client
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,16 +10,22 @@ module WSDL
|
|||||||
|
|
||||||
|
|
||||||
class Info
|
class Info
|
||||||
|
attr_accessor :root
|
||||||
attr_accessor :parent
|
attr_accessor :parent
|
||||||
attr_accessor :id
|
attr_accessor :id
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
|
@root = nil
|
||||||
@parent = nil
|
@parent = nil
|
||||||
@id = nil
|
@id = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def root
|
def inspect
|
||||||
@parent.root
|
if self.respond_to?(:name)
|
||||||
|
sprintf("#<%s:0x%x %s>", self.class.name, __id__, self.name)
|
||||||
|
else
|
||||||
|
sprintf("#<%s:0x%x>", self.class.name, __id__)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_element(element); end # abstract
|
def parse_element(element); end # abstract
|
||||||
|
@ -46,21 +46,23 @@ class Operation < Info
|
|||||||
end
|
end
|
||||||
|
|
||||||
def input_info
|
def input_info
|
||||||
op_name = @name
|
typename = input.find_message.name
|
||||||
optype_name = XSD::QName.new(targetnamespace, input.name ? input.name.name : @name.name)
|
NameInfo.new(@name, typename, inputparts)
|
||||||
NameInfo.new(op_name, optype_name, inputparts)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def output_info
|
def output_info
|
||||||
op_name = @name
|
typename = output.find_message.name
|
||||||
optype_name = XSD::QName.new(targetnamespace, output.name ? output.name.name : @name.name)
|
NameInfo.new(@name, typename, outputparts)
|
||||||
NameInfo.new(op_name, optype_name, outputparts)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def inputparts
|
def inputparts
|
||||||
sort_parts(input.find_message.parts)
|
sort_parts(input.find_message.parts)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def inputname
|
||||||
|
XSD::QName.new(targetnamespace, input.name ? input.name.name : @name.name)
|
||||||
|
end
|
||||||
|
|
||||||
def outputparts
|
def outputparts
|
||||||
sort_parts(output.find_message.parts)
|
sort_parts(output.find_message.parts)
|
||||||
end
|
end
|
||||||
|
@ -37,7 +37,35 @@ class OperationBinding < Info
|
|||||||
end
|
end
|
||||||
|
|
||||||
def find_operation
|
def find_operation
|
||||||
porttype.operations[@name]
|
porttype.operations[@name] or raise RuntimeError.new("#{@name} not found")
|
||||||
|
end
|
||||||
|
|
||||||
|
def soapoperation_name
|
||||||
|
if @soapoperation
|
||||||
|
@soapoperation.input_info.op_name
|
||||||
|
else
|
||||||
|
find_operation.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def soapoperation_style
|
||||||
|
style = nil
|
||||||
|
if @soapoperation
|
||||||
|
style = @soapoperation.operation_style
|
||||||
|
elsif parent.soapbinding
|
||||||
|
style = parent.soapbinding.style
|
||||||
|
else
|
||||||
|
raise TypeError.new("operation style definition not found")
|
||||||
|
end
|
||||||
|
style || :document
|
||||||
|
end
|
||||||
|
|
||||||
|
def soapaction
|
||||||
|
if @soapoperation
|
||||||
|
@soapoperation.soapaction
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_element(element)
|
def parse_element(element)
|
||||||
|
@ -33,7 +33,7 @@ class Param < Info
|
|||||||
end
|
end
|
||||||
|
|
||||||
def find_message
|
def find_message
|
||||||
root.message(@message)
|
root.message(@message) or raise RuntimeError.new("#{@message} not found")
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_element(element)
|
def parse_element(element)
|
||||||
@ -61,6 +61,9 @@ class Param < Info
|
|||||||
def parse_attr(attr, value)
|
def parse_attr(attr, value)
|
||||||
case attr
|
case attr
|
||||||
when MessageAttrName
|
when MessageAttrName
|
||||||
|
if value.namespace.nil?
|
||||||
|
value = XSD::QName.new(targetnamespace, value.source)
|
||||||
|
end
|
||||||
@message = value
|
@message = value
|
||||||
when NameAttrName
|
when NameAttrName
|
||||||
@name = XSD::QName.new(targetnamespace, value.source)
|
@name = XSD::QName.new(targetnamespace, value.source)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - WSDL XML Instance parser library.
|
# WSDL4R - WSDL XML Instance parser library.
|
||||||
# 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;
|
||||||
@ -53,6 +53,9 @@ public
|
|||||||
@parser = XSD::XMLParser.create_parser(self, opt)
|
@parser = XSD::XMLParser.create_parser(self, opt)
|
||||||
@parsestack = nil
|
@parsestack = nil
|
||||||
@lastnode = nil
|
@lastnode = nil
|
||||||
|
@ignored = {}
|
||||||
|
@location = opt[:location]
|
||||||
|
@originalroot = opt[:originalroot]
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse(string_or_readable)
|
def parse(string_or_readable)
|
||||||
@ -96,7 +99,7 @@ public
|
|||||||
def end_element(name)
|
def end_element(name)
|
||||||
lastframe = @parsestack.pop
|
lastframe = @parsestack.pop
|
||||||
unless name == lastframe.name
|
unless name == lastframe.name
|
||||||
raise UnexpectedElementError.new("Closing element name '#{ name }' does not match with opening element '#{ lastframe.name }'.")
|
raise UnexpectedElementError.new("closing element name '#{name}' does not match with opening element '#{lastframe.name}'")
|
||||||
end
|
end
|
||||||
decode_tag_end(lastframe.ns, lastframe.node)
|
decode_tag_end(lastframe.ns, lastframe.node)
|
||||||
@lastnode = lastframe.node
|
@lastnode = lastframe.node
|
||||||
@ -106,20 +109,31 @@ private
|
|||||||
|
|
||||||
def decode_tag(ns, name, attrs, parent)
|
def decode_tag(ns, name, attrs, parent)
|
||||||
o = nil
|
o = nil
|
||||||
element = ns.parse(name)
|
elename = ns.parse(name)
|
||||||
if !parent
|
if !parent
|
||||||
if element == DefinitionsName
|
if elename == DefinitionsName
|
||||||
o = Definitions.parse_element(element)
|
o = Definitions.parse_element(elename)
|
||||||
|
o.location = @location
|
||||||
else
|
else
|
||||||
raise UnknownElementError.new("Unknown element #{ element }.")
|
raise UnknownElementError.new("unknown element: #{elename}")
|
||||||
end
|
end
|
||||||
|
o.root = @originalroot if @originalroot # o.root = o otherwise
|
||||||
else
|
else
|
||||||
o = parent.parse_element(element)
|
if elename == XMLSchema::AnnotationName
|
||||||
|
# only the first annotation element is allowed for each xsd element.
|
||||||
|
o = XMLSchema::Annotation.new
|
||||||
|
else
|
||||||
|
o = parent.parse_element(elename)
|
||||||
|
end
|
||||||
unless o
|
unless o
|
||||||
STDERR.puts("Unknown element #{ element }.")
|
unless @ignored.key?(elename)
|
||||||
|
warn("ignored element: #{elename}")
|
||||||
|
@ignored[elename] = elename
|
||||||
|
end
|
||||||
o = Documentation.new # which accepts any element.
|
o = Documentation.new # which accepts any element.
|
||||||
end
|
end
|
||||||
# node could be a pseudo element. pseudo element has its own parent.
|
# node could be a pseudo element. pseudo element has its own parent.
|
||||||
|
o.root = parent.root
|
||||||
o.parent = parent if o.parent.nil?
|
o.parent = parent if o.parent.nil?
|
||||||
end
|
end
|
||||||
attrs.each do |key, value|
|
attrs.each do |key, value|
|
||||||
@ -127,7 +141,10 @@ private
|
|||||||
value_ele = ns.parse(value, true)
|
value_ele = ns.parse(value, true)
|
||||||
value_ele.source = value # for recovery; value may not be a QName
|
value_ele.source = value # for recovery; value may not be a QName
|
||||||
unless o.parse_attr(attr_ele, value_ele)
|
unless o.parse_attr(attr_ele, value_ele)
|
||||||
STDERR.puts("Unknown attr #{ attr_ele }.")
|
unless @ignored.key?(attr_ele)
|
||||||
|
warn("ignored attr: #{attr_ele}")
|
||||||
|
@ignored[attr_ele] = attr_ele
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
o
|
o
|
||||||
|
@ -33,7 +33,7 @@ class Port < Info
|
|||||||
end
|
end
|
||||||
|
|
||||||
def find_binding
|
def find_binding
|
||||||
root.binding(@binding)
|
root.binding(@binding) or raise RuntimeError.new("#{@binding} not found")
|
||||||
end
|
end
|
||||||
|
|
||||||
def inputoperation_map
|
def inputoperation_map
|
||||||
|
@ -28,7 +28,8 @@ class PortType < Info
|
|||||||
end
|
end
|
||||||
|
|
||||||
def find_binding
|
def find_binding
|
||||||
root.bindings.find { |item| item.type == @name }
|
root.bindings.find { |item| item.type == @name } or
|
||||||
|
raise RuntimeError.new("#{@name} not found")
|
||||||
end
|
end
|
||||||
|
|
||||||
def locations
|
def locations
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - Creating CGI stub code from WSDL.
|
# WSDL4R - Creating CGI stub code from 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;
|
||||||
@ -26,9 +26,7 @@ class CGIStubCreator
|
|||||||
end
|
end
|
||||||
|
|
||||||
def dump(service_name)
|
def dump(service_name)
|
||||||
STDERR.puts "!!! IMPORTANT !!!"
|
warn("CGI stub can have only 1 port. Creating stub for the first port... Rests are ignored.")
|
||||||
STDERR.puts "- CGI stub can only 1 port. Creating stub for the first port... Rests are ignored."
|
|
||||||
STDERR.puts "!!! IMPORTANT !!!"
|
|
||||||
port = @definitions.service(service_name).ports[0]
|
port = @definitions.service(service_name).ports[0]
|
||||||
dump_porttype(port.porttype.name)
|
dump_porttype(port.porttype.name)
|
||||||
end
|
end
|
||||||
@ -39,28 +37,28 @@ private
|
|||||||
class_name = create_class_name(name)
|
class_name = create_class_name(name)
|
||||||
methoddef, types = MethodDefCreator.new(@definitions).dump(name)
|
methoddef, types = MethodDefCreator.new(@definitions).dump(name)
|
||||||
mr_creator = MappingRegistryCreator.new(@definitions)
|
mr_creator = MappingRegistryCreator.new(@definitions)
|
||||||
c1 = ::XSD::CodeGen::ClassDef.new(class_name)
|
c1 = XSD::CodeGen::ClassDef.new(class_name)
|
||||||
c1.def_require("soap/rpc/cgistub")
|
c1.def_require("soap/rpc/cgistub")
|
||||||
c1.def_require("soap/mapping/registry")
|
c1.def_require("soap/mapping/registry")
|
||||||
c1.def_const("MappingRegistry", "::SOAP::Mapping::Registry.new")
|
c1.def_const("MappingRegistry", "::SOAP::Mapping::Registry.new")
|
||||||
c1.def_code(mr_creator.dump(types))
|
c1.def_code(mr_creator.dump(types))
|
||||||
c1.def_code <<-EOD
|
c1.def_code <<-EOD
|
||||||
Methods = [
|
Methods = [
|
||||||
#{ methoddef.gsub(/^/, " ") }
|
#{methoddef.gsub(/^/, " ")}
|
||||||
]
|
]
|
||||||
EOD
|
EOD
|
||||||
c2 = ::XSD::CodeGen::ClassDef.new(class_name + "App",
|
c2 = XSD::CodeGen::ClassDef.new(class_name + "App",
|
||||||
"::SOAP::RPC::CGIStub")
|
"::SOAP::RPC::CGIStub")
|
||||||
c2.def_method("initialize", "*arg") do
|
c2.def_method("initialize", "*arg") do
|
||||||
<<-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 |name_as, name, param_def, soapaction, namespace, style|
|
||||||
qname = XSD::QName.new(namespace, name_as)
|
|
||||||
if style == :document
|
if style == :document
|
||||||
@router.add_document_method(servant, qname, soapaction, name, param_def)
|
@router.add_document_operation(servant, soapaction, name, param_def)
|
||||||
else
|
else
|
||||||
@router.add_rpc_method(servant, qname, soapaction, name, param_def)
|
qname = XSD::QName.new(namespace, name_as)
|
||||||
|
@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
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - Creating class definition from WSDL
|
# WSDL4R - Creating class definition from WSDL
|
||||||
# Copyright (C) 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 2002, 2003, 2004 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;
|
||||||
@ -22,13 +22,16 @@ class ClassDefCreator
|
|||||||
@elements = definitions.collect_elements
|
@elements = definitions.collect_elements
|
||||||
@simpletypes = definitions.collect_simpletypes
|
@simpletypes = definitions.collect_simpletypes
|
||||||
@complextypes = definitions.collect_complextypes
|
@complextypes = definitions.collect_complextypes
|
||||||
@faulttypes = definitions.collect_faulttypes if definitions.respond_to?(:collect_faulttypes)
|
@faulttypes = nil
|
||||||
|
if definitions.respond_to?(:collect_faulttypes)
|
||||||
|
@faulttypes = definitions.collect_faulttypes
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def dump(class_name = nil)
|
def dump(type = nil)
|
||||||
result = ''
|
result = "require 'xsd/qname'\n"
|
||||||
if class_name
|
if type
|
||||||
result = dump_classdef(class_name)
|
result = dump_classdef(type.name, type)
|
||||||
else
|
else
|
||||||
str = dump_element
|
str = dump_element
|
||||||
unless str.empty?
|
unless str.empty?
|
||||||
@ -53,117 +56,129 @@ private
|
|||||||
|
|
||||||
def dump_element
|
def dump_element
|
||||||
@elements.collect { |ele|
|
@elements.collect { |ele|
|
||||||
ele.local_complextype ? dump_classdef(ele) : ''
|
if ele.local_complextype
|
||||||
}.join("\n")
|
dump_classdef(ele.name, ele.local_complextype)
|
||||||
|
elsif ele.local_simpletype
|
||||||
|
dump_simpletypedef(ele.name, ele.local_simpletype)
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
}.compact.join("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
def dump_simpletype
|
def dump_simpletype
|
||||||
@simpletypes.collect { |type|
|
@simpletypes.collect { |type|
|
||||||
dump_simpletypedef(type)
|
dump_simpletypedef(type.name, type)
|
||||||
}.join("\n")
|
}.compact.join("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
def dump_complextype
|
def dump_complextype
|
||||||
@complextypes.collect { |type|
|
@complextypes.collect { |type|
|
||||||
case type.compoundtype
|
case type.compoundtype
|
||||||
when :TYPE_STRUCT
|
when :TYPE_STRUCT, :TYPE_EMPTY
|
||||||
dump_classdef(type)
|
dump_classdef(type.name, type)
|
||||||
when :TYPE_ARRAY
|
when :TYPE_ARRAY
|
||||||
dump_arraydef(type)
|
dump_arraydef(type)
|
||||||
when :TYPE_SIMPLE
|
when :TYPE_SIMPLE
|
||||||
STDERR.puts("not implemented: ToDo")
|
dump_simpleclassdef(type)
|
||||||
|
when :TYPE_MAP
|
||||||
|
# mapped as a general Hash
|
||||||
|
nil
|
||||||
else
|
else
|
||||||
raise RuntimeError.new(
|
raise RuntimeError.new(
|
||||||
"Unknown kind of complexContent: #{type.compoundtype}")
|
"unknown kind of complexContent: #{type.compoundtype}")
|
||||||
end
|
end
|
||||||
}.join("\n")
|
}.compact.join("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
def dump_simpletypedef(simpletype)
|
def dump_simpletypedef(qname, simpletype)
|
||||||
qname = simpletype.name
|
if !simpletype.restriction or simpletype.restriction.enumeration.empty?
|
||||||
if simpletype.restriction.enumeration.empty?
|
return nil
|
||||||
STDERR.puts("#{qname}: simpleType which is not enum type not supported.")
|
|
||||||
return ''
|
|
||||||
end
|
end
|
||||||
c = XSD::CodeGen::ModuleDef.new(create_class_name(qname))
|
c = XSD::CodeGen::ModuleDef.new(create_class_name(qname))
|
||||||
c.comment = "#{ qname.namespace }"
|
c.comment = "#{qname}"
|
||||||
|
const = {}
|
||||||
simpletype.restriction.enumeration.each do |value|
|
simpletype.restriction.enumeration.each do |value|
|
||||||
c.def_const(safeconstname(value), value.dump)
|
constname = safeconstname(value)
|
||||||
|
const[constname] ||= 0
|
||||||
|
if (const[constname] += 1) > 1
|
||||||
|
constname += "_#{const[constname]}"
|
||||||
|
end
|
||||||
|
c.def_const(constname, ndq(value))
|
||||||
end
|
end
|
||||||
c.dump
|
c.dump
|
||||||
end
|
end
|
||||||
|
|
||||||
def dump_classdef(type_or_element)
|
def dump_simpleclassdef(type_or_element)
|
||||||
qname = type_or_element.name
|
qname = type_or_element.name
|
||||||
|
base = create_class_name(type_or_element.simplecontent.base)
|
||||||
|
c = XSD::CodeGen::ClassDef.new(create_class_name(qname), base)
|
||||||
|
c.comment = "#{qname}"
|
||||||
|
c.dump
|
||||||
|
end
|
||||||
|
|
||||||
|
def dump_classdef(qname, typedef)
|
||||||
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')
|
||||||
else
|
else
|
||||||
c = XSD::CodeGen::ClassDef.new(create_class_name(qname))
|
c = XSD::CodeGen::ClassDef.new(create_class_name(qname))
|
||||||
end
|
end
|
||||||
c.comment = "#{ qname.namespace }"
|
c.comment = "#{qname}"
|
||||||
c.def_classvar('schema_type', qname.name.dump)
|
c.def_classvar('schema_type', ndq(qname.name))
|
||||||
c.def_classvar('schema_ns', qname.namespace.dump)
|
c.def_classvar('schema_ns', ndq(qname.namespace))
|
||||||
schema_attribute = []
|
|
||||||
schema_element = []
|
schema_element = []
|
||||||
init_lines = ''
|
init_lines = ''
|
||||||
params = []
|
params = []
|
||||||
type_or_element.each_element do |element|
|
typedef.each_element do |element|
|
||||||
next unless element.name
|
|
||||||
name = element.name.name
|
|
||||||
if element.type == XSD::AnyTypeName
|
if element.type == XSD::AnyTypeName
|
||||||
type = nil
|
type = nil
|
||||||
elsif basetype = basetype_class(element.type)
|
elsif klass = element_basetype(element)
|
||||||
type = basetype.name
|
type = klass.name
|
||||||
else
|
elsif element.type
|
||||||
type = create_class_name(element.type)
|
type = create_class_name(element.type)
|
||||||
|
else
|
||||||
|
type = nil # means anyType.
|
||||||
|
# do we define a class for local complexType from it's name?
|
||||||
|
# type = create_class_name(element.name)
|
||||||
|
# <element>
|
||||||
|
# <complexType>
|
||||||
|
# <seq...>
|
||||||
|
# </complexType>
|
||||||
|
# </element>
|
||||||
end
|
end
|
||||||
|
name = name_element(element).name
|
||||||
attrname = safemethodname?(name) ? name : safemethodname(name)
|
attrname = safemethodname?(name) ? name : safemethodname(name)
|
||||||
varname = safevarname(name)
|
varname = safevarname(name)
|
||||||
c.def_attr(attrname, true, varname)
|
c.def_attr(attrname, true, varname)
|
||||||
init_lines << "@#{ varname } = #{ varname }\n"
|
init_lines << "@#{varname} = #{varname}\n"
|
||||||
if element.map_as_array?
|
if element.map_as_array?
|
||||||
params << "#{ varname } = []"
|
params << "#{varname} = []"
|
||||||
type << '[]'
|
type << '[]' if type
|
||||||
else
|
else
|
||||||
params << "#{ varname } = nil"
|
params << "#{varname} = nil"
|
||||||
end
|
end
|
||||||
schema_element << [name, type]
|
eleqname = (varname == name) ? nil : element.name
|
||||||
|
schema_element << [varname, eleqname, type]
|
||||||
end
|
end
|
||||||
unless type_or_element.attributes.empty?
|
unless typedef.attributes.empty?
|
||||||
type_or_element.attributes.each do |attribute|
|
define_attribute(c, typedef.attributes)
|
||||||
name = attribute.name.name
|
init_lines << "@__xmlattr = {}\n"
|
||||||
if basetype = basetype_class(attribute.type)
|
|
||||||
type = basetype_class(attribute.type).name
|
|
||||||
else
|
|
||||||
type = nil
|
|
||||||
end
|
end
|
||||||
varname = safevarname('attr_' + name)
|
|
||||||
c.def_method(varname) do <<-__EOD__
|
|
||||||
@__soap_attribute[#{name.dump}]
|
|
||||||
__EOD__
|
|
||||||
end
|
|
||||||
c.def_method(varname + '=', 'value') do <<-__EOD__
|
|
||||||
@__soap_attribute[#{name.dump}] = value
|
|
||||||
__EOD__
|
|
||||||
end
|
|
||||||
schema_attribute << [name, type]
|
|
||||||
end
|
|
||||||
init_lines << "@__soap_attribute = {}\n"
|
|
||||||
end
|
|
||||||
c.def_classvar('schema_attribute',
|
|
||||||
'{' +
|
|
||||||
schema_attribute.collect { |name, type|
|
|
||||||
name.dump + ' => ' + ndq(type)
|
|
||||||
}.join(', ') +
|
|
||||||
'}'
|
|
||||||
)
|
|
||||||
c.def_classvar('schema_element',
|
c.def_classvar('schema_element',
|
||||||
'{' +
|
'[' +
|
||||||
schema_element.collect { |name, type|
|
schema_element.collect { |varname, name, type|
|
||||||
name.dump + ' => ' + ndq(type)
|
'[' +
|
||||||
|
(
|
||||||
|
if name
|
||||||
|
varname.dump + ', [' + ndq(type) + ', ' + dqname(name) + ']'
|
||||||
|
else
|
||||||
|
varname.dump + ', ' + ndq(type)
|
||||||
|
end
|
||||||
|
) +
|
||||||
|
']'
|
||||||
}.join(', ') +
|
}.join(', ') +
|
||||||
'}'
|
']'
|
||||||
)
|
)
|
||||||
c.def_method('initialize', *params) do
|
c.def_method('initialize', *params) do
|
||||||
init_lines
|
init_lines
|
||||||
@ -171,20 +186,83 @@ private
|
|||||||
c.dump
|
c.dump
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def element_basetype(ele)
|
||||||
|
if klass = basetype_class(ele.type)
|
||||||
|
klass
|
||||||
|
elsif ele.local_simpletype
|
||||||
|
basetype_class(ele.local_simpletype.base)
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def attribute_basetype(attr)
|
||||||
|
if klass = basetype_class(attr.type)
|
||||||
|
klass
|
||||||
|
elsif attr.local_simpletype
|
||||||
|
basetype_class(attr.local_simpletype.base)
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def basetype_class(type)
|
def basetype_class(type)
|
||||||
if @simpletypes[type]
|
return nil if type.nil?
|
||||||
basetype_mapped_class(@simpletypes[type].base)
|
if simpletype = @simpletypes[type]
|
||||||
|
basetype_mapped_class(simpletype.base)
|
||||||
else
|
else
|
||||||
basetype_mapped_class(type)
|
basetype_mapped_class(type)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def define_attribute(c, attributes)
|
||||||
|
schema_attribute = []
|
||||||
|
attributes.each do |attribute|
|
||||||
|
name = name_attribute(attribute)
|
||||||
|
if klass = attribute_basetype(attribute)
|
||||||
|
type = klass.name
|
||||||
|
else
|
||||||
|
type = nil
|
||||||
|
end
|
||||||
|
methodname = safemethodname('xmlattr_' + name.name)
|
||||||
|
c.def_method(methodname) do <<-__EOD__
|
||||||
|
(@__xmlattr ||= {})[#{dqname(name)}]
|
||||||
|
__EOD__
|
||||||
|
end
|
||||||
|
c.def_method(methodname + '=', 'value') do <<-__EOD__
|
||||||
|
(@__xmlattr ||= {})[#{dqname(name)}] = value
|
||||||
|
__EOD__
|
||||||
|
end
|
||||||
|
schema_attribute << [name, type]
|
||||||
|
end
|
||||||
|
c.def_classvar('schema_attribute',
|
||||||
|
'{' +
|
||||||
|
schema_attribute.collect { |name, type|
|
||||||
|
dqname(name) + ' => ' + ndq(type)
|
||||||
|
}.join(', ') +
|
||||||
|
'}'
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def name_element(element)
|
||||||
|
return element.name if element.name
|
||||||
|
return element.ref if element.ref
|
||||||
|
raise RuntimeError.new("cannot define name of #{element}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def name_attribute(attribute)
|
||||||
|
return attribute.name if attribute.name
|
||||||
|
return attribute.ref if attribute.ref
|
||||||
|
raise RuntimeError.new("cannot define name of #{attribute}")
|
||||||
|
end
|
||||||
|
|
||||||
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.namespace }"
|
c.comment = "#{qname}"
|
||||||
c.def_classvar('schema_type', qname.name.dump)
|
type = complextype.child_type
|
||||||
c.def_classvar('schema_ns', qname.namespace.dump)
|
c.def_classvar('schema_type', ndq(type.name))
|
||||||
|
c.def_classvar('schema_ns', ndq(type.namespace))
|
||||||
c.dump
|
c.dump
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -21,7 +21,7 @@ module ClassDefCreatorSupport
|
|||||||
|
|
||||||
def create_class_name(qname)
|
def create_class_name(qname)
|
||||||
if klass = basetype_mapped_class(qname)
|
if klass = basetype_mapped_class(qname)
|
||||||
::SOAP::Mapping::DefaultRegistry.find_mapped_obj_class(klass.name)
|
::SOAP::Mapping::DefaultRegistry.find_mapped_obj_class(klass).name
|
||||||
else
|
else
|
||||||
safeconstname(qname.name)
|
safeconstname(qname.name)
|
||||||
end
|
end
|
||||||
@ -71,6 +71,10 @@ __EOD__
|
|||||||
':' + ele
|
':' + ele
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def dqname(qname)
|
||||||
|
qname.dump
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def dump_inout_type(param)
|
def dump_inout_type(param)
|
||||||
|
@ -31,42 +31,44 @@ class ComplexType < Info
|
|||||||
else
|
else
|
||||||
:TYPE_STRUCT
|
:TYPE_STRUCT
|
||||||
end
|
end
|
||||||
elsif complexcontent and complexcontent.base == ::SOAP::ValueArrayName
|
elsif complexcontent
|
||||||
|
if complexcontent.base == ::SOAP::ValueArrayName
|
||||||
:TYPE_ARRAY
|
:TYPE_ARRAY
|
||||||
|
else
|
||||||
|
complexcontent.basetype.check_type
|
||||||
|
end
|
||||||
elsif simplecontent
|
elsif simplecontent
|
||||||
:TYPE_SIMPLE
|
:TYPE_SIMPLE
|
||||||
elsif !attributes.empty?
|
elsif !attributes.empty?
|
||||||
:TYPE_STRUCT
|
:TYPE_STRUCT
|
||||||
else
|
else # empty complexType definition (seen in partner.wsdl of salesforce)
|
||||||
raise NotImplementedError.new("Unknown kind of complexType.")
|
:TYPE_EMPTY
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def child_type(name = nil)
|
def child_type(name = nil)
|
||||||
type = nil
|
|
||||||
case compoundtype
|
case compoundtype
|
||||||
when :TYPE_STRUCT
|
when :TYPE_STRUCT
|
||||||
if ele = find_element(name)
|
if ele = find_element(name)
|
||||||
type = ele.type
|
ele.type
|
||||||
elsif ele = find_element_by_name(name.name)
|
elsif ele = find_element_by_name(name.name)
|
||||||
type = ele.type
|
ele.type
|
||||||
end
|
end
|
||||||
when :TYPE_ARRAY
|
when :TYPE_ARRAY
|
||||||
type = @contenttype ||= content_arytype
|
@contenttype ||= content_arytype
|
||||||
when :TYPE_MAP
|
when :TYPE_MAP
|
||||||
item_ele = find_element_by_name("item") or
|
item_ele = find_element_by_name("item") or
|
||||||
raise RuntimeError.new("'item' element not found in Map definition.")
|
raise RuntimeError.new("'item' element not found in Map definition.")
|
||||||
content = item_ele.local_complextype or
|
content = item_ele.local_complextype or
|
||||||
raise RuntimeError.new("No complexType definition for 'item'.")
|
raise RuntimeError.new("No complexType definition for 'item'.")
|
||||||
if ele = content.find_element(name)
|
if ele = content.find_element(name)
|
||||||
type = ele.type
|
ele.type
|
||||||
elsif ele = content.find_element_by_name(name.name)
|
elsif ele = content.find_element_by_name(name.name)
|
||||||
type = ele.type
|
ele.type
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise NotImplementedError.new("Unknown kind of complexType.")
|
raise NotImplementedError.new("Unknown kind of complexType.")
|
||||||
end
|
end
|
||||||
type
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def child_defined_complextype(name)
|
def child_defined_complextype(name)
|
||||||
@ -103,16 +105,21 @@ class ComplexType < Info
|
|||||||
return attribute.arytype
|
return attribute.arytype
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elsif content.elements.size == 1 and content.elements[0].maxoccurs != '1'
|
if check_array_content(complexcontent.content)
|
||||||
return content.elements[0].type
|
return complexcontent.content.elements[0].type
|
||||||
else
|
|
||||||
raise RuntimeError.new("Assert: Unknown array definition.")
|
|
||||||
end
|
end
|
||||||
nil
|
elsif check_array_content(content)
|
||||||
|
return content.elements[0].type
|
||||||
|
end
|
||||||
|
raise RuntimeError.new("Assert: Unknown array definition.")
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def check_array_content(content)
|
||||||
|
content.elements.size == 1 and content.elements[0].maxoccurs != '1'
|
||||||
|
end
|
||||||
|
|
||||||
def content_arytype
|
def content_arytype
|
||||||
if arytype = find_arytype
|
if arytype = find_arytype
|
||||||
ns = arytype.namespace
|
ns = arytype.namespace
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - WSDL additional definitions for SOAP.
|
# WSDL4R - WSDL additional definitions for SOAP.
|
||||||
# Copyright (C) 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 2002-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;
|
||||||
@ -77,13 +77,13 @@ class Definitions < Info
|
|||||||
|
|
||||||
def collect_faulttypes
|
def collect_faulttypes
|
||||||
result = []
|
result = []
|
||||||
collect_fault_messages.each do |m|
|
collect_fault_messages.each do |name|
|
||||||
parts = message(m).parts
|
faultparts = message(name).parts
|
||||||
if parts.size != 1
|
if faultparts.size != 1
|
||||||
raise RuntimeError.new("Expecting fault message to have only 1 part.")
|
raise RuntimeError.new("expecting fault message to have only 1 part")
|
||||||
end
|
end
|
||||||
if result.index(parts[0].type).nil?
|
if result.index(faultparts[0].type).nil?
|
||||||
result << parts[0].type
|
result << faultparts[0].type
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
result
|
result
|
||||||
@ -111,13 +111,13 @@ private
|
|||||||
if op_bind_rpc?(op_bind)
|
if op_bind_rpc?(op_bind)
|
||||||
operation = op_bind.find_operation
|
operation = op_bind.find_operation
|
||||||
if op_bind.input
|
if op_bind.input
|
||||||
type = XMLSchema::ComplexType.new(operation_input_name(operation))
|
type = XMLSchema::ComplexType.new(op_bind.soapoperation_name)
|
||||||
message = messages[operation.input.message]
|
message = messages[operation.input.message]
|
||||||
type.sequence_elements = elements_from_message(message)
|
type.sequence_elements = elements_from_message(message)
|
||||||
types << type
|
types << type
|
||||||
end
|
end
|
||||||
if op_bind.output
|
if op_bind.output
|
||||||
type = XMLSchema::ComplexType.new(operation_output_name(operation))
|
type = XMLSchema::ComplexType.new(operation.outputname)
|
||||||
message = messages[operation.output.message]
|
message = messages[operation.output.message]
|
||||||
type.sequence_elements = elements_from_message(message)
|
type.sequence_elements = elements_from_message(message)
|
||||||
types << type
|
types << type
|
||||||
@ -127,23 +127,20 @@ private
|
|||||||
types
|
types
|
||||||
end
|
end
|
||||||
|
|
||||||
def operation_input_name(operation)
|
|
||||||
operation.input.name || operation.name
|
|
||||||
end
|
|
||||||
|
|
||||||
def operation_output_name(operation)
|
|
||||||
operation.output.name ||
|
|
||||||
XSD::QName.new(operation.name.namespace, operation.name.name + "Response")
|
|
||||||
end
|
|
||||||
|
|
||||||
def op_bind_rpc?(op_bind)
|
def op_bind_rpc?(op_bind)
|
||||||
op_bind.soapoperation and op_bind.soapoperation.operation_style == :rpc
|
op_bind.soapoperation_style == :rpc
|
||||||
end
|
end
|
||||||
|
|
||||||
def elements_from_message(message)
|
def elements_from_message(message)
|
||||||
message.parts.collect { |part|
|
message.parts.collect { |part|
|
||||||
|
if part.element
|
||||||
|
collect_elements[part.element]
|
||||||
|
elsif part.name.nil? or part.type.nil?
|
||||||
|
raise RuntimeError.new("part of a message must be an element or typed")
|
||||||
|
else
|
||||||
qname = XSD::QName.new(nil, part.name)
|
qname = XSD::QName.new(nil, part.name)
|
||||||
XMLSchema::Element.new(qname, part.type)
|
XMLSchema::Element.new(qname, part.type)
|
||||||
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - Creating driver code from WSDL.
|
# WSDL4R - Creating driver code from 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;
|
||||||
@ -46,16 +46,17 @@ private
|
|||||||
methoddef, types = MethodDefCreator.new(@definitions).dump(name)
|
methoddef, types = MethodDefCreator.new(@definitions).dump(name)
|
||||||
mr_creator = MappingRegistryCreator.new(@definitions)
|
mr_creator = MappingRegistryCreator.new(@definitions)
|
||||||
binding = @definitions.bindings.find { |item| item.type == name }
|
binding = @definitions.bindings.find { |item| item.type == name }
|
||||||
addresses = @definitions.porttype(name).locations
|
return '' unless binding.soapbinding # not a SOAP binding
|
||||||
|
address = @definitions.porttype(name).locations[0]
|
||||||
|
|
||||||
c = ::XSD::CodeGen::ClassDef.new(class_name, "::SOAP::RPC::Driver")
|
c = XSD::CodeGen::ClassDef.new(class_name, "::SOAP::RPC::Driver")
|
||||||
c.def_require("soap/rpc/driver")
|
c.def_require("soap/rpc/driver")
|
||||||
c.def_const("MappingRegistry", "::SOAP::Mapping::Registry.new")
|
c.def_const("MappingRegistry", "::SOAP::Mapping::Registry.new")
|
||||||
c.def_const("DefaultEndpointUrl", addresses[0].dump)
|
c.def_const("DefaultEndpointUrl", ndq(address))
|
||||||
c.def_code(mr_creator.dump(types))
|
c.def_code(mr_creator.dump(types))
|
||||||
c.def_code <<-EOD
|
c.def_code <<-EOD
|
||||||
Methods = [
|
Methods = [
|
||||||
#{ methoddef.gsub(/^/, " ") }
|
#{methoddef.gsub(/^/, " ")}
|
||||||
]
|
]
|
||||||
EOD
|
EOD
|
||||||
c.def_method("initialize", "endpoint_url = nil") do
|
c.def_method("initialize", "endpoint_url = nil") do
|
||||||
@ -69,14 +70,19 @@ Methods = [
|
|||||||
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 |name_as, name, params, soapaction, namespace, style|
|
||||||
qname = ::XSD::QName.new(namespace, name_as)
|
qname = XSD::QName.new(namespace, name_as)
|
||||||
if style == :document
|
if style == :document
|
||||||
@proxy.add_document_method(qname, soapaction, name, params)
|
@proxy.add_document_method(soapaction, name, params)
|
||||||
add_document_method_interface(name, name_as)
|
add_document_method_interface(name, params)
|
||||||
else
|
else
|
||||||
@proxy.add_rpc_method(qname, soapaction, name, params)
|
@proxy.add_rpc_method(qname, soapaction, name, params)
|
||||||
add_rpc_method_interface(name, params)
|
add_rpc_method_interface(name, params)
|
||||||
end
|
end
|
||||||
|
if name_as != name and name_as.capitalize == name.capitalize
|
||||||
|
::SOAP::Mapping.define_singleton_method(self, name_as) do |*arg|
|
||||||
|
__send__(name, *arg)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
EOD
|
EOD
|
||||||
end
|
end
|
||||||
|
@ -21,12 +21,6 @@ class Element < Info
|
|||||||
def attributes
|
def attributes
|
||||||
@local_complextype.attributes
|
@local_complextype.attributes
|
||||||
end
|
end
|
||||||
|
|
||||||
def each_element
|
|
||||||
@local_complextype.each_element do |element|
|
|
||||||
yield(element)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,6 +27,10 @@ class Fault < Info
|
|||||||
@namespace = nil
|
@namespace = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def targetnamespace
|
||||||
|
parent.targetnamespace
|
||||||
|
end
|
||||||
|
|
||||||
def parse_element(element)
|
def parse_element(element)
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
@ -32,8 +32,12 @@ class Header < Info
|
|||||||
@headerfault = nil
|
@headerfault = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def targetnamespace
|
||||||
|
parent.targetnamespace
|
||||||
|
end
|
||||||
|
|
||||||
def find_message
|
def find_message
|
||||||
root.message(@message)
|
root.message(@message) or raise RuntimeError.new("#{@message} not found")
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_part
|
def find_part
|
||||||
@ -42,7 +46,7 @@ class Header < Info
|
|||||||
return part
|
return part
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
nil
|
raise RuntimeError.new("#{@part} not found")
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_element(element)
|
def parse_element(element)
|
||||||
@ -59,7 +63,10 @@ class Header < Info
|
|||||||
def parse_attr(attr, value)
|
def parse_attr(attr, value)
|
||||||
case attr
|
case attr
|
||||||
when MessageAttrName
|
when MessageAttrName
|
||||||
@message = XSD::QName.new(targetnamespace, value.source)
|
if value.namespace.nil?
|
||||||
|
value = XSD::QName.new(targetnamespace, value.source)
|
||||||
|
end
|
||||||
|
@message = value
|
||||||
when PartAttrName
|
when PartAttrName
|
||||||
@part = value.source
|
@part = value.source
|
||||||
when UseAttrName
|
when UseAttrName
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - Creating MappingRegistry code from WSDL.
|
# WSDL4R - Creating MappingRegistry code from 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;
|
||||||
@ -51,8 +51,10 @@ private
|
|||||||
dump_struct_typemap(definedtype)
|
dump_struct_typemap(definedtype)
|
||||||
when :TYPE_ARRAY
|
when :TYPE_ARRAY
|
||||||
dump_array_typemap(definedtype)
|
dump_array_typemap(definedtype)
|
||||||
|
when :TYPE_MAP, :TYPE_EMPTY
|
||||||
|
nil
|
||||||
else
|
else
|
||||||
raise NotImplementedError.new("Must not reach here.")
|
raise NotImplementedError.new("must not reach here")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -61,10 +63,10 @@ private
|
|||||||
ele = definedtype.name
|
ele = definedtype.name
|
||||||
return <<__EOD__
|
return <<__EOD__
|
||||||
MappingRegistry.set(
|
MappingRegistry.set(
|
||||||
#{ create_class_name(ele) },
|
#{create_class_name(ele)},
|
||||||
::SOAP::SOAPStruct,
|
::SOAP::SOAPStruct,
|
||||||
::SOAP::Mapping::Registry::TypedStructFactory,
|
::SOAP::Mapping::Registry::TypedStructFactory,
|
||||||
{ :type => ::XSD::QName.new("#{ ele.namespace }", "#{ ele.name }") }
|
{ :type => #{dqname(ele)} }
|
||||||
)
|
)
|
||||||
__EOD__
|
__EOD__
|
||||||
end
|
end
|
||||||
@ -76,10 +78,10 @@ __EOD__
|
|||||||
@types << type
|
@types << type
|
||||||
return <<__EOD__
|
return <<__EOD__
|
||||||
MappingRegistry.set(
|
MappingRegistry.set(
|
||||||
#{ create_class_name(ele) },
|
#{create_class_name(ele)},
|
||||||
::SOAP::SOAPArray,
|
::SOAP::SOAPArray,
|
||||||
::SOAP::Mapping::Registry::TypedArrayFactory,
|
::SOAP::Mapping::Registry::TypedArrayFactory,
|
||||||
{ :type => ::XSD::QName.new("#{ type.namespace }", "#{ type.name }") }
|
{ :type => #{dqname(type)} }
|
||||||
)
|
)
|
||||||
__EOD__
|
__EOD__
|
||||||
end
|
end
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - Creating driver code from WSDL.
|
# WSDL4R - Creating driver code from 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;
|
||||||
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
require 'wsdl/info'
|
require 'wsdl/info'
|
||||||
require 'wsdl/soap/classDefCreatorSupport'
|
require 'wsdl/soap/classDefCreatorSupport'
|
||||||
|
require 'soap/rpc/element'
|
||||||
|
|
||||||
|
|
||||||
module WSDL
|
module WSDL
|
||||||
@ -24,110 +25,122 @@ class MethodDefCreator
|
|||||||
@simpletypes = @definitions.collect_simpletypes
|
@simpletypes = @definitions.collect_simpletypes
|
||||||
@complextypes = @definitions.collect_complextypes
|
@complextypes = @definitions.collect_complextypes
|
||||||
@elements = @definitions.collect_elements
|
@elements = @definitions.collect_elements
|
||||||
@types = nil
|
@types = []
|
||||||
end
|
end
|
||||||
|
|
||||||
def dump(porttype)
|
def dump(porttype)
|
||||||
@types = []
|
@types.clear
|
||||||
result = ""
|
result = ""
|
||||||
operations = @definitions.porttype(porttype).operations
|
operations = @definitions.porttype(porttype).operations
|
||||||
binding = @definitions.porttype_binding(porttype)
|
binding = @definitions.porttype_binding(porttype)
|
||||||
operations.each do |operation|
|
operations.each do |operation|
|
||||||
op_bind = binding.operations[operation.name]
|
op_bind = binding.operations[operation.name]
|
||||||
|
next unless op_bind # no binding is defined
|
||||||
|
next unless op_bind.soapoperation # not a SOAP operation binding
|
||||||
result << ",\n" unless result.empty?
|
result << ",\n" unless result.empty?
|
||||||
result << dump_method(operation, op_bind).chomp
|
result << dump_method(operation, op_bind).chomp
|
||||||
end
|
end
|
||||||
return result, @types
|
return result, @types
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def collect_rpcparameter(operation)
|
||||||
|
result = operation.inputparts.collect { |part|
|
||||||
|
collect_type(part.type)
|
||||||
|
param_set(::SOAP::RPC::SOAPMethod::IN, rpcdefinedtype(part), part.name)
|
||||||
|
}
|
||||||
|
outparts = operation.outputparts
|
||||||
|
if outparts.size > 0
|
||||||
|
retval = outparts[0]
|
||||||
|
collect_type(retval.type)
|
||||||
|
result << param_set(::SOAP::RPC::SOAPMethod::RETVAL,
|
||||||
|
rpcdefinedtype(retval), retval.name)
|
||||||
|
cdr(outparts).each { |part|
|
||||||
|
collect_type(part.type)
|
||||||
|
result << param_set(::SOAP::RPC::SOAPMethod::OUT, rpcdefinedtype(part),
|
||||||
|
part.name)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
def collect_documentparameter(operation)
|
||||||
|
param = []
|
||||||
|
operation.inputparts.each do |input|
|
||||||
|
param << param_set(::SOAP::RPC::SOAPMethod::IN,
|
||||||
|
documentdefinedtype(input), input.name)
|
||||||
|
end
|
||||||
|
operation.outputparts.each do |output|
|
||||||
|
param << param_set(::SOAP::RPC::SOAPMethod::OUT,
|
||||||
|
documentdefinedtype(output), output.name)
|
||||||
|
end
|
||||||
|
param
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def dump_method(operation, binding)
|
def dump_method(operation, binding)
|
||||||
name = safemethodname(operation.name.name)
|
name = safemethodname(operation.name.name)
|
||||||
name_as = operation.name.name
|
name_as = operation.name.name
|
||||||
stylestr = binding.soapoperation.operation_style.id2name
|
style = binding.soapoperation_style
|
||||||
if binding.soapoperation.operation_style == :rpc
|
|
||||||
soapaction = binding.soapoperation.soapaction
|
|
||||||
namespace = binding.input.soapbody.namespace
|
namespace = binding.input.soapbody.namespace
|
||||||
params = collect_rpcparameter(operation)
|
if style == :rpc
|
||||||
|
paramstr = param2str(collect_rpcparameter(operation))
|
||||||
else
|
else
|
||||||
soapaction = namespace = nil
|
paramstr = param2str(collect_documentparameter(operation))
|
||||||
params = collect_documentparameter(operation)
|
|
||||||
end
|
end
|
||||||
paramstr = param2str(params)
|
|
||||||
if paramstr.empty?
|
if paramstr.empty?
|
||||||
paramstr = '[]'
|
paramstr = '[]'
|
||||||
else
|
else
|
||||||
paramstr = "[\n" << paramstr.gsub(/^/, ' ') << "\n ]"
|
paramstr = "[\n" << paramstr.gsub(/^/, ' ') << "\n ]"
|
||||||
end
|
end
|
||||||
return <<__EOD__
|
return <<__EOD__
|
||||||
[#{ dq(name_as) }, #{ dq(name) },
|
[#{dq(name_as)}, #{dq(name)},
|
||||||
#{ paramstr },
|
#{paramstr},
|
||||||
#{ ndq(soapaction) }, #{ ndq(namespace) }, #{ sym(stylestr) }
|
#{ndq(binding.soapaction)}, #{ndq(namespace)}, #{sym(style.id2name)}
|
||||||
]
|
]
|
||||||
__EOD__
|
__EOD__
|
||||||
end
|
end
|
||||||
|
|
||||||
def collect_rpcparameter(operation)
|
|
||||||
result = operation.inputparts.collect { |part|
|
|
||||||
collect_type(part.type)
|
|
||||||
param_set('in', rpcdefinedtype(part), part.name)
|
|
||||||
}
|
|
||||||
outparts = operation.outputparts
|
|
||||||
if outparts.size > 0
|
|
||||||
retval = outparts[0]
|
|
||||||
collect_type(retval.type)
|
|
||||||
result << param_set('retval', rpcdefinedtype(retval), retval.name)
|
|
||||||
cdr(outparts).each { |part|
|
|
||||||
collect_type(part.type)
|
|
||||||
result << param_set('out', rpcdefinedtype(part), part.name)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
result
|
|
||||||
end
|
|
||||||
|
|
||||||
def collect_documentparameter(operation)
|
|
||||||
input = operation.inputparts[0]
|
|
||||||
output = operation.outputparts[0]
|
|
||||||
[
|
|
||||||
param_set('input', documentdefinedtype(input), input.name),
|
|
||||||
param_set('output', documentdefinedtype(output), output.name)
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
def rpcdefinedtype(part)
|
def rpcdefinedtype(part)
|
||||||
if mapped = basetype_mapped_class(part.type)
|
if mapped = basetype_mapped_class(part.type)
|
||||||
['::' + mapped.name]
|
['::' + mapped.name]
|
||||||
elsif definedtype = @simpletypes[part.type]
|
elsif definedtype = @simpletypes[part.type]
|
||||||
['::' + basetype_mapped_class(definedtype.base).name]
|
['::' + basetype_mapped_class(definedtype.base).name]
|
||||||
elsif definedtype = @elements[part.element]
|
elsif definedtype = @elements[part.element]
|
||||||
['::SOAP::SOAPStruct', part.element.namespace, part.element.name]
|
#['::SOAP::SOAPStruct', part.element.namespace, part.element.name]
|
||||||
|
['nil', part.element.namespace, part.element.name]
|
||||||
elsif definedtype = @complextypes[part.type]
|
elsif definedtype = @complextypes[part.type]
|
||||||
case definedtype.compoundtype
|
case definedtype.compoundtype
|
||||||
when :TYPE_STRUCT
|
when :TYPE_STRUCT, :TYPE_EMPTY # ToDo: empty should be treated as void.
|
||||||
['::SOAP::SOAPStruct', part.type.namespace, part.type.name]
|
type = create_class_name(part.type)
|
||||||
|
[type, part.type.namespace, part.type.name]
|
||||||
|
when :TYPE_MAP
|
||||||
|
[Hash.name, part.type.namespace, part.type.name]
|
||||||
when :TYPE_ARRAY
|
when :TYPE_ARRAY
|
||||||
arytype = definedtype.find_arytype || XSD::AnyTypeName
|
arytype = definedtype.find_arytype || XSD::AnyTypeName
|
||||||
ns = arytype.namespace
|
ns = arytype.namespace
|
||||||
name = arytype.name.sub(/\[(?:,)*\]$/, '')
|
name = arytype.name.sub(/\[(?:,)*\]$/, '')
|
||||||
['::SOAP::SOAPArray', ns, name]
|
type = create_class_name(XSD::QName.new(ns, name))
|
||||||
|
[type + '[]', ns, name]
|
||||||
else
|
else
|
||||||
raise NotImplementedError.new("Must not reach here.")
|
raise NotImplementedError.new("must not reach here")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise RuntimeError.new("Part: #{part.name} cannot be resolved.")
|
raise RuntimeError.new("part: #{part.name} cannot be resolved")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def documentdefinedtype(part)
|
def documentdefinedtype(part)
|
||||||
if definedtype = @simpletypes[part.type]
|
if mapped = basetype_mapped_class(part.type)
|
||||||
|
['::' + mapped.name, nil, part.name]
|
||||||
|
elsif definedtype = @simpletypes[part.type]
|
||||||
['::' + basetype_mapped_class(definedtype.base).name, nil, part.name]
|
['::' + basetype_mapped_class(definedtype.base).name, nil, part.name]
|
||||||
elsif definedtype = @elements[part.element]
|
elsif definedtype = @elements[part.element]
|
||||||
['::SOAP::SOAPElement', part.element.namespace, part.element.name]
|
['::SOAP::SOAPElement', part.element.namespace, part.element.name]
|
||||||
elsif definedtype = @complextypes[part.type]
|
elsif definedtype = @complextypes[part.type]
|
||||||
['::SOAP::SOAPElement', part.type.namespace, part.type.name]
|
['::SOAP::SOAPElement', part.type.namespace, part.type.name]
|
||||||
else
|
else
|
||||||
raise RuntimeError.new("Part: #{part.name} cannot be resolved.")
|
raise RuntimeError.new("part: #{part.name} cannot be resolved")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -138,6 +151,7 @@ __EOD__
|
|||||||
def collect_type(type)
|
def collect_type(type)
|
||||||
# ignore inline type definition.
|
# ignore inline type definition.
|
||||||
return if type.nil?
|
return if type.nil?
|
||||||
|
return if @types.include?(type)
|
||||||
@types << type
|
@types << type
|
||||||
return unless @complextypes[type]
|
return unless @complextypes[type]
|
||||||
@complextypes[type].each_element do |element|
|
@complextypes[type].each_element do |element|
|
||||||
@ -147,15 +161,15 @@ __EOD__
|
|||||||
|
|
||||||
def param2str(params)
|
def param2str(params)
|
||||||
params.collect { |param|
|
params.collect { |param|
|
||||||
"[#{ dq(param[0]) }, #{ dq(param[2]) }, #{ type2str(param[1]) }]"
|
"[#{dq(param[0])}, #{dq(param[2])}, #{type2str(param[1])}]"
|
||||||
}.join(",\n")
|
}.join(",\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
def type2str(type)
|
def type2str(type)
|
||||||
if type.size == 1
|
if type.size == 1
|
||||||
"[#{ type[0] }]"
|
"[#{dq(type[0])}]"
|
||||||
else
|
else
|
||||||
"[#{ type[0] }, #{ ndq(type[1]) }, #{ dq(type[2]) }]"
|
"[#{dq(type[0])}, #{ndq(type[1])}, #{dq(type[2])}]"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -101,8 +101,7 @@ private
|
|||||||
"EncodingStyle '#{ soapbody.encodingstyle }' not supported.")
|
"EncodingStyle '#{ soapbody.encodingstyle }' not supported.")
|
||||||
end
|
end
|
||||||
if soapbody.namespace
|
if soapbody.namespace
|
||||||
op_name = op_name.dup
|
op_name = XSD::QName.new(soapbody.namespace, op_name.name)
|
||||||
op_name.namespace = soapbody.namespace
|
|
||||||
end
|
end
|
||||||
if soapbody.parts
|
if soapbody.parts
|
||||||
target = soapbody.parts.split(/\s+/)
|
target = soapbody.parts.split(/\s+/)
|
||||||
@ -114,8 +113,7 @@ private
|
|||||||
end
|
end
|
||||||
|
|
||||||
faultpart = nil
|
faultpart = nil
|
||||||
soapaction = parent.soapoperation.soapaction
|
OperationInfo.new(operation_style, op_name, optype_name, headerparts, bodyparts, faultpart, parent.soapaction)
|
||||||
OperationInfo.new(operation_style, op_name, optype_name, headerparts, bodyparts, faultpart, soapaction)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - Creating servant skelton code from WSDL.
|
# WSDL4R - Creating servant skelton code from 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;
|
||||||
@ -17,7 +17,7 @@ module SOAP
|
|||||||
|
|
||||||
class ServantSkeltonCreator
|
class ServantSkeltonCreator
|
||||||
include ClassDefCreatorSupport
|
include ClassDefCreatorSupport
|
||||||
include ::XSD::CodeGen::GenSupport
|
include XSD::CodeGen::GenSupport
|
||||||
|
|
||||||
attr_reader :definitions
|
attr_reader :definitions
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ private
|
|||||||
|
|
||||||
def dump_porttype(name)
|
def dump_porttype(name)
|
||||||
class_name = create_class_name(name)
|
class_name = create_class_name(name)
|
||||||
c = ::XSD::CodeGen::ClassDef.new(class_name)
|
c = XSD::CodeGen::ClassDef.new(class_name)
|
||||||
operations = @definitions.porttype(name).operations
|
operations = @definitions.porttype(name).operations
|
||||||
operations.each do |operation|
|
operations.each do |operation|
|
||||||
name = safemethodname(operation.name.name)
|
name = safemethodname(operation.name.name)
|
||||||
@ -50,7 +50,7 @@ private
|
|||||||
params = input.find_message.parts.collect { |part|
|
params = input.find_message.parts.collect { |part|
|
||||||
safevarname(part.name)
|
safevarname(part.name)
|
||||||
}
|
}
|
||||||
m = ::XSD::CodeGen::MethodDef.new(name, params) do <<-EOD
|
m = XSD::CodeGen::MethodDef.new(name, params) do <<-EOD
|
||||||
p [#{params.join(", ")}]
|
p [#{params.join(", ")}]
|
||||||
raise NotImplementedError.new
|
raise NotImplementedError.new
|
||||||
EOD
|
EOD
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - Creating standalone server stub code from WSDL.
|
# WSDL4R - Creating standalone server stub code from 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;
|
||||||
@ -26,10 +26,8 @@ class StandaloneServerStubCreator
|
|||||||
end
|
end
|
||||||
|
|
||||||
def dump(service_name)
|
def dump(service_name)
|
||||||
STDERR.puts "!!! IMPORTANT !!!"
|
warn("- Standalone stub can have only 1 port for now. So creating stub for the first port and rests are ignored.")
|
||||||
STDERR.puts "- Standalone stub can have only 1 port for now. So creating stub for the first port and rests are ignored."
|
warn("- Standalone server stub ignores port location defined in WSDL. Location is http://localhost:10080/ by default. Generated client from WSDL must be configured to point this endpoint manually.")
|
||||||
STDERR.puts "- Standalone server stub ignores port location defined in WSDL. Location is http://localhost:10080/ by default. Generated client from WSDL must be configured to point this endpoint by hand."
|
|
||||||
STDERR.puts "!!! IMPORTANT !!!"
|
|
||||||
port = @definitions.service(service_name).ports[0]
|
port = @definitions.service(service_name).ports[0]
|
||||||
dump_porttype(port.porttype.name)
|
dump_porttype(port.porttype.name)
|
||||||
end
|
end
|
||||||
@ -41,28 +39,28 @@ private
|
|||||||
methoddef, types = MethodDefCreator.new(@definitions).dump(name)
|
methoddef, types = MethodDefCreator.new(@definitions).dump(name)
|
||||||
mr_creator = MappingRegistryCreator.new(@definitions)
|
mr_creator = MappingRegistryCreator.new(@definitions)
|
||||||
|
|
||||||
c1 = ::XSD::CodeGen::ClassDef.new(class_name)
|
c1 = XSD::CodeGen::ClassDef.new(class_name)
|
||||||
c1.def_require("soap/rpc/standaloneServer")
|
c1.def_require("soap/rpc/standaloneServer")
|
||||||
c1.def_require("soap/mapping/registry")
|
c1.def_require("soap/mapping/registry")
|
||||||
c1.def_const("MappingRegistry", "::SOAP::Mapping::Registry.new")
|
c1.def_const("MappingRegistry", "::SOAP::Mapping::Registry.new")
|
||||||
c1.def_code(mr_creator.dump(types))
|
c1.def_code(mr_creator.dump(types))
|
||||||
c1.def_code <<-EOD
|
c1.def_code <<-EOD
|
||||||
Methods = [
|
Methods = [
|
||||||
#{ methoddef.gsub(/^/, " ") }
|
#{methoddef.gsub(/^/, " ")}
|
||||||
]
|
]
|
||||||
EOD
|
EOD
|
||||||
c2 = ::XSD::CodeGen::ClassDef.new(class_name + "App",
|
c2 = XSD::CodeGen::ClassDef.new(class_name + "App",
|
||||||
"::SOAP::RPC::StandaloneServer")
|
"::SOAP::RPC::StandaloneServer")
|
||||||
c2.def_method("initialize", "*arg") do
|
c2.def_method("initialize", "*arg") do
|
||||||
<<-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 |name_as, name, param_def, soapaction, namespace, style|
|
||||||
qname = XSD::QName.new(namespace, name_as)
|
|
||||||
if style == :document
|
if style == :document
|
||||||
@soaplet.app_scope_router.add_document_method(servant, qname, soapaction, name, param_def)
|
@router.add_document_operation(servant, soapaction, name, param_def)
|
||||||
else
|
else
|
||||||
@soaplet.app_scope_router.add_rpc_method(servant, qname, soapaction, name, param_def)
|
qname = XSD::QName.new(namespace, name_as)
|
||||||
|
@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
|
||||||
|
176
lib/wsdl/soap/wsdl2ruby.rb
Normal file
176
lib/wsdl/soap/wsdl2ruby.rb
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
# WSDL4R - WSDL to ruby mapping library.
|
||||||
|
# Copyright (C) 2002-2005 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 'logger'
|
||||||
|
require 'xsd/qname'
|
||||||
|
require 'wsdl/importer'
|
||||||
|
require 'wsdl/soap/classDefCreator'
|
||||||
|
require 'wsdl/soap/servantSkeltonCreator'
|
||||||
|
require 'wsdl/soap/driverCreator'
|
||||||
|
require 'wsdl/soap/clientSkeltonCreator'
|
||||||
|
require 'wsdl/soap/standaloneServerStubCreator'
|
||||||
|
require 'wsdl/soap/cgiStubCreator'
|
||||||
|
|
||||||
|
|
||||||
|
module WSDL
|
||||||
|
module SOAP
|
||||||
|
|
||||||
|
|
||||||
|
class WSDL2Ruby
|
||||||
|
attr_accessor :location
|
||||||
|
attr_reader :opt
|
||||||
|
attr_accessor :logger
|
||||||
|
attr_accessor :basedir
|
||||||
|
|
||||||
|
def run
|
||||||
|
unless @location
|
||||||
|
raise RuntimeError, "WSDL location not given"
|
||||||
|
end
|
||||||
|
@wsdl = import(@location)
|
||||||
|
@name = @wsdl.name ? @wsdl.name.name : 'default'
|
||||||
|
create_file
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@location = nil
|
||||||
|
@opt = {}
|
||||||
|
@logger = Logger.new(STDERR)
|
||||||
|
@basedir = nil
|
||||||
|
@wsdl = nil
|
||||||
|
@name = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_file
|
||||||
|
create_classdef if @opt.key?('classdef')
|
||||||
|
create_servant_skelton(@opt['servant_skelton']) if @opt.key?('servant_skelton')
|
||||||
|
create_cgi_stub(@opt['cgi_stub']) if @opt.key?('cgi_stub')
|
||||||
|
create_standalone_server_stub(@opt['standalone_server_stub']) if @opt.key?('standalone_server_stub')
|
||||||
|
create_driver(@opt['driver']) if @opt.key?('driver')
|
||||||
|
create_client_skelton(@opt['client_skelton']) if @opt.key?('client_skelton')
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_classdef
|
||||||
|
@logger.info { "Creating class definition." }
|
||||||
|
@classdef_filename = @name + '.rb'
|
||||||
|
check_file(@classdef_filename) or return
|
||||||
|
write_file(@classdef_filename) do |f|
|
||||||
|
f << WSDL::SOAP::ClassDefCreator.new(@wsdl).dump
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_client_skelton(servicename)
|
||||||
|
@logger.info { "Creating client skelton." }
|
||||||
|
servicename ||= @wsdl.services[0].name.name
|
||||||
|
@client_skelton_filename = servicename + 'Client.rb'
|
||||||
|
check_file(@client_skelton_filename) or return
|
||||||
|
write_file(@client_skelton_filename) do |f|
|
||||||
|
f << shbang << "\n"
|
||||||
|
f << "require '#{@driver_filename}'\n\n" if @driver_filename
|
||||||
|
f << WSDL::SOAP::ClientSkeltonCreator.new(@wsdl).dump(
|
||||||
|
create_name(servicename))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_servant_skelton(porttypename)
|
||||||
|
@logger.info { "Creating servant skelton." }
|
||||||
|
@servant_skelton_filename = (porttypename || @name + 'Servant') + '.rb'
|
||||||
|
check_file(@servant_skelton_filename) or return
|
||||||
|
write_file(@servant_skelton_filename) do |f|
|
||||||
|
f << "require '#{@classdef_filename}'\n\n" if @classdef_filename
|
||||||
|
f << WSDL::SOAP::ServantSkeltonCreator.new(@wsdl).dump(
|
||||||
|
create_name(porttypename))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_cgi_stub(servicename)
|
||||||
|
@logger.info { "Creating CGI stub." }
|
||||||
|
servicename ||= @wsdl.services[0].name.name
|
||||||
|
@cgi_stubFilename = servicename + '.cgi'
|
||||||
|
check_file(@cgi_stubFilename) or return
|
||||||
|
write_file(@cgi_stubFilename) do |f|
|
||||||
|
f << shbang << "\n"
|
||||||
|
if @servant_skelton_filename
|
||||||
|
f << "require '#{@servant_skelton_filename}'\n\n"
|
||||||
|
end
|
||||||
|
f << WSDL::SOAP::CGIStubCreator.new(@wsdl).dump(create_name(servicename))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_standalone_server_stub(servicename)
|
||||||
|
@logger.info { "Creating standalone stub." }
|
||||||
|
servicename ||= @wsdl.services[0].name.name
|
||||||
|
@standalone_server_stub_filename = servicename + '.rb'
|
||||||
|
check_file(@standalone_server_stub_filename) or return
|
||||||
|
write_file(@standalone_server_stub_filename) do |f|
|
||||||
|
f << shbang << "\n"
|
||||||
|
f << "require '#{@servant_skelton_filename}'\n\n" if @servant_skelton_filename
|
||||||
|
f << WSDL::SOAP::StandaloneServerStubCreator.new(@wsdl).dump(
|
||||||
|
create_name(servicename))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_driver(porttypename)
|
||||||
|
@logger.info { "Creating driver." }
|
||||||
|
@driver_filename = (porttypename || @name) + 'Driver.rb'
|
||||||
|
check_file(@driver_filename) or return
|
||||||
|
write_file(@driver_filename) do |f|
|
||||||
|
f << "require '#{@classdef_filename}'\n\n" if @classdef_filename
|
||||||
|
f << WSDL::SOAP::DriverCreator.new(@wsdl).dump(
|
||||||
|
create_name(porttypename))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def write_file(filename)
|
||||||
|
if @basedir
|
||||||
|
filename = File.join(basedir, filename)
|
||||||
|
end
|
||||||
|
File.open(filename, "w") do |f|
|
||||||
|
yield f
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_file(filename)
|
||||||
|
if @basedir
|
||||||
|
filename = File.join(basedir, filename)
|
||||||
|
end
|
||||||
|
if FileTest.exist?(filename)
|
||||||
|
if @opt.key?('force')
|
||||||
|
@logger.warn {
|
||||||
|
"File '#{filename}' exists but overrides it."
|
||||||
|
}
|
||||||
|
true
|
||||||
|
else
|
||||||
|
@logger.warn {
|
||||||
|
"File '#{filename}' exists. #{$0} did not override it."
|
||||||
|
}
|
||||||
|
false
|
||||||
|
end
|
||||||
|
else
|
||||||
|
@logger.info { "Creates file '#{filename}'." }
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def shbang
|
||||||
|
"#!/usr/bin/env ruby"
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_name(name)
|
||||||
|
name ? XSD::QName.new(@wsdl.targetnamespace, name) : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def import(location)
|
||||||
|
WSDL::Importer.import(location)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
34
lib/wsdl/xmlSchema/annotation.rb
Normal file
34
lib/wsdl/xmlSchema/annotation.rb
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# WSDL4R - WSDL SOAP documentation element.
|
||||||
|
# Copyright (C) 2003, 2005 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 'wsdl/info'
|
||||||
|
|
||||||
|
|
||||||
|
module WSDL
|
||||||
|
module XMLSchema
|
||||||
|
|
||||||
|
|
||||||
|
class Annotation < Info
|
||||||
|
def initialize
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_element(element)
|
||||||
|
# Accepts any element.
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_attr(attr, value)
|
||||||
|
# Accepts any attribute.
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - XMLSchema attribute definition for WSDL.
|
# WSDL4R - XMLSchema attribute 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;
|
||||||
@ -14,34 +14,74 @@ module XMLSchema
|
|||||||
|
|
||||||
|
|
||||||
class Attribute < Info
|
class Attribute < Info
|
||||||
attr_accessor :ref
|
class << self
|
||||||
attr_accessor :use
|
if RUBY_VERSION > "1.7.0"
|
||||||
attr_accessor :form
|
def attr_reader_ref(symbol)
|
||||||
attr_accessor :name
|
name = symbol.to_s
|
||||||
attr_accessor :type
|
self.__send__(:define_method, name, proc {
|
||||||
attr_accessor :default
|
instance_variable_get("@#{name}") ||
|
||||||
attr_accessor :fixed
|
(refelement ? refelement.__send__(name) : nil)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
else
|
||||||
|
def attr_reader_ref(symbol)
|
||||||
|
name = symbol.to_s
|
||||||
|
module_eval <<-EOS
|
||||||
|
def #{name}
|
||||||
|
@#{name} || (refelement ? refelement.#{name} : nil)
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_writer :use
|
||||||
|
attr_writer :form
|
||||||
|
attr_writer :name
|
||||||
|
attr_writer :type
|
||||||
|
attr_writer :local_simpletype
|
||||||
|
attr_writer :default
|
||||||
|
attr_writer :fixed
|
||||||
|
|
||||||
|
attr_reader_ref :use
|
||||||
|
attr_reader_ref :form
|
||||||
|
attr_reader_ref :name
|
||||||
|
attr_reader_ref :type
|
||||||
|
attr_reader_ref :local_simpletype
|
||||||
|
attr_reader_ref :default
|
||||||
|
attr_reader_ref :fixed
|
||||||
|
|
||||||
|
attr_accessor :ref
|
||||||
attr_accessor :arytype
|
attr_accessor :arytype
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
@ref = nil
|
|
||||||
@use = nil
|
@use = nil
|
||||||
@form = nil
|
@form = nil
|
||||||
@name = nil
|
@name = nil
|
||||||
@type = nil
|
@type = nil
|
||||||
|
@local_simpletype = nil
|
||||||
@default = nil
|
@default = nil
|
||||||
@fixed = nil
|
@fixed = nil
|
||||||
|
@ref = nil
|
||||||
|
@refelement = nil
|
||||||
@arytype = nil
|
@arytype = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def refelement
|
||||||
|
@refelement ||= root.collect_attributes[@ref]
|
||||||
|
end
|
||||||
|
|
||||||
def targetnamespace
|
def targetnamespace
|
||||||
parent.targetnamespace
|
parent.targetnamespace
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_element(element)
|
def parse_element(element)
|
||||||
nil
|
case element
|
||||||
|
when SimpleTypeName
|
||||||
|
@local_simpletype = SimpleType.new
|
||||||
|
@local_simpletype
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_attr(attr, value)
|
def parse_attr(attr, value)
|
||||||
|
@ -26,12 +26,17 @@ class ComplexContent < Info
|
|||||||
@derivetype = nil
|
@derivetype = nil
|
||||||
@content = nil
|
@content = nil
|
||||||
@attributes = XSD::NamedElements.new
|
@attributes = XSD::NamedElements.new
|
||||||
|
@basetype = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def targetnamespace
|
def targetnamespace
|
||||||
parent.targetnamespace
|
parent.targetnamespace
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def basetype
|
||||||
|
@basetype ||= root.collect_complextypes[@base]
|
||||||
|
end
|
||||||
|
|
||||||
def parse_element(element)
|
def parse_element(element)
|
||||||
case element
|
case element
|
||||||
when RestrictionName, ExtensionName
|
when RestrictionName, ExtensionName
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - XMLSchema data definitions.
|
# WSDL4R - XMLSchema data definitions.
|
||||||
# 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;
|
||||||
@ -7,10 +7,13 @@
|
|||||||
|
|
||||||
|
|
||||||
require 'xsd/datatypes'
|
require 'xsd/datatypes'
|
||||||
|
require 'wsdl/xmlSchema/annotation'
|
||||||
require 'wsdl/xmlSchema/schema'
|
require 'wsdl/xmlSchema/schema'
|
||||||
require 'wsdl/xmlSchema/import'
|
require 'wsdl/xmlSchema/import'
|
||||||
|
require 'wsdl/xmlSchema/include'
|
||||||
require 'wsdl/xmlSchema/simpleType'
|
require 'wsdl/xmlSchema/simpleType'
|
||||||
require 'wsdl/xmlSchema/simpleRestriction'
|
require 'wsdl/xmlSchema/simpleRestriction'
|
||||||
|
require 'wsdl/xmlSchema/simpleExtension'
|
||||||
require 'wsdl/xmlSchema/complexType'
|
require 'wsdl/xmlSchema/complexType'
|
||||||
require 'wsdl/xmlSchema/complexContent'
|
require 'wsdl/xmlSchema/complexContent'
|
||||||
require 'wsdl/xmlSchema/simpleContent'
|
require 'wsdl/xmlSchema/simpleContent'
|
||||||
@ -22,12 +25,15 @@ require 'wsdl/xmlSchema/sequence'
|
|||||||
require 'wsdl/xmlSchema/attribute'
|
require 'wsdl/xmlSchema/attribute'
|
||||||
require 'wsdl/xmlSchema/unique'
|
require 'wsdl/xmlSchema/unique'
|
||||||
require 'wsdl/xmlSchema/enumeration'
|
require 'wsdl/xmlSchema/enumeration'
|
||||||
|
require 'wsdl/xmlSchema/length'
|
||||||
|
require 'wsdl/xmlSchema/pattern'
|
||||||
|
|
||||||
module WSDL
|
module WSDL
|
||||||
module XMLSchema
|
module XMLSchema
|
||||||
|
|
||||||
|
|
||||||
AllName = XSD::QName.new(XSD::Namespace, 'all')
|
AllName = XSD::QName.new(XSD::Namespace, 'all')
|
||||||
|
AnnotationName = XSD::QName.new(XSD::Namespace, 'annotation')
|
||||||
AnyName = XSD::QName.new(XSD::Namespace, 'any')
|
AnyName = XSD::QName.new(XSD::Namespace, 'any')
|
||||||
AttributeName = XSD::QName.new(XSD::Namespace, 'attribute')
|
AttributeName = XSD::QName.new(XSD::Namespace, 'attribute')
|
||||||
ChoiceName = XSD::QName.new(XSD::Namespace, 'choice')
|
ChoiceName = XSD::QName.new(XSD::Namespace, 'choice')
|
||||||
@ -37,6 +43,9 @@ ElementName = XSD::QName.new(XSD::Namespace, 'element')
|
|||||||
EnumerationName = XSD::QName.new(XSD::Namespace, 'enumeration')
|
EnumerationName = XSD::QName.new(XSD::Namespace, 'enumeration')
|
||||||
ExtensionName = XSD::QName.new(XSD::Namespace, 'extension')
|
ExtensionName = XSD::QName.new(XSD::Namespace, 'extension')
|
||||||
ImportName = XSD::QName.new(XSD::Namespace, 'import')
|
ImportName = XSD::QName.new(XSD::Namespace, 'import')
|
||||||
|
IncludeName = XSD::QName.new(XSD::Namespace, 'include')
|
||||||
|
LengthName = XSD::QName.new(XSD::Namespace, 'length')
|
||||||
|
PatternName = XSD::QName.new(XSD::Namespace, 'pattern')
|
||||||
RestrictionName = XSD::QName.new(XSD::Namespace, 'restriction')
|
RestrictionName = XSD::QName.new(XSD::Namespace, 'restriction')
|
||||||
SequenceName = XSD::QName.new(XSD::Namespace, 'sequence')
|
SequenceName = XSD::QName.new(XSD::Namespace, 'sequence')
|
||||||
SchemaName = XSD::QName.new(XSD::Namespace, 'schema')
|
SchemaName = XSD::QName.new(XSD::Namespace, 'schema')
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - XMLSchema element definition for WSDL.
|
# WSDL4R - XMLSchema element 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;
|
||||||
@ -14,23 +14,62 @@ module XMLSchema
|
|||||||
|
|
||||||
|
|
||||||
class Element < Info
|
class Element < Info
|
||||||
attr_accessor :name # required
|
class << self
|
||||||
attr_accessor :type
|
if RUBY_VERSION > "1.7.0"
|
||||||
attr_accessor :local_complextype
|
def attr_reader_ref(symbol)
|
||||||
attr_accessor :constraint
|
name = symbol.to_s
|
||||||
attr_accessor :maxoccurs
|
self.__send__(:define_method, name, proc {
|
||||||
attr_accessor :minoccurs
|
instance_variable_get("@#{name}") ||
|
||||||
attr_accessor :nillable
|
(refelement ? refelement.__send__(name) : nil)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
else
|
||||||
|
def attr_reader_ref(symbol)
|
||||||
|
name = symbol.to_s
|
||||||
|
module_eval <<-EOS
|
||||||
|
def #{name}
|
||||||
|
@#{name} || (refelement ? refelement.#{name} : nil)
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(name = nil, type = XSD::AnyTypeName)
|
attr_writer :name # required
|
||||||
|
attr_writer :type
|
||||||
|
attr_writer :local_simpletype
|
||||||
|
attr_writer :local_complextype
|
||||||
|
attr_writer :constraint
|
||||||
|
attr_writer :maxoccurs
|
||||||
|
attr_writer :minoccurs
|
||||||
|
attr_writer :nillable
|
||||||
|
|
||||||
|
attr_reader_ref :name
|
||||||
|
attr_reader_ref :type
|
||||||
|
attr_reader_ref :local_simpletype
|
||||||
|
attr_reader_ref :local_complextype
|
||||||
|
attr_reader_ref :constraint
|
||||||
|
attr_reader_ref :maxoccurs
|
||||||
|
attr_reader_ref :minoccurs
|
||||||
|
attr_reader_ref :nillable
|
||||||
|
|
||||||
|
attr_accessor :ref
|
||||||
|
|
||||||
|
def initialize(name = nil, type = nil)
|
||||||
super()
|
super()
|
||||||
@name = name
|
@name = name
|
||||||
@type = type
|
@type = type
|
||||||
@local_complextype = nil
|
@local_simpletype = @local_complextype = nil
|
||||||
@constraint = nil
|
@constraint = nil
|
||||||
@maxoccurs = '1'
|
@maxoccurs = '1'
|
||||||
@minoccurs = '1'
|
@minoccurs = '1'
|
||||||
@nillable = nil
|
@nillable = nil
|
||||||
|
@ref = nil
|
||||||
|
@refelement = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def refelement
|
||||||
|
@refelement ||= root.collect_elements[@ref]
|
||||||
end
|
end
|
||||||
|
|
||||||
def targetnamespace
|
def targetnamespace
|
||||||
@ -44,6 +83,9 @@ class Element < Info
|
|||||||
|
|
||||||
def parse_element(element)
|
def parse_element(element)
|
||||||
case element
|
case element
|
||||||
|
when SimpleTypeName
|
||||||
|
@local_simpletype = SimpleType.new
|
||||||
|
@local_simpletype
|
||||||
when ComplexTypeName
|
when ComplexTypeName
|
||||||
@type = nil
|
@type = nil
|
||||||
@local_complextype = ComplexType.new
|
@local_complextype = ComplexType.new
|
||||||
@ -62,19 +104,19 @@ class Element < Info
|
|||||||
@name = XSD::QName.new(targetnamespace, value.source)
|
@name = XSD::QName.new(targetnamespace, value.source)
|
||||||
when TypeAttrName
|
when TypeAttrName
|
||||||
@type = value
|
@type = value
|
||||||
|
when RefAttrName
|
||||||
|
@ref = value
|
||||||
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(
|
raise Parser::AttrConstraintError.new("cannot parse #{value} for #{attr}")
|
||||||
"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(
|
raise Parser::AttrConstraintError.new("cannot parse #{value} for #{attr}")
|
||||||
"Cannot parse #{ value } for #{ attr }.")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@minoccurs = value.source
|
@minoccurs = value.source
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - XMLSchema import definition.
|
# WSDL4R - XMLSchema import definition.
|
||||||
# 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;
|
||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
require 'wsdl/info'
|
require 'wsdl/info'
|
||||||
|
require 'wsdl/xmlSchema/importer'
|
||||||
|
|
||||||
|
|
||||||
module WSDL
|
module WSDL
|
||||||
@ -16,11 +17,13 @@ module XMLSchema
|
|||||||
class Import < Info
|
class Import < Info
|
||||||
attr_reader :namespace
|
attr_reader :namespace
|
||||||
attr_reader :schemalocation
|
attr_reader :schemalocation
|
||||||
|
attr_reader :content
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
@namespace = nil
|
@namespace = nil
|
||||||
@schemalocation = nil
|
@schemalocation = nil
|
||||||
|
@content = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_element(element)
|
def parse_element(element)
|
||||||
@ -32,11 +35,29 @@ class Import < Info
|
|||||||
when NamespaceAttrName
|
when NamespaceAttrName
|
||||||
@namespace = value.source
|
@namespace = value.source
|
||||||
when SchemaLocationAttrName
|
when SchemaLocationAttrName
|
||||||
@schemalocation = value.source
|
@schemalocation = URI.parse(value.source)
|
||||||
|
if @schemalocation.relative? and !parent.location.nil? and
|
||||||
|
!parent.location.relative?
|
||||||
|
@schemalocation = parent.location + @schemalocation
|
||||||
|
end
|
||||||
|
if root.importedschema.key?(@schemalocation)
|
||||||
|
@content = root.importedschema[@schemalocation]
|
||||||
|
else
|
||||||
|
root.importedschema[@schemalocation] = nil # placeholder
|
||||||
|
@content = import(@schemalocation)
|
||||||
|
root.importedschema[@schemalocation] = @content
|
||||||
|
end
|
||||||
|
@schemalocation
|
||||||
else
|
else
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def import(location)
|
||||||
|
Importer.import(location, root)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
81
lib/wsdl/xmlSchema/importer.rb
Normal file
81
lib/wsdl/xmlSchema/importer.rb
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# WSDL4R - XSD importer library.
|
||||||
|
# Copyright (C) 2003, 2005 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/httpconfigloader'
|
||||||
|
require 'wsdl/xmlSchema/parser'
|
||||||
|
|
||||||
|
|
||||||
|
module WSDL
|
||||||
|
module XMLSchema
|
||||||
|
|
||||||
|
|
||||||
|
class Importer
|
||||||
|
def self.import(location, originalroot = nil)
|
||||||
|
new.import(location, originalroot)
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@web_client = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def import(location, originalroot = nil)
|
||||||
|
unless location.is_a?(URI)
|
||||||
|
location = URI.parse(location)
|
||||||
|
end
|
||||||
|
content = parse(fetch(location), location, originalroot)
|
||||||
|
content.location = location
|
||||||
|
content
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def parse(content, location, originalroot)
|
||||||
|
opt = {
|
||||||
|
:location => location,
|
||||||
|
:originalroot => originalroot
|
||||||
|
}
|
||||||
|
WSDL::XMLSchema::Parser.new(opt).parse(content)
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch(location)
|
||||||
|
warn("importing: #{location}") if $DEBUG
|
||||||
|
content = nil
|
||||||
|
if location.scheme == 'file' or
|
||||||
|
(location.relative? and FileTest.exist?(location.path))
|
||||||
|
content = File.open(location.path).read
|
||||||
|
else
|
||||||
|
client = web_client.new(nil, "WSDL4R")
|
||||||
|
client.proxy = ::SOAP::Env::HTTP_PROXY
|
||||||
|
client.no_proxy = ::SOAP::Env::NO_PROXY
|
||||||
|
if opt = ::SOAP::Property.loadproperty(::SOAP::PropertyName)
|
||||||
|
::SOAP::HTTPConfigLoader.set_options(client, opt["client.protocol.http"])
|
||||||
|
end
|
||||||
|
content = client.get_content(location)
|
||||||
|
end
|
||||||
|
content
|
||||||
|
end
|
||||||
|
|
||||||
|
def web_client
|
||||||
|
@web_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
|
||||||
|
@web_client
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
54
lib/wsdl/xmlSchema/include.rb
Normal file
54
lib/wsdl/xmlSchema/include.rb
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# WSDL4R - XMLSchema include definition.
|
||||||
|
# Copyright (C) 2005 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 'wsdl/info'
|
||||||
|
require 'wsdl/xmlSchema/importer'
|
||||||
|
|
||||||
|
|
||||||
|
module WSDL
|
||||||
|
module XMLSchema
|
||||||
|
|
||||||
|
|
||||||
|
class Include < Info
|
||||||
|
attr_reader :schemalocation
|
||||||
|
attr_reader :content
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super
|
||||||
|
@schemalocation = nil
|
||||||
|
@content = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_element(element)
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_attr(attr, value)
|
||||||
|
case attr
|
||||||
|
when SchemaLocationAttrName
|
||||||
|
@schemalocation = URI.parse(value.source)
|
||||||
|
if @schemalocation.relative?
|
||||||
|
@schemalocation = parent.location + @schemalocation
|
||||||
|
end
|
||||||
|
@content = import(@schemalocation)
|
||||||
|
@schemalocation
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def import(location)
|
||||||
|
Importer.import(location)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
35
lib/wsdl/xmlSchema/length.rb
Normal file
35
lib/wsdl/xmlSchema/length.rb
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# WSDL4R - XMLSchema length definition for WSDL.
|
||||||
|
# Copyright (C) 2005 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 'wsdl/info'
|
||||||
|
|
||||||
|
|
||||||
|
module WSDL
|
||||||
|
module XMLSchema
|
||||||
|
|
||||||
|
|
||||||
|
class Length < Info
|
||||||
|
def initialize
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_element(element)
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_attr(attr, value)
|
||||||
|
case attr
|
||||||
|
when ValueAttrName
|
||||||
|
value.source
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - WSDL XML Instance parser library.
|
# WSDL4R - WSDL XML Instance parser library.
|
||||||
# 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;
|
||||||
@ -51,6 +51,9 @@ public
|
|||||||
@parser = XSD::XMLParser.create_parser(self, opt)
|
@parser = XSD::XMLParser.create_parser(self, opt)
|
||||||
@parsestack = nil
|
@parsestack = nil
|
||||||
@lastnode = nil
|
@lastnode = nil
|
||||||
|
@ignored = {}
|
||||||
|
@location = opt[:location]
|
||||||
|
@originalroot = opt[:originalroot]
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse(string_or_readable)
|
def parse(string_or_readable)
|
||||||
@ -94,7 +97,7 @@ public
|
|||||||
def end_element(name)
|
def end_element(name)
|
||||||
lastframe = @parsestack.pop
|
lastframe = @parsestack.pop
|
||||||
unless name == lastframe.name
|
unless name == lastframe.name
|
||||||
raise UnexpectedElementError.new("Closing element name '#{ name }' does not match with opening element '#{ lastframe.name }'.")
|
raise UnexpectedElementError.new("closing element name '#{name}' does not match with opening element '#{lastframe.name}'")
|
||||||
end
|
end
|
||||||
decode_tag_end(lastframe.ns, lastframe.node)
|
decode_tag_end(lastframe.ns, lastframe.node)
|
||||||
@lastnode = lastframe.node
|
@lastnode = lastframe.node
|
||||||
@ -104,20 +107,31 @@ private
|
|||||||
|
|
||||||
def decode_tag(ns, name, attrs, parent)
|
def decode_tag(ns, name, attrs, parent)
|
||||||
o = nil
|
o = nil
|
||||||
element = ns.parse(name)
|
elename = ns.parse(name)
|
||||||
if !parent
|
if !parent
|
||||||
if element == SchemaName
|
if elename == SchemaName
|
||||||
o = Schema.parse_element(element)
|
o = Schema.parse_element(elename)
|
||||||
|
o.location = @location
|
||||||
else
|
else
|
||||||
raise UnknownElementError.new("Unknown element #{ element }.")
|
raise UnknownElementError.new("unknown element: #{elename}")
|
||||||
end
|
end
|
||||||
|
o.root = @originalroot if @originalroot # o.root = o otherwise
|
||||||
else
|
else
|
||||||
o = parent.parse_element(element)
|
if elename == AnnotationName
|
||||||
|
# only the first annotation element is allowed for each element.
|
||||||
|
o = Annotation.new
|
||||||
|
else
|
||||||
|
o = parent.parse_element(elename)
|
||||||
|
end
|
||||||
unless o
|
unless o
|
||||||
STDERR.puts("Unknown element #{ element }.")
|
unless @ignored.key?(elename)
|
||||||
|
warn("ignored element: #{elename} of #{parent.class}")
|
||||||
|
@ignored[elename] = elename
|
||||||
|
end
|
||||||
o = Documentation.new # which accepts any element.
|
o = Documentation.new # which accepts any element.
|
||||||
end
|
end
|
||||||
# node could be a pseudo element. pseudo element has its own parent.
|
# node could be a pseudo element. pseudo element has its own parent.
|
||||||
|
o.root = parent.root
|
||||||
o.parent = parent if o.parent.nil?
|
o.parent = parent if o.parent.nil?
|
||||||
end
|
end
|
||||||
attrs.each do |key, value|
|
attrs.each do |key, value|
|
||||||
@ -128,7 +142,10 @@ private
|
|||||||
o.id = value_ele
|
o.id = value_ele
|
||||||
else
|
else
|
||||||
unless o.parse_attr(attr_ele, value_ele)
|
unless o.parse_attr(attr_ele, value_ele)
|
||||||
STDERR.puts("Unknown attr #{ attr_ele }.")
|
unless @ignored.key?(attr_ele)
|
||||||
|
warn("ignored attr: #{attr_ele}")
|
||||||
|
@ignored[attr_ele] = attr_ele
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
36
lib/wsdl/xmlSchema/pattern.rb
Normal file
36
lib/wsdl/xmlSchema/pattern.rb
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# WSDL4R - XMLSchema pattern definition for WSDL.
|
||||||
|
# Copyright (C) 2005 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 'wsdl/info'
|
||||||
|
|
||||||
|
|
||||||
|
module WSDL
|
||||||
|
module XMLSchema
|
||||||
|
|
||||||
|
|
||||||
|
class Pattern < Info
|
||||||
|
def initialize
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_element(element)
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_attr(attr, value)
|
||||||
|
case attr
|
||||||
|
when ValueAttrName
|
||||||
|
parent.pattern = /\A#{value.source}\z/n
|
||||||
|
value.source
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
@ -24,6 +24,8 @@ class Schema < Info
|
|||||||
attr_accessor :attributeformdefault
|
attr_accessor :attributeformdefault
|
||||||
attr_accessor :elementformdefault
|
attr_accessor :elementformdefault
|
||||||
|
|
||||||
|
attr_reader :importedschema
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
@targetnamespace = nil
|
@targetnamespace = nil
|
||||||
@ -33,6 +35,17 @@ class Schema < Info
|
|||||||
@attributes = XSD::NamedElements.new
|
@attributes = XSD::NamedElements.new
|
||||||
@imports = []
|
@imports = []
|
||||||
@elementformdefault = "qualified"
|
@elementformdefault = "qualified"
|
||||||
|
@importedschema = {}
|
||||||
|
@location = nil
|
||||||
|
@root = self
|
||||||
|
end
|
||||||
|
|
||||||
|
def location
|
||||||
|
@location || (root.nil? ? nil : root.location)
|
||||||
|
end
|
||||||
|
|
||||||
|
def location=(location)
|
||||||
|
@location = location
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_element(element)
|
def parse_element(element)
|
||||||
@ -41,6 +54,10 @@ class Schema < Info
|
|||||||
o = Import.new
|
o = Import.new
|
||||||
@imports << o
|
@imports << o
|
||||||
o
|
o
|
||||||
|
when IncludeName
|
||||||
|
o = Include.new
|
||||||
|
@imports << o
|
||||||
|
o
|
||||||
when ComplexTypeName
|
when ComplexTypeName
|
||||||
o = ComplexType.new
|
o = ComplexType.new
|
||||||
@complextypes << o
|
@complextypes << o
|
||||||
@ -55,6 +72,7 @@ class Schema < Info
|
|||||||
o
|
o
|
||||||
when AttributeName
|
when AttributeName
|
||||||
o = Attribute.new
|
o = Attribute.new
|
||||||
|
@attributes << o
|
||||||
o
|
o
|
||||||
else
|
else
|
||||||
nil
|
nil
|
||||||
@ -74,21 +92,39 @@ class Schema < Info
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def collect_attributes
|
||||||
|
result = XSD::NamedElements.new
|
||||||
|
result.concat(@attributes)
|
||||||
|
@imports.each do |import|
|
||||||
|
result.concat(import.content.collect_attributes) if import.content
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
def collect_elements
|
def collect_elements
|
||||||
result = XSD::NamedElements.new
|
result = XSD::NamedElements.new
|
||||||
result.concat(@elements)
|
result.concat(@elements)
|
||||||
|
@imports.each do |import|
|
||||||
|
result.concat(import.content.collect_elements) if import.content
|
||||||
|
end
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
def collect_complextypes
|
def collect_complextypes
|
||||||
result = XSD::NamedElements.new
|
result = XSD::NamedElements.new
|
||||||
result.concat(@complextypes)
|
result.concat(@complextypes)
|
||||||
|
@imports.each do |import|
|
||||||
|
result.concat(import.content.collect_complextypes) if import.content
|
||||||
|
end
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
def collect_simpletypes
|
def collect_simpletypes
|
||||||
result = XSD::NamedElements.new
|
result = XSD::NamedElements.new
|
||||||
result.concat(@simpletypes)
|
result.concat(@simpletypes)
|
||||||
|
@imports.each do |import|
|
||||||
|
result.concat(import.content.collect_simpletypes) if import.content
|
||||||
|
end
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - XMLSchema simpleContent definition for WSDL.
|
# WSDL4R - XMLSchema simpleContent definition for WSDL.
|
||||||
# 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;
|
||||||
@ -15,17 +15,21 @@ module XMLSchema
|
|||||||
|
|
||||||
|
|
||||||
class SimpleContent < Info
|
class SimpleContent < Info
|
||||||
attr_accessor :base
|
attr_reader :restriction
|
||||||
attr_reader :derivetype
|
attr_reader :extension
|
||||||
attr_reader :content
|
|
||||||
attr_reader :attributes
|
def check_lexical_format(value)
|
||||||
|
check(value)
|
||||||
|
end
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
@base = nil
|
@restriction = nil
|
||||||
@derivetype = nil
|
@extension = nil
|
||||||
@content = nil
|
end
|
||||||
@attributes = XSD::NamedElements.new
|
|
||||||
|
def base
|
||||||
|
content.base
|
||||||
end
|
end
|
||||||
|
|
||||||
def targetnamespace
|
def targetnamespace
|
||||||
@ -34,28 +38,24 @@ class SimpleContent < Info
|
|||||||
|
|
||||||
def parse_element(element)
|
def parse_element(element)
|
||||||
case element
|
case element
|
||||||
when RestrictionName, ExtensionName
|
when RestrictionName
|
||||||
@derivetype = element.name
|
@restriction = SimpleRestriction.new
|
||||||
self
|
@restriction
|
||||||
when AttributeName
|
when ExtensionName
|
||||||
if @derivetype.nil?
|
@extension = SimpleExtension.new
|
||||||
raise Parser::ElementConstraintError.new("base attr not found.")
|
@extension
|
||||||
end
|
|
||||||
o = Attribute.new
|
|
||||||
@attributes << o
|
|
||||||
o
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_attr(attr, value)
|
private
|
||||||
if @derivetype.nil?
|
|
||||||
return nil
|
def content
|
||||||
|
@restriction || @extension
|
||||||
end
|
end
|
||||||
case attr
|
|
||||||
when BaseAttrName
|
def check(value)
|
||||||
@base = value
|
unless content.valid?(value)
|
||||||
else
|
raise XSD::ValueSpaceError.new("#{@name}: cannot accept '#{value}'")
|
||||||
nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
54
lib/wsdl/xmlSchema/simpleExtension.rb
Normal file
54
lib/wsdl/xmlSchema/simpleExtension.rb
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# WSDL4R - XMLSchema simpleType extension definition for WSDL.
|
||||||
|
# Copyright (C) 2005 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 'wsdl/info'
|
||||||
|
require 'xsd/namedelements'
|
||||||
|
|
||||||
|
|
||||||
|
module WSDL
|
||||||
|
module XMLSchema
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleExtension < Info
|
||||||
|
attr_reader :base
|
||||||
|
attr_reader :attributes
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super
|
||||||
|
@base = nil
|
||||||
|
@attributes = XSD::NamedElements.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def targetnamespace
|
||||||
|
parent.targetnamespace
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid?(value)
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_element(element)
|
||||||
|
case element
|
||||||
|
when AttributeName
|
||||||
|
o = Attribute.new
|
||||||
|
@attributes << o
|
||||||
|
o
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_attr(attr, value)
|
||||||
|
case attr
|
||||||
|
when BaseAttrName
|
||||||
|
@base = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
@ -1,4 +1,4 @@
|
|||||||
# WSDL4R - XMLSchema simpleType definition for WSDL.
|
# WSDL4R - XMLSchema simpleContent restriction definition for WSDL.
|
||||||
# Copyright (C) 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 2004 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
|
||||||
@ -17,21 +17,32 @@ module XMLSchema
|
|||||||
class SimpleRestriction < Info
|
class SimpleRestriction < Info
|
||||||
attr_reader :base
|
attr_reader :base
|
||||||
attr_reader :enumeration
|
attr_reader :enumeration
|
||||||
|
attr_accessor :length
|
||||||
|
attr_accessor :pattern
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
@base = nil
|
@base = nil
|
||||||
@enumeration = [] # NamedElements?
|
@enumeration = [] # NamedElements?
|
||||||
|
@length = nil
|
||||||
|
@pattern = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def valid?(value)
|
def valid?(value)
|
||||||
@enumeration.include?(value)
|
return false unless check_restriction(value)
|
||||||
|
return false unless check_length(value)
|
||||||
|
return false unless check_pattern(value)
|
||||||
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_element(element)
|
def parse_element(element)
|
||||||
case element
|
case element
|
||||||
when EnumerationName
|
when EnumerationName
|
||||||
Enumeration.new # just a parsing handler
|
Enumeration.new # just a parsing handler
|
||||||
|
when LengthName
|
||||||
|
Length.new # just a parsing handler
|
||||||
|
when PatternName
|
||||||
|
Pattern.new # just a parsing handler
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -41,6 +52,20 @@ class SimpleRestriction < Info
|
|||||||
@base = value
|
@base = value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def check_restriction(value)
|
||||||
|
@enumeration.empty? or @enumeration.include?(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_length(value)
|
||||||
|
@length.nil? or value.size == @length
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_pattern(value)
|
||||||
|
@pattern.nil? or @pattern =~ value
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# WSDL4R - XMLSchema simpleType definition for WSDL.
|
# WSDL4R - XMLSchema simpleType definition for WSDL.
|
||||||
# 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;
|
||||||
@ -16,15 +16,11 @@ module XMLSchema
|
|||||||
|
|
||||||
class SimpleType < Info
|
class SimpleType < Info
|
||||||
attr_accessor :name
|
attr_accessor :name
|
||||||
attr_reader :derivetype
|
|
||||||
attr_reader :restriction
|
attr_reader :restriction
|
||||||
|
|
||||||
def check_lexical_format(value)
|
def check_lexical_format(value)
|
||||||
if @restriction
|
if @restriction
|
||||||
check_restriction(value)
|
check_restriction(value)
|
||||||
elsif @extension
|
|
||||||
raise NotImplementedError
|
|
||||||
# ToDo
|
|
||||||
else
|
else
|
||||||
raise ArgumentError.new("incomplete simpleType")
|
raise ArgumentError.new("incomplete simpleType")
|
||||||
end
|
end
|
||||||
@ -33,8 +29,6 @@ class SimpleType < Info
|
|||||||
def base
|
def base
|
||||||
if @restriction
|
if @restriction
|
||||||
@restriction.base
|
@restriction.base
|
||||||
elsif @extension
|
|
||||||
@extension.base
|
|
||||||
else
|
else
|
||||||
raise ArgumentError.new("incomplete simpleType")
|
raise ArgumentError.new("incomplete simpleType")
|
||||||
end
|
end
|
||||||
@ -43,7 +37,6 @@ class SimpleType < Info
|
|||||||
def initialize(name = nil)
|
def initialize(name = nil)
|
||||||
super()
|
super()
|
||||||
@name = name
|
@name = name
|
||||||
@derivetype = nil
|
|
||||||
@restriction = nil
|
@restriction = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -55,7 +48,6 @@ class SimpleType < Info
|
|||||||
case element
|
case element
|
||||||
when RestrictionName
|
when RestrictionName
|
||||||
@restriction = SimpleRestriction.new
|
@restriction = SimpleRestriction.new
|
||||||
@derivetype = element.name
|
|
||||||
@restriction
|
@restriction
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -71,7 +63,7 @@ private
|
|||||||
|
|
||||||
def check_restriction(value)
|
def check_restriction(value)
|
||||||
unless @restriction.valid?(value)
|
unless @restriction.valid?(value)
|
||||||
raise ::XSD::ValueSpaceError.new("#{@name}: cannot accept '#{value}'.")
|
raise XSD::ValueSpaceError.new("#{@name}: cannot accept '#{value}'")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
107
lib/wsdl/xmlSchema/xsd2ruby.rb
Normal file
107
lib/wsdl/xmlSchema/xsd2ruby.rb
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
# XSD4R - XSD to ruby mapping library.
|
||||||
|
# Copyright (C) 2005 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 'xsd/codegen/gensupport'
|
||||||
|
require 'wsdl/xmlSchema/importer'
|
||||||
|
require 'wsdl/soap/classDefCreator'
|
||||||
|
|
||||||
|
|
||||||
|
module WSDL
|
||||||
|
module XMLSchema
|
||||||
|
|
||||||
|
|
||||||
|
class XSD2Ruby
|
||||||
|
attr_accessor :location
|
||||||
|
attr_reader :opt
|
||||||
|
attr_accessor :logger
|
||||||
|
attr_accessor :basedir
|
||||||
|
|
||||||
|
def run
|
||||||
|
unless @location
|
||||||
|
raise RuntimeError, "XML Schema location not given"
|
||||||
|
end
|
||||||
|
@xsd = import(@location)
|
||||||
|
@name = create_classname(@xsd)
|
||||||
|
create_file
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@location = nil
|
||||||
|
@opt = {}
|
||||||
|
@logger = Logger.new(STDERR)
|
||||||
|
@basedir = nil
|
||||||
|
@xsd = nil
|
||||||
|
@name = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_file
|
||||||
|
create_classdef
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_classdef
|
||||||
|
@logger.info { "Creating class definition." }
|
||||||
|
@classdef_filename = @name + '.rb'
|
||||||
|
check_file(@classdef_filename) or return
|
||||||
|
write_file(@classdef_filename) do |f|
|
||||||
|
f << WSDL::SOAP::ClassDefCreator.new(@xsd).dump
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def write_file(filename)
|
||||||
|
if @basedir
|
||||||
|
filename = File.join(basedir, filename)
|
||||||
|
end
|
||||||
|
File.open(filename, "w") do |f|
|
||||||
|
yield f
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_file(filename)
|
||||||
|
if @basedir
|
||||||
|
filename = File.join(basedir, filename)
|
||||||
|
end
|
||||||
|
if FileTest.exist?(filename)
|
||||||
|
if @opt.key?('force')
|
||||||
|
@logger.warn {
|
||||||
|
"File '#{filename}' exists but overrides it."
|
||||||
|
}
|
||||||
|
true
|
||||||
|
else
|
||||||
|
@logger.warn {
|
||||||
|
"File '#{filename}' exists. #{$0} did not override it."
|
||||||
|
}
|
||||||
|
false
|
||||||
|
end
|
||||||
|
else
|
||||||
|
@logger.info { "Creates file '#{filename}'." }
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_classname(xsd)
|
||||||
|
name = nil
|
||||||
|
if xsd.targetnamespace
|
||||||
|
name = xsd.targetnamespace.scan(/[a-zA-Z0-9]+$/)[0]
|
||||||
|
end
|
||||||
|
if name.nil?
|
||||||
|
'default'
|
||||||
|
else
|
||||||
|
XSD::CodeGen::GenSupport.safevarname(name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def import(location)
|
||||||
|
WSDL::XMLSchema::Importer.import(location)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
@ -71,7 +71,7 @@ public
|
|||||||
end
|
end
|
||||||
|
|
||||||
def Charset.encoding=(encoding)
|
def Charset.encoding=(encoding)
|
||||||
STDERR.puts("xsd charset is set to #{encoding}") if $DEBUG
|
warn("xsd charset is set to #{encoding}") if $DEBUG
|
||||||
@encoding = encoding
|
@encoding = encoding
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ class ClassDef < ModuleDef
|
|||||||
end
|
end
|
||||||
buf << dump_class_def_end
|
buf << dump_class_def_end
|
||||||
buf << dump_package_def_end(package) unless package.empty?
|
buf << dump_package_def_end(package) unless package.empty?
|
||||||
buf
|
buf.gsub(/^\s+$/, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -21,10 +21,10 @@ module CommentDef
|
|||||||
private
|
private
|
||||||
|
|
||||||
def dump_comment
|
def dump_comment
|
||||||
if /^#/ =~ @comment
|
if /\A#/ =~ @comment
|
||||||
format(@comment)
|
format(@comment)
|
||||||
else
|
else
|
||||||
format(@comment).gsub(/^/, "# ")
|
format(@comment).gsub(/^/, '# ')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -9,6 +9,49 @@
|
|||||||
module XSD
|
module XSD
|
||||||
module CodeGen
|
module CodeGen
|
||||||
|
|
||||||
|
# from the file 'keywords' in 1.9.
|
||||||
|
KEYWORD = %w(
|
||||||
|
__LINE__
|
||||||
|
__FILE__
|
||||||
|
BEGIN
|
||||||
|
END
|
||||||
|
alias
|
||||||
|
and
|
||||||
|
begin
|
||||||
|
break
|
||||||
|
case
|
||||||
|
class
|
||||||
|
def
|
||||||
|
defined?
|
||||||
|
do
|
||||||
|
else
|
||||||
|
elsif
|
||||||
|
end
|
||||||
|
ensure
|
||||||
|
false
|
||||||
|
for
|
||||||
|
if
|
||||||
|
in
|
||||||
|
module
|
||||||
|
next
|
||||||
|
nil
|
||||||
|
not
|
||||||
|
or
|
||||||
|
redo
|
||||||
|
rescue
|
||||||
|
retry
|
||||||
|
return
|
||||||
|
self
|
||||||
|
super
|
||||||
|
then
|
||||||
|
true
|
||||||
|
undef
|
||||||
|
unless
|
||||||
|
until
|
||||||
|
when
|
||||||
|
while
|
||||||
|
yield
|
||||||
|
)
|
||||||
|
|
||||||
module GenSupport
|
module GenSupport
|
||||||
def capitalize(target)
|
def capitalize(target)
|
||||||
@ -25,7 +68,7 @@ module GenSupport
|
|||||||
safename = name.scan(/[a-zA-Z0-9_]+/).collect { |ele|
|
safename = name.scan(/[a-zA-Z0-9_]+/).collect { |ele|
|
||||||
GenSupport.capitalize(ele)
|
GenSupport.capitalize(ele)
|
||||||
}.join
|
}.join
|
||||||
unless /^[A-Z]/ =~ safename
|
if /^[A-Z]/ !~ safename or keyword?(safename)
|
||||||
safename = "C_#{safename}"
|
safename = "C_#{safename}"
|
||||||
end
|
end
|
||||||
safename
|
safename
|
||||||
@ -33,12 +76,17 @@ module GenSupport
|
|||||||
module_function :safeconstname
|
module_function :safeconstname
|
||||||
|
|
||||||
def safeconstname?(name)
|
def safeconstname?(name)
|
||||||
/\A[A-Z][a-zA-Z0-9_]*\z/ =~ name
|
/\A[A-Z][a-zA-Z0-9_]*\z/ =~ name and !keyword?(name)
|
||||||
end
|
end
|
||||||
module_function :safeconstname?
|
module_function :safeconstname?
|
||||||
|
|
||||||
def safemethodname(name)
|
def safemethodname(name)
|
||||||
safevarname(name)
|
safename = name.scan(/[a-zA-Z0-9_]+/).join('_')
|
||||||
|
safename = uncapitalize(safename)
|
||||||
|
if /^[a-z]/ !~ safename
|
||||||
|
safename = "m_#{safename}"
|
||||||
|
end
|
||||||
|
safename
|
||||||
end
|
end
|
||||||
module_function :safemethodname
|
module_function :safemethodname
|
||||||
|
|
||||||
@ -50,18 +98,23 @@ module GenSupport
|
|||||||
def safevarname(name)
|
def safevarname(name)
|
||||||
safename = name.scan(/[a-zA-Z0-9_]+/).join('_')
|
safename = name.scan(/[a-zA-Z0-9_]+/).join('_')
|
||||||
safename = uncapitalize(safename)
|
safename = uncapitalize(safename)
|
||||||
unless /^[a-z]/ =~ safename
|
if /^[a-z]/ !~ safename or keyword?(safename)
|
||||||
safename = "m_#{safename}"
|
safename = "v_#{safename}"
|
||||||
end
|
end
|
||||||
safename
|
safename
|
||||||
end
|
end
|
||||||
module_function :safevarname
|
module_function :safevarname
|
||||||
|
|
||||||
def safevarname?(name)
|
def safevarname?(name)
|
||||||
/\A[a-z_][a-zA-Z0-9_]*\z/ =~ name
|
/\A[a-z_][a-zA-Z0-9_]*\z/ =~ name and !keyword?(name)
|
||||||
end
|
end
|
||||||
module_function :safevarname?
|
module_function :safevarname?
|
||||||
|
|
||||||
|
def keyword?(word)
|
||||||
|
KEYWORD.include?(word)
|
||||||
|
end
|
||||||
|
module_function :keyword?
|
||||||
|
|
||||||
def format(str, indent = nil)
|
def format(str, indent = nil)
|
||||||
str = trim_eol(str)
|
str = trim_eol(str)
|
||||||
str = trim_indent(str)
|
str = trim_indent(str)
|
||||||
@ -76,7 +129,7 @@ private
|
|||||||
|
|
||||||
def trim_eol(str)
|
def trim_eol(str)
|
||||||
str.collect { |line|
|
str.collect { |line|
|
||||||
line.sub(/\r?\n$/, "") + "\n"
|
line.sub(/\r?\n\z/, "") + "\n"
|
||||||
}.join
|
}.join
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ class MethodDef
|
|||||||
buf = ""
|
buf = ""
|
||||||
buf << dump_comment if @comment
|
buf << dump_comment if @comment
|
||||||
buf << dump_method_def
|
buf << dump_method_def
|
||||||
buf << dump_definition if @definition
|
buf << dump_definition if @definition and !@definition.empty?
|
||||||
buf << dump_method_def_end
|
buf << dump_method_def_end
|
||||||
buf
|
buf
|
||||||
end
|
end
|
||||||
|
@ -89,7 +89,7 @@ class ModuleDef
|
|||||||
end
|
end
|
||||||
buf << dump_module_def_end
|
buf << dump_module_def_end
|
||||||
buf << dump_package_def_end(package) unless package.empty?
|
buf << dump_package_def_end(package) unless package.empty?
|
||||||
buf
|
buf.gsub(/^\s+$/, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -495,6 +495,18 @@ require 'date'
|
|||||||
module XSDDateTimeImpl
|
module XSDDateTimeImpl
|
||||||
SecInDay = 86400 # 24 * 60 * 60
|
SecInDay = 86400 # 24 * 60 * 60
|
||||||
|
|
||||||
|
def to_obj(klass)
|
||||||
|
if klass == Time
|
||||||
|
to_time
|
||||||
|
elsif klass == Date
|
||||||
|
to_date
|
||||||
|
elsif klass == DateTime
|
||||||
|
to_datetime
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def to_time
|
def to_time
|
||||||
begin
|
begin
|
||||||
if @data.offset * SecInDay == Time.now.utc_offset
|
if @data.offset * SecInDay == Time.now.utc_offset
|
||||||
@ -511,6 +523,14 @@ module XSDDateTimeImpl
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_date
|
||||||
|
Date.new0(@data.class.jd_to_ajd(@data.jd, 0, 0), 0, @data.start)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_datetime
|
||||||
|
data
|
||||||
|
end
|
||||||
|
|
||||||
def tz2of(str)
|
def tz2of(str)
|
||||||
/^(?:Z|(?:([+\-])(\d\d):(\d\d))?)$/ =~ str
|
/^(?:Z|(?:([+\-])(\d\d):(\d\d))?)$/ =~ str
|
||||||
sign = $1
|
sign = $1
|
||||||
@ -539,9 +559,18 @@ module XSDDateTimeImpl
|
|||||||
end
|
end
|
||||||
|
|
||||||
def screen_data(t)
|
def screen_data(t)
|
||||||
if (t.is_a?(Date))
|
# convert t to a DateTime as an internal representation.
|
||||||
|
if t.is_a?(DateTime)
|
||||||
t
|
t
|
||||||
elsif (t.is_a?(Time))
|
elsif t.is_a?(Date)
|
||||||
|
if t.respond_to?(:to_datetime) # from 1.9
|
||||||
|
t.to_datetime
|
||||||
|
else
|
||||||
|
t = screen_data_str(t)
|
||||||
|
t <<= 12 if t.year < 0
|
||||||
|
t
|
||||||
|
end
|
||||||
|
elsif t.is_a?(Time)
|
||||||
sec, min, hour, mday, month, year = t.to_a[0..5]
|
sec, min, hour, mday, month, year = t.to_a[0..5]
|
||||||
diffday = t.usec.to_r / 1000000 / SecInDay
|
diffday = t.usec.to_r / 1000000 / SecInDay
|
||||||
of = t.utc_offset.to_r / SecInDay
|
of = t.utc_offset.to_r / SecInDay
|
||||||
|
@ -22,7 +22,7 @@ class IconvCharset
|
|||||||
out << e.success
|
out << e.success
|
||||||
ch, str = e.failed.split(//, 2)
|
ch, str = e.failed.split(//, 2)
|
||||||
out << '?'
|
out << '?'
|
||||||
STDERR.puts("Failed to convert #{ch}")
|
warn("Failed to convert #{ch}")
|
||||||
retry
|
retry
|
||||||
end
|
end
|
||||||
return out
|
return out
|
||||||
|
42
lib/xsd/mapping.rb
Normal file
42
lib/xsd/mapping.rb
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# XSD4R - XML Mapping for Ruby
|
||||||
|
# Copyright (C) 2005 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/parser"
|
||||||
|
require 'soap/encodingstyle/literalHandler'
|
||||||
|
require "soap/generator"
|
||||||
|
require "soap/mapping"
|
||||||
|
require "soap/mapping/wsdlliteralregistry"
|
||||||
|
|
||||||
|
|
||||||
|
module XSD
|
||||||
|
|
||||||
|
|
||||||
|
module Mapping
|
||||||
|
MappingRegistry = SOAP::Mapping::WSDLLiteralRegistry.new
|
||||||
|
MappingOpt = {:default_encodingstyle => SOAP::LiteralNamespace}
|
||||||
|
|
||||||
|
def self.obj2xml(obj, elename = nil, io = nil)
|
||||||
|
if !elename.nil? and !elename.is_a?(XSD::QName)
|
||||||
|
elename = XSD::QName.new(nil, elename)
|
||||||
|
end
|
||||||
|
elename ||= XSD::QName.new(nil, SOAP::Mapping.name2elename(obj.class.to_s))
|
||||||
|
soap = SOAP::Mapping.obj2soap(obj, MappingRegistry)
|
||||||
|
soap.elename = elename
|
||||||
|
generator = SOAP::SOAPGenerator.new(MappingOpt)
|
||||||
|
generator.generate(soap, io)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.xml2obj(stream)
|
||||||
|
parser = SOAP::Parser.new(MappingOpt)
|
||||||
|
soap = parser.parse(stream)
|
||||||
|
SOAP::Mapping.soap2obj(soap, MappingRegistry)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
@ -1,5 +1,5 @@
|
|||||||
# XSD4R - WSDL named element collection.
|
# XSD4R - WSDL named element collection.
|
||||||
# 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;
|
||||||
@ -23,6 +23,12 @@ class NamedElements
|
|||||||
o
|
o
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def freeze
|
||||||
|
super
|
||||||
|
@elements.freeze
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
def empty?
|
def empty?
|
||||||
size == 0
|
size == 0
|
||||||
end
|
end
|
||||||
@ -43,6 +49,10 @@ class NamedElements
|
|||||||
@elements.find { |item| item.name.name == name }
|
@elements.find { |item| item.name.name == name }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def keys
|
||||||
|
collect { |element| element.name }
|
||||||
|
end
|
||||||
|
|
||||||
def each
|
def each
|
||||||
@elements.each do |element|
|
@elements.each do |element|
|
||||||
yield(element)
|
yield(element)
|
||||||
@ -69,6 +79,8 @@ class NamedElements
|
|||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Empty = NamedElements.new.freeze
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def elements=(rhs)
|
def elements=(rhs)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# XSD4R - XML Schema Namespace library
|
# XSD4R - XML Schema Namespace library
|
||||||
# Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
# Copyright (C) 2000-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;
|
||||||
@ -20,7 +20,7 @@ class NS
|
|||||||
|
|
||||||
def assign(ns)
|
def assign(ns)
|
||||||
@count += 1
|
@count += 1
|
||||||
"n#{ @count }"
|
"n#{@count}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ public
|
|||||||
end
|
end
|
||||||
|
|
||||||
def assigned?(ns)
|
def assigned?(ns)
|
||||||
@ns2tag.key?(ns)
|
@default_namespace == ns or @ns2tag.key?(ns)
|
||||||
end
|
end
|
||||||
|
|
||||||
def assigned_tag?(tag)
|
def assigned_tag?(tag)
|
||||||
@ -74,7 +74,7 @@ public
|
|||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ public
|
|||||||
return true if (name == rhs)
|
return true if (name == rhs)
|
||||||
end
|
end
|
||||||
@tag2ns.each do |assigned_tag, assigned_ns|
|
@tag2ns.each do |assigned_tag, assigned_ns|
|
||||||
if assigned_ns == ns && "#{ assigned_tag }:#{ name }" == rhs
|
if assigned_ns == ns && "#{assigned_tag}:#{name}" == rhs
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -103,22 +103,22 @@ public
|
|||||||
end
|
end
|
||||||
|
|
||||||
# For local attribute key parsing
|
# For local attribute key parsing
|
||||||
# <foo xmlns="urn:" xmlns:n1="urn:" bar="1" n1:baz="2" />
|
# <foo xmlns="urn:a" xmlns:n1="urn:a" bar="1" n1:baz="2" />
|
||||||
# =>
|
# =>
|
||||||
# {}bar, {urn:}baz
|
# {}bar, {urn:a}baz
|
||||||
def parse_local(elem)
|
def parse_local(elem)
|
||||||
ParseRegexp =~ elem
|
ParseRegexp =~ elem
|
||||||
if $2
|
if $2
|
||||||
ns = @tag2ns[$1]
|
ns = @tag2ns[$1]
|
||||||
name = $2
|
name = $2
|
||||||
if !ns
|
if !ns
|
||||||
raise FormatError.new('Unknown namespace qualifier: ' << $1)
|
raise FormatError.new("unknown namespace qualifier: #{$1}")
|
||||||
end
|
end
|
||||||
elsif $1
|
elsif $1
|
||||||
ns = nil
|
ns = nil
|
||||||
name = $1
|
name = $1
|
||||||
else
|
else
|
||||||
raise FormatError.new("Illegal element format: #{ elem }")
|
raise FormatError.new("illegal element format: #{elem}")
|
||||||
end
|
end
|
||||||
XSD::QName.new(ns, name)
|
XSD::QName.new(ns, name)
|
||||||
end
|
end
|
||||||
|
@ -24,6 +24,12 @@ class QName
|
|||||||
XSD::QName.new(@namespace, name)
|
XSD::QName.new(@namespace, name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def dump
|
||||||
|
ns = @namespace.nil? ? 'nil' : @namespace.dump
|
||||||
|
name = @name.nil? ? 'nil' : @name.dump
|
||||||
|
"XSD::QName.new(#{ns}, #{name})"
|
||||||
|
end
|
||||||
|
|
||||||
def match(rhs)
|
def match(rhs)
|
||||||
unless self.class === rhs
|
unless self.class === rhs
|
||||||
return false
|
return false
|
||||||
|
@ -45,8 +45,8 @@ end
|
|||||||
# Try to load XML processor.
|
# Try to load XML processor.
|
||||||
loaded = false
|
loaded = false
|
||||||
[
|
[
|
||||||
'xsd/xmlparser/xmlscanner',
|
|
||||||
'xsd/xmlparser/xmlparser',
|
'xsd/xmlparser/xmlparser',
|
||||||
|
'xsd/xmlparser/xmlscanner',
|
||||||
'xsd/xmlparser/rexmlparser',
|
'xsd/xmlparser/rexmlparser',
|
||||||
].each do |lib|
|
].each do |lib|
|
||||||
begin
|
begin
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# XSD4R - XMLScan XML parser library.
|
# XSD4R - XMLScan XML parser library.
|
||||||
# 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;
|
||||||
@ -21,12 +21,12 @@ class XMLScanner < XSD::XMLParser::Parser
|
|||||||
@attrs = {}
|
@attrs = {}
|
||||||
@curattr = nil
|
@curattr = nil
|
||||||
@scanner = XMLScan::XMLScanner.new(self)
|
@scanner = XMLScan::XMLScanner.new(self)
|
||||||
@scanner.kcode = ::XSD::Charset.charset_str(charset) if charset
|
@scanner.kcode = XSD::Charset.charset_str(charset) if charset
|
||||||
@scanner.parse(string_or_readable)
|
@scanner.parse(string_or_readable)
|
||||||
end
|
end
|
||||||
|
|
||||||
def scanner_kcode=(charset)
|
def scanner_kcode=(charset)
|
||||||
@scanner.kcode = ::XSD::Charset.charset_str(charset) if charset
|
@scanner.kcode = XSD::Charset.charset_str(charset) if charset
|
||||||
self.xmldecl_encoding = charset
|
self.xmldecl_encoding = charset
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
class Authmgr
|
|
||||||
def initialize
|
|
||||||
@users = {
|
|
||||||
'NaHi' => 'passwd',
|
|
||||||
'HiNa' => 'wspass'
|
|
||||||
}
|
|
||||||
@sessions = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
def login(userid, passwd)
|
|
||||||
userid and passwd and @users[userid] == passwd
|
|
||||||
end
|
|
||||||
|
|
||||||
# returns userid
|
|
||||||
def auth(sessionid)
|
|
||||||
@sessions[sessionid]
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_session(userid)
|
|
||||||
while true
|
|
||||||
key = create_sessionkey
|
|
||||||
break unless @sessions[key]
|
|
||||||
end
|
|
||||||
@sessions[key] = userid
|
|
||||||
key
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_session(userid)
|
|
||||||
@sessions.index(userid)
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy_session(sessionkey)
|
|
||||||
@sessions.delete(sessionkey)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def create_sessionkey
|
|
||||||
Time.now.usec.to_s
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,40 +0,0 @@
|
|||||||
require 'soap/rpc/driver'
|
|
||||||
require 'soap/header/simplehandler'
|
|
||||||
|
|
||||||
server = ARGV.shift || 'http://localhost:7000/'
|
|
||||||
|
|
||||||
class ClientAuthHeaderHandler < SOAP::Header::SimpleHandler
|
|
||||||
MyHeaderName = XSD::QName.new("http://tempuri.org/authHeader", "auth")
|
|
||||||
|
|
||||||
def initialize(userid, passwd)
|
|
||||||
super(MyHeaderName)
|
|
||||||
@sessionid = nil
|
|
||||||
@userid = userid
|
|
||||||
@passwd = passwd
|
|
||||||
@mustunderstand = true
|
|
||||||
end
|
|
||||||
|
|
||||||
def on_simple_outbound
|
|
||||||
if @sessionid
|
|
||||||
{ "sessionid" => @sessionid }
|
|
||||||
else
|
|
||||||
{ "userid" => @userid, "passwd" => @passwd }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def on_simple_inbound(my_header, mustunderstand)
|
|
||||||
@sessionid = my_header["sessionid"]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
ns = 'http://tempuri.org/authHeaderPort'
|
|
||||||
serv = SOAP::RPC::Driver.new(server, ns)
|
|
||||||
serv.add_method('deposit', 'amt')
|
|
||||||
serv.add_method('withdrawal', 'amt')
|
|
||||||
|
|
||||||
serv.headerhandler << ClientAuthHeaderHandler.new('NaHi', 'passwd')
|
|
||||||
|
|
||||||
serv.wiredump_dev = STDOUT
|
|
||||||
|
|
||||||
p serv.deposit(150)
|
|
||||||
p serv.withdrawal(120)
|
|
@ -1,42 +0,0 @@
|
|||||||
require 'soap/rpc/driver'
|
|
||||||
require 'soap/header/simplehandler'
|
|
||||||
|
|
||||||
server = ARGV.shift || 'http://localhost:7000/'
|
|
||||||
|
|
||||||
class ClientAuthHeaderHandler < SOAP::Header::SimpleHandler
|
|
||||||
MyHeaderName = XSD::QName.new("http://tempuri.org/authHeader", "auth")
|
|
||||||
|
|
||||||
attr_accessor :sessionid
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
super(MyHeaderName)
|
|
||||||
@sessionid = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def on_simple_outbound
|
|
||||||
if @sessionid
|
|
||||||
{ "sessionid" => @sessionid }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def on_simple_inbound(my_header, mustunderstand)
|
|
||||||
@sessionid = my_header["sessionid"]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
ns = 'http://tempuri.org/authHeaderPort'
|
|
||||||
serv = SOAP::RPC::Driver.new(server, ns)
|
|
||||||
serv.add_method('login', 'userid', 'passwd')
|
|
||||||
serv.add_method('deposit', 'amt')
|
|
||||||
serv.add_method('withdrawal', 'amt')
|
|
||||||
|
|
||||||
h = ClientAuthHeaderHandler.new
|
|
||||||
|
|
||||||
serv.headerhandler << h
|
|
||||||
|
|
||||||
serv.wiredump_dev = STDOUT
|
|
||||||
|
|
||||||
sessionid = serv.login('NaHi', 'passwd')
|
|
||||||
h.sessionid = sessionid
|
|
||||||
p serv.deposit(150)
|
|
||||||
p serv.withdrawal(120)
|
|
@ -1,73 +0,0 @@
|
|||||||
#!/usr/bin/env ruby
|
|
||||||
|
|
||||||
require 'soap/rpc/standaloneServer'
|
|
||||||
require 'soap/header/simplehandler'
|
|
||||||
require 'authmgr'
|
|
||||||
|
|
||||||
class AuthHeaderPortServer < SOAP::RPC::StandaloneServer
|
|
||||||
class AuthHeaderService
|
|
||||||
def self.create
|
|
||||||
new
|
|
||||||
end
|
|
||||||
|
|
||||||
def deposit(amt)
|
|
||||||
"deposit #{amt} OK"
|
|
||||||
end
|
|
||||||
|
|
||||||
def withdrawal(amt)
|
|
||||||
"withdrawal #{amt} OK"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Name = 'http://tempuri.org/authHeaderPort'
|
|
||||||
def initialize(*arg)
|
|
||||||
super
|
|
||||||
add_rpc_servant(AuthHeaderService.new, Name)
|
|
||||||
# header handler must be a per request handler.
|
|
||||||
add_rpc_request_headerhandler(ServerAuthHeaderHandler)
|
|
||||||
end
|
|
||||||
|
|
||||||
class ServerAuthHeaderHandler < SOAP::Header::SimpleHandler
|
|
||||||
MyHeaderName = XSD::QName.new("http://tempuri.org/authHeader", "auth")
|
|
||||||
|
|
||||||
@authmgr = Authmgr.new
|
|
||||||
def self.create
|
|
||||||
new(@authmgr)
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize(authmgr)
|
|
||||||
super(MyHeaderName)
|
|
||||||
@authmgr = authmgr
|
|
||||||
@userid = @sessionid = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def on_simple_outbound
|
|
||||||
{ "sessionid" => @sessionid }
|
|
||||||
end
|
|
||||||
|
|
||||||
def on_simple_inbound(my_header, mu)
|
|
||||||
auth = false
|
|
||||||
userid = my_header["userid"]
|
|
||||||
passwd = my_header["passwd"]
|
|
||||||
if @authmgr.login(userid, passwd)
|
|
||||||
auth = true
|
|
||||||
elsif sessionid = my_header["sessionid"]
|
|
||||||
if userid = @authmgr.auth(sessionid)
|
|
||||||
@authmgr.destroy_session(sessionid)
|
|
||||||
auth = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
raise RuntimeError.new("authentication failed") unless auth
|
|
||||||
@userid = userid
|
|
||||||
@sessionid = @authmgr.create_session(userid)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if $0 == __FILE__
|
|
||||||
svr = AuthHeaderPortServer.new('AuthHeaderPortServer', nil, '0.0.0.0', 7000)
|
|
||||||
trap(:INT) do
|
|
||||||
svr.shutdown
|
|
||||||
end
|
|
||||||
status = svr.start
|
|
||||||
end
|
|
@ -1,83 +0,0 @@
|
|||||||
#!/usr/bin/env ruby
|
|
||||||
|
|
||||||
require 'soap/rpc/standaloneServer'
|
|
||||||
require 'soap/header/simplehandler'
|
|
||||||
require 'authmgr'
|
|
||||||
|
|
||||||
class AuthHeaderPortServer < SOAP::RPC::StandaloneServer
|
|
||||||
class AuthHeaderService
|
|
||||||
def initialize(authmgr)
|
|
||||||
@authmgr = authmgr
|
|
||||||
end
|
|
||||||
|
|
||||||
def login(userid, passwd)
|
|
||||||
if @authmgr.login(userid, passwd)
|
|
||||||
@authmgr.create_session(userid)
|
|
||||||
else
|
|
||||||
raise RuntimeError.new("authentication failed")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def deposit(amt)
|
|
||||||
"deposit #{amt} OK"
|
|
||||||
end
|
|
||||||
|
|
||||||
def withdrawal(amt)
|
|
||||||
"withdrawal #{amt} OK"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Name = 'http://tempuri.org/authHeaderPort'
|
|
||||||
def initialize(*arg)
|
|
||||||
super
|
|
||||||
authmgr = Authmgr.new
|
|
||||||
add_rpc_servant(AuthHeaderService.new(authmgr), Name)
|
|
||||||
ServerAuthHeaderHandler.init(authmgr)
|
|
||||||
# header handler must be a per request handler.
|
|
||||||
add_rpc_request_headerhandler(ServerAuthHeaderHandler)
|
|
||||||
end
|
|
||||||
|
|
||||||
class ServerAuthHeaderHandler < SOAP::Header::SimpleHandler
|
|
||||||
MyHeaderName = XSD::QName.new("http://tempuri.org/authHeader", "auth")
|
|
||||||
|
|
||||||
def self.init(authmgr)
|
|
||||||
@authmgr = authmgr
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.create
|
|
||||||
new(@authmgr)
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize(authmgr)
|
|
||||||
super(MyHeaderName)
|
|
||||||
@authmgr = authmgr
|
|
||||||
@sessionid = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def on_simple_outbound
|
|
||||||
if @sessionid
|
|
||||||
{ "sessionid" => @sessionid }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def on_simple_inbound(my_header, mu)
|
|
||||||
auth = false
|
|
||||||
if sessionid = my_header["sessionid"]
|
|
||||||
if userid = @authmgr.auth(sessionid)
|
|
||||||
@authmgr.destroy_session(sessionid)
|
|
||||||
@sessionid = @authmgr.create_session(userid)
|
|
||||||
auth = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
raise RuntimeError.new("authentication failed") unless auth
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if $0 == __FILE__
|
|
||||||
svr = AuthHeaderPortServer.new('AuthHeaderPortServer', nil, '0.0.0.0', 7000)
|
|
||||||
trap(:INT) do
|
|
||||||
svr.shutdown
|
|
||||||
end
|
|
||||||
status = svr.start
|
|
||||||
end
|
|
@ -1,16 +0,0 @@
|
|||||||
#!/usr/bin/env ruby
|
|
||||||
|
|
||||||
text = ARGV.shift || 'Hello world.'
|
|
||||||
lang = ARGV.shift || 'en_fr'
|
|
||||||
|
|
||||||
require 'soap/rpc/driver'
|
|
||||||
|
|
||||||
server = 'http://services.xmethods.net/perl/soaplite.cgi'
|
|
||||||
InterfaceNS = 'urn:xmethodsBabelFish'
|
|
||||||
wireDumpDev = nil # STDERR
|
|
||||||
|
|
||||||
drv = SOAP::RPC::Driver.new(server, InterfaceNS)
|
|
||||||
drv.wiredump_dev = wireDumpDev
|
|
||||||
drv.add_method_with_soapaction('BabelFish', InterfaceNS + "#BabelFish", 'translationmode', 'sourcedata')
|
|
||||||
|
|
||||||
p drv.BabelFish(lang, text)
|
|
@ -1,17 +0,0 @@
|
|||||||
module CalcService
|
|
||||||
def self.add(lhs, rhs)
|
|
||||||
lhs + rhs
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.sub(lhs, rhs)
|
|
||||||
lhs - rhs
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.multi(lhs, rhs)
|
|
||||||
lhs * rhs
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.div(lhs, rhs)
|
|
||||||
lhs / rhs
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,29 +0,0 @@
|
|||||||
class CalcService2
|
|
||||||
def initialize(value = 0)
|
|
||||||
@value = value
|
|
||||||
end
|
|
||||||
|
|
||||||
def set(value)
|
|
||||||
@value = value
|
|
||||||
end
|
|
||||||
|
|
||||||
def get
|
|
||||||
@value
|
|
||||||
end
|
|
||||||
|
|
||||||
def +(rhs)
|
|
||||||
@value + rhs
|
|
||||||
end
|
|
||||||
|
|
||||||
def -(rhs)
|
|
||||||
@value - rhs
|
|
||||||
end
|
|
||||||
|
|
||||||
def *(rhs)
|
|
||||||
@value * rhs
|
|
||||||
end
|
|
||||||
|
|
||||||
def /(rhs)
|
|
||||||
@value / rhs
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,26 +0,0 @@
|
|||||||
require 'soap/rpc/driver'
|
|
||||||
|
|
||||||
server = ARGV.shift || 'http://localhost:7000/'
|
|
||||||
# server = 'http://localhost:8808/server.cgi'
|
|
||||||
|
|
||||||
calc = SOAP::RPC::Driver.new(server, 'http://tempuri.org/calcService')
|
|
||||||
#calc.wiredump_dev = STDERR
|
|
||||||
calc.add_method('add', 'lhs', 'rhs')
|
|
||||||
calc.add_method('sub', 'lhs', 'rhs')
|
|
||||||
calc.add_method('multi', 'lhs', 'rhs')
|
|
||||||
calc.add_method('div', 'lhs', 'rhs')
|
|
||||||
|
|
||||||
puts 'add: 1 + 2 # => 3'
|
|
||||||
puts calc.add(1, 2)
|
|
||||||
puts 'sub: 1.1 - 2.2 # => -1.1'
|
|
||||||
puts calc.sub(1.1, 2.2)
|
|
||||||
puts 'multi: 1.1 * 2.2 # => 2.42'
|
|
||||||
puts calc.multi(1.1, 2.2)
|
|
||||||
puts 'div: 5 / 2 # => 2'
|
|
||||||
puts calc.div(5, 2)
|
|
||||||
puts 'div: 5.0 / 2 # => 2.5'
|
|
||||||
puts calc.div(5.0, 2)
|
|
||||||
puts 'div: 1.1 / 0 # => Infinity'
|
|
||||||
puts calc.div(1.1, 0)
|
|
||||||
puts 'div: 1 / 0 # => ZeroDivisionError'
|
|
||||||
puts calc.div(1, 0)
|
|
@ -1,29 +0,0 @@
|
|||||||
require 'soap/rpc/driver'
|
|
||||||
|
|
||||||
server = ARGV.shift || 'http://localhost:7000/'
|
|
||||||
# server = 'http://localhost:8808/server2.cgi'
|
|
||||||
|
|
||||||
var = SOAP::RPC::Driver.new( server, 'http://tempuri.org/calcService' )
|
|
||||||
var.add_method( 'set', 'newValue' )
|
|
||||||
var.add_method( 'get' )
|
|
||||||
var.add_method_as( '+', 'add', 'rhs' )
|
|
||||||
var.add_method_as( '-', 'sub', 'rhs' )
|
|
||||||
var.add_method_as( '*', 'multi', 'rhs' )
|
|
||||||
var.add_method_as( '/', 'div', 'rhs' )
|
|
||||||
|
|
||||||
puts 'var.set( 1 )'
|
|
||||||
puts '# Bare in mind that another client set another value to this service.'
|
|
||||||
puts '# This is only a sample for proof of concept.'
|
|
||||||
var.set( 1 )
|
|
||||||
puts 'var + 2 # => 1 + 2 = 3'
|
|
||||||
puts var + 2
|
|
||||||
puts 'var - 2.2 # => 1 - 2.2 = -1.2'
|
|
||||||
puts var - 2.2
|
|
||||||
puts 'var * 2.2 # => 1 * 2.2 = 2.2'
|
|
||||||
puts var * 2.2
|
|
||||||
puts 'var / 2 # => 1 / 2 = 0'
|
|
||||||
puts var / 2
|
|
||||||
puts 'var / 2.0 # => 1 / 2.0 = 0.5'
|
|
||||||
puts var / 2.0
|
|
||||||
puts 'var / 0 # => 1 / 0 => ZeroDivisionError'
|
|
||||||
puts var / 0
|
|
@ -1,20 +0,0 @@
|
|||||||
#!/usr/bin/env ruby
|
|
||||||
|
|
||||||
require 'webrick'
|
|
||||||
require 'soap/property'
|
|
||||||
|
|
||||||
docroot = "."
|
|
||||||
port = 8808
|
|
||||||
if opt = SOAP::Property.loadproperty("samplehttpd.conf")
|
|
||||||
docroot = opt["docroot"]
|
|
||||||
port = Integer(opt["port"])
|
|
||||||
end
|
|
||||||
|
|
||||||
s = WEBrick::HTTPServer.new(
|
|
||||||
:BindAddress => "0.0.0.0",
|
|
||||||
:Port => port,
|
|
||||||
:DocumentRoot => docroot,
|
|
||||||
:CGIPathEnv => ENV['PATH']
|
|
||||||
)
|
|
||||||
trap(:INT){ s.shutdown }
|
|
||||||
s.start
|
|
@ -1,2 +0,0 @@
|
|||||||
docroot = .
|
|
||||||
port = 8808
|
|
@ -1,15 +0,0 @@
|
|||||||
#!/usr/bin/env ruby
|
|
||||||
|
|
||||||
require 'soap/rpc/cgistub'
|
|
||||||
|
|
||||||
class CalcServer < SOAP::RPC::CGIStub
|
|
||||||
def initialize(*arg)
|
|
||||||
super
|
|
||||||
|
|
||||||
require 'calc'
|
|
||||||
servant = CalcService
|
|
||||||
add_servant(servant, 'http://tempuri.org/calcService')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
status = CalcServer.new('CalcServer', nil).start
|
|
@ -1,21 +0,0 @@
|
|||||||
#!/usr/bin/env ruby
|
|
||||||
|
|
||||||
require 'soap/rpc/standaloneServer'
|
|
||||||
require 'calc'
|
|
||||||
|
|
||||||
class CalcServer < SOAP::RPC::StandaloneServer
|
|
||||||
def initialize(*arg)
|
|
||||||
super
|
|
||||||
|
|
||||||
servant = CalcService
|
|
||||||
add_servant(servant, 'http://tempuri.org/calcService')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if $0 == __FILE__
|
|
||||||
server = CalcServer.new('CalcServer', nil, '0.0.0.0', 7000)
|
|
||||||
trap(:INT) do
|
|
||||||
server.shutdown
|
|
||||||
end
|
|
||||||
server.start
|
|
||||||
end
|
|
@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env ruby
|
|
||||||
|
|
||||||
require 'soap/rpc/standaloneServer'
|
|
||||||
require 'calc2'
|
|
||||||
|
|
||||||
class CalcServer2 < SOAP::RPC::StandaloneServer
|
|
||||||
def on_init
|
|
||||||
servant = CalcService2.new
|
|
||||||
add_method(servant, 'set', 'newValue')
|
|
||||||
add_method(servant, 'get')
|
|
||||||
add_method_as(servant, '+', 'add', 'lhs')
|
|
||||||
add_method_as(servant, '-', 'sub', 'lhs')
|
|
||||||
add_method_as(servant, '*', 'multi', 'lhs')
|
|
||||||
add_method_as(servant, '/', 'div', 'lhs')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if $0 == __FILE__
|
|
||||||
server = CalcServer2.new('CalcServer', 'http://tempuri.org/calcService', '0.0.0.0', 7000)
|
|
||||||
trap(:INT) do
|
|
||||||
server.shutdown
|
|
||||||
end
|
|
||||||
status = server.start
|
|
||||||
end
|
|
@ -1,43 +0,0 @@
|
|||||||
require 'soap/marshal'
|
|
||||||
|
|
||||||
class Node; include SOAP::Marshallable
|
|
||||||
attr_reader :first, :second, :str
|
|
||||||
|
|
||||||
def initialize(*init_next)
|
|
||||||
@first = init_next[0]
|
|
||||||
@second = init_next[1]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
n9 = Node.new
|
|
||||||
n81 = Node.new(n9)
|
|
||||||
n82 = Node.new(n9)
|
|
||||||
n7 = Node.new(n81, n82)
|
|
||||||
n61 = Node.new(n7)
|
|
||||||
n62 = Node.new(n7)
|
|
||||||
n5 = Node.new(n61, n62)
|
|
||||||
n41 = Node.new(n5)
|
|
||||||
n42 = Node.new(n5)
|
|
||||||
n3 = Node.new(n41, n42)
|
|
||||||
n21 = Node.new(n3)
|
|
||||||
n22 = Node.new(n3)
|
|
||||||
n1 = Node.new(n21, n22)
|
|
||||||
|
|
||||||
File.open("digraph_marshalled_string.soap", "wb") do |f|
|
|
||||||
SOAP::Marshal.dump(n1, f)
|
|
||||||
end
|
|
||||||
|
|
||||||
marshalledString = File.open("digraph_marshalled_string.soap") { |f| f.read }
|
|
||||||
|
|
||||||
puts marshalledString
|
|
||||||
|
|
||||||
newnode = SOAP::Marshal.unmarshal(marshalledString)
|
|
||||||
|
|
||||||
puts newnode.inspect
|
|
||||||
|
|
||||||
p newnode.first.first.__id__
|
|
||||||
p newnode.second.first.__id__
|
|
||||||
p newnode.first.first.first.first.__id__
|
|
||||||
p newnode.second.first.second.first.__id__
|
|
||||||
|
|
||||||
File.unlink("digraph_marshalled_string.soap")
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user