mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/soap/* (29 files): SOAP4R added.
* lib/wsdl/* (42 files): WSDL4R added. * lib/xsd/* (12 files): XSD4R added. * test/soap/* (16 files): added. * test/wsdl/* (2 files): added. * test/xsd/* (3 files): added. * sample/soap/* (27 files): added. * sample/wsdl/* (13 files): added. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4591 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
8c2fb77787
commit
db9445103c
145 changed files with 20938 additions and 0 deletions
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,21 @@
|
|||
Mon Sep 25 00:13:15 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
|
||||
|
||||
* lib/soap/* (29 files): SOAP4R added.
|
||||
|
||||
* lib/wsdl/* (42 files): WSDL4R added.
|
||||
|
||||
* lib/xsd/* (12 files): XSD4R added.
|
||||
|
||||
* test/soap/* (16 files): added.
|
||||
|
||||
* test/wsdl/* (2 files): added.
|
||||
|
||||
* test/xsd/* (3 files): added.
|
||||
|
||||
* sample/soap/* (27 files): added.
|
||||
|
||||
* sample/wsdl/* (13 files): added.
|
||||
|
||||
Wed Sep 24 02:08:11 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
|
||||
|
||||
* lib/webrick/httpservlet/cgihandler.rb: conform to mswin32.
|
||||
|
|
782
lib/soap/baseData.rb
Normal file
782
lib/soap/baseData.rb
Normal file
|
@ -0,0 +1,782 @@
|
|||
=begin
|
||||
SOAP4R - Base type library
|
||||
Copyright (C) 2000, 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/datatypes'
|
||||
require 'soap/soap'
|
||||
|
||||
|
||||
module SOAP
|
||||
|
||||
|
||||
###
|
||||
## Mix-in module for SOAP base type classes.
|
||||
#
|
||||
module SOAPModuleUtils
|
||||
include SOAP
|
||||
|
||||
public
|
||||
|
||||
def decode(elename)
|
||||
d = self.new
|
||||
d.elename = elename
|
||||
d
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
## Mix-in module for SOAP base type instances.
|
||||
#
|
||||
module SOAPBasetype
|
||||
include SOAP
|
||||
|
||||
attr_accessor :encodingstyle
|
||||
|
||||
attr_accessor :elename
|
||||
attr_accessor :id
|
||||
attr_reader :precedents
|
||||
attr_accessor :root
|
||||
attr_accessor :parent
|
||||
attr_accessor :position
|
||||
attr_reader :extraattr
|
||||
|
||||
public
|
||||
|
||||
def initialize(*vars)
|
||||
super(*vars)
|
||||
@encodingstyle = nil
|
||||
@elename = XSD::QName.new
|
||||
@id = nil
|
||||
@precedents = []
|
||||
@parent = nil
|
||||
@position = nil
|
||||
@extraattr = {}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
## Mix-in module for SOAP compound type instances.
|
||||
#
|
||||
module SOAPCompoundtype
|
||||
include SOAP
|
||||
|
||||
attr_accessor :encodingstyle
|
||||
|
||||
attr_accessor :elename
|
||||
attr_accessor :id
|
||||
attr_reader :precedents
|
||||
attr_accessor :root
|
||||
attr_accessor :parent
|
||||
attr_accessor :position
|
||||
attr_reader :extraattr
|
||||
|
||||
attr_accessor :definedtype
|
||||
|
||||
public
|
||||
|
||||
def initialize(type)
|
||||
super()
|
||||
@type = type
|
||||
@encodingstyle = nil
|
||||
@elename = XSD::QName.new
|
||||
@id = nil
|
||||
@precedents = []
|
||||
@root = false
|
||||
@parent = nil
|
||||
@position = nil
|
||||
@definedtype = nil
|
||||
@extraattr = {}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
## Convenience datatypes.
|
||||
#
|
||||
class SOAPReference < XSD::NSDBase
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
|
||||
public
|
||||
|
||||
attr_accessor :refid
|
||||
attr_accessor :elename
|
||||
|
||||
# Override the definition in SOAPBasetype.
|
||||
def initialize(refid = nil)
|
||||
super()
|
||||
@type = XSD::QName.new
|
||||
@encodingstyle = nil
|
||||
@elename = XSD::QName.new
|
||||
@id = nil
|
||||
@precedents = []
|
||||
@root = false
|
||||
@parent = nil
|
||||
@refid = refid
|
||||
@obj = nil
|
||||
end
|
||||
|
||||
def __getobj__
|
||||
@obj
|
||||
end
|
||||
|
||||
def __setobj__(obj)
|
||||
@obj = obj
|
||||
@refid = SOAPReference.create_refid(@obj)
|
||||
@obj.id = @refid unless @obj.id
|
||||
@obj.precedents << self
|
||||
# Copies NSDBase information
|
||||
@obj.type = @type unless @obj.type
|
||||
end
|
||||
|
||||
# Why don't I use delegate.rb?
|
||||
# -> delegate requires target object type at initialize time.
|
||||
# Why don't I use forwardable.rb?
|
||||
# -> forwardable requires a list of forwarding methods.
|
||||
#
|
||||
# ToDo: Maybe I should use forwardable.rb and give it a methods list like
|
||||
# delegate.rb...
|
||||
#
|
||||
def method_missing(msg_id, *params)
|
||||
if @obj
|
||||
@obj.send(msg_id, *params)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def self.decode(elename, refid)
|
||||
d = super(elename)
|
||||
d.refid = refid
|
||||
d
|
||||
end
|
||||
|
||||
def SOAPReference.create_refid(obj)
|
||||
'id' << obj.__id__.to_s
|
||||
end
|
||||
end
|
||||
|
||||
class SOAPNil < XSD::XSDNil
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
# SOAPRawString is for sending raw string. In contrast to SOAPString,
|
||||
# SOAP4R does not do XML encoding and does not convert its CES. The string it
|
||||
# holds is embedded to XML instance directly as a 'xsd:string'.
|
||||
class SOAPRawString < XSD::XSDString
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
## Basic datatypes.
|
||||
#
|
||||
class SOAPAnySimpleType < XSD::XSDAnySimpleType
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPString < XSD::XSDString
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPBoolean < XSD::XSDBoolean
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPDecimal < XSD::XSDDecimal
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPFloat < XSD::XSDFloat
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPDouble < XSD::XSDDouble
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPDuration < XSD::XSDDuration
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPDateTime < XSD::XSDDateTime
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPTime < XSD::XSDTime
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPDate < XSD::XSDDate
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPGYearMonth < XSD::XSDGYearMonth
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPGYear < XSD::XSDGYear
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPGMonthDay < XSD::XSDGMonthDay
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPGDay < XSD::XSDGDay
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPGMonth < XSD::XSDGMonth
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPHexBinary < XSD::XSDHexBinary
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPBase64 < XSD::XSDBase64Binary
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
Type = QName.new(EncodingNamespace, Base64Literal)
|
||||
|
||||
public
|
||||
# Override the definition in SOAPBasetype.
|
||||
def initialize(value = nil)
|
||||
super(value)
|
||||
@type = Type
|
||||
end
|
||||
|
||||
def as_xsd
|
||||
@type = XSD::XSDBase64Binary::Type
|
||||
end
|
||||
end
|
||||
|
||||
class SOAPAnyURI < XSD::XSDAnyURI
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPQName < XSD::XSDQName
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
|
||||
class SOAPInteger < XSD::XSDInteger
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPLong < XSD::XSDLong
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPInt < XSD::XSDInt
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
class SOAPShort < XSD::XSDShort
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
## Compound datatypes.
|
||||
#
|
||||
class SOAPStruct < XSD::NSDBase
|
||||
include SOAPCompoundtype
|
||||
include Enumerable
|
||||
|
||||
public
|
||||
|
||||
def initialize(type = nil)
|
||||
super(type || XSD::QName.new)
|
||||
@array = []
|
||||
@data = []
|
||||
end
|
||||
|
||||
def to_s()
|
||||
str = ''
|
||||
self.each do |key, data|
|
||||
str << "#{ key }: #{ data }\n"
|
||||
end
|
||||
str
|
||||
end
|
||||
|
||||
def add(name, value)
|
||||
add_member(name, value)
|
||||
end
|
||||
|
||||
def [](idx)
|
||||
if idx.is_a?(Range)
|
||||
@data[idx]
|
||||
elsif idx.is_a?(Integer)
|
||||
if (idx > @array.size)
|
||||
raise ArrayIndexOutOfBoundsError.new('In ' << @type.name)
|
||||
end
|
||||
@data[idx]
|
||||
else
|
||||
if @array.include?(idx)
|
||||
@data[@array.index(idx)]
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def []=(idx, data)
|
||||
if @array.include?(idx)
|
||||
@data[@array.index(idx)] = data
|
||||
else
|
||||
add(idx, data)
|
||||
end
|
||||
end
|
||||
|
||||
def key?(name)
|
||||
@array.include?(name)
|
||||
end
|
||||
|
||||
def members
|
||||
@array
|
||||
end
|
||||
|
||||
def each
|
||||
for i in 0..(@array.length - 1)
|
||||
yield(@array[i], @data[i])
|
||||
end
|
||||
end
|
||||
|
||||
def replace
|
||||
members.each do |member|
|
||||
self[member] = yield(self[member])
|
||||
end
|
||||
end
|
||||
|
||||
def self.decode(elename, type)
|
||||
s = SOAPStruct.new(type)
|
||||
s.elename = elename
|
||||
s
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_member(name, value = nil)
|
||||
value = SOAPNil.new() unless value
|
||||
@array.push(name)
|
||||
value.elename = value.elename.dup_name(name)
|
||||
@data.push(value)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# SOAPElement is not typed so it does not derive NSDBase.
|
||||
class SOAPElement
|
||||
include Enumerable
|
||||
|
||||
attr_accessor :encodingstyle
|
||||
attr_accessor :extraattr
|
||||
attr_reader :precedents
|
||||
|
||||
attr_accessor :qualified
|
||||
attr_accessor :elename
|
||||
|
||||
def initialize(elename, text = nil)
|
||||
if !elename.is_a?(XSD::QName)
|
||||
elename = XSD::QName.new(nil, elename)
|
||||
end
|
||||
@encodingstyle = LiteralNamespace
|
||||
@extraattr = {}
|
||||
@precedents = []
|
||||
|
||||
@qualified = false
|
||||
@elename = elename
|
||||
|
||||
@array = []
|
||||
@data = []
|
||||
@text = text
|
||||
end
|
||||
|
||||
# Text interface.
|
||||
attr_accessor :text
|
||||
|
||||
# Element interfaces.
|
||||
def add(value)
|
||||
add_member(value.elename.name, value)
|
||||
end
|
||||
|
||||
def [](idx)
|
||||
if @array.include?(idx)
|
||||
@data[@array.index(idx)]
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def []=(idx, data)
|
||||
if @array.include?(idx)
|
||||
@data[@array.index(idx)] = data
|
||||
else
|
||||
add(data)
|
||||
end
|
||||
end
|
||||
|
||||
def key?(name)
|
||||
@array.include?(name)
|
||||
end
|
||||
|
||||
def members
|
||||
@array
|
||||
end
|
||||
|
||||
def to_obj
|
||||
if members.empty?
|
||||
@text
|
||||
else
|
||||
hash = {}
|
||||
each do |k, v|
|
||||
hash[k] = v.to_obj
|
||||
end
|
||||
hash
|
||||
end
|
||||
end
|
||||
|
||||
def each
|
||||
for i in 0..(@array.length - 1)
|
||||
yield(@array[i], @data[i])
|
||||
end
|
||||
end
|
||||
|
||||
def self.decode(elename)
|
||||
o = SOAPElement.new
|
||||
o.elename = elename
|
||||
o
|
||||
end
|
||||
|
||||
def self.from_obj(hash_or_string)
|
||||
o = SOAPElement.new(nil)
|
||||
if hash_or_string.is_a?(Hash)
|
||||
hash_or_string.each do |k, v|
|
||||
child = self.from_obj(v)
|
||||
child.elename = XSD::QName.new(nil, k)
|
||||
o.add(child)
|
||||
end
|
||||
else
|
||||
o.text = hash_or_string
|
||||
end
|
||||
o
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_member(name, value)
|
||||
add_accessor(name)
|
||||
@array.push(name)
|
||||
@data.push(value)
|
||||
end
|
||||
|
||||
def add_accessor(name)
|
||||
methodname = name
|
||||
if self.respond_to?(methodname)
|
||||
methodname = safe_accessor_name(methodname)
|
||||
end
|
||||
begin
|
||||
instance_eval <<-EOS
|
||||
def #{ methodname }()
|
||||
@data[@array.index('#{ name }')]
|
||||
end
|
||||
|
||||
def #{ methodname }=(value)
|
||||
@data[@array.index('#{ name }')] = value
|
||||
end
|
||||
EOS
|
||||
rescue SyntaxError
|
||||
methodname = safe_accessor_name(methodname)
|
||||
retry
|
||||
end
|
||||
end
|
||||
|
||||
def safe_accessor_name(name)
|
||||
"var_" << name.gsub(/[^a-zA-Z0-9_]/, '')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class SOAPArray < XSD::NSDBase
|
||||
include SOAPCompoundtype
|
||||
include Enumerable
|
||||
|
||||
public
|
||||
|
||||
attr_accessor :sparse
|
||||
|
||||
attr_reader :offset, :rank
|
||||
attr_accessor :size, :size_fixed
|
||||
attr_reader :arytype
|
||||
|
||||
def initialize(type = nil, rank = 1, arytype = nil)
|
||||
super(type || XSD::QName.new)
|
||||
@rank = rank
|
||||
@data = Array.new
|
||||
@sparse = false
|
||||
@offset = Array.new(rank, 0)
|
||||
@size = Array.new(rank, 0)
|
||||
@size_fixed = false
|
||||
@position = nil
|
||||
@arytype = arytype
|
||||
end
|
||||
|
||||
def offset=(var)
|
||||
@offset = var
|
||||
@sparse = true
|
||||
end
|
||||
|
||||
def add(value)
|
||||
self[*(@offset)] = value
|
||||
end
|
||||
|
||||
def [](*idxary)
|
||||
if idxary.size != @rank
|
||||
raise ArgumentError.new("Given #{ idxary.size } params does not match rank: #{ @rank }")
|
||||
end
|
||||
|
||||
retrieve(idxary)
|
||||
end
|
||||
|
||||
def []=(*idxary)
|
||||
value = idxary.slice!(-1)
|
||||
|
||||
if idxary.size != @rank
|
||||
raise ArgumentError.new("Given #{ idxary.size } params(#{ idxary }) does not match rank: #{ @rank }")
|
||||
end
|
||||
|
||||
for i in 0..(idxary.size - 1)
|
||||
if idxary[i] + 1 > @size[i]
|
||||
@size[i] = idxary[i] + 1
|
||||
end
|
||||
end
|
||||
|
||||
data = retrieve(idxary[0, idxary.size - 1])
|
||||
data[idxary.last] = value
|
||||
|
||||
if value.is_a?(SOAPBasetype) || value.is_a?(SOAPCompoundtype)
|
||||
value.elename = value.elename.dup_name('item')
|
||||
|
||||
# Sync type
|
||||
unless @type.name
|
||||
@type = XSD::QName.new(value.type.namespace,
|
||||
SOAPArray.create_arytype(value.type.name, @rank))
|
||||
end
|
||||
|
||||
unless value.type
|
||||
value.type = @type
|
||||
end
|
||||
end
|
||||
|
||||
@offset = idxary
|
||||
offsetnext
|
||||
end
|
||||
|
||||
def each
|
||||
@data.each do |data|
|
||||
yield(data)
|
||||
end
|
||||
end
|
||||
|
||||
def to_a
|
||||
@data.dup
|
||||
end
|
||||
|
||||
def replace
|
||||
@data = deep_map(@data) do |ele|
|
||||
yield(ele)
|
||||
end
|
||||
end
|
||||
|
||||
def deep_map(ary, &block)
|
||||
ary.collect do |ele|
|
||||
if ele.is_a?(Array)
|
||||
deep_map(ele, &block)
|
||||
else
|
||||
new_obj = block.call(ele)
|
||||
new_obj.elename = new_obj.elename.dup_name('item')
|
||||
new_obj
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def include?(var)
|
||||
traverse_data(@data) do |v, *rank|
|
||||
if v.is_a?(SOAPBasetype) && v.data == var
|
||||
return true
|
||||
end
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def traverse
|
||||
traverse_data(@data) do |v, *rank|
|
||||
unless @sparse
|
||||
yield(v)
|
||||
else
|
||||
yield(v, *rank) if v && !v.is_a?(SOAPNil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def soap2array(ary)
|
||||
traverse_data(@data) do |v, *position|
|
||||
iteary = ary
|
||||
for rank in 1..(position.size - 1)
|
||||
idx = position[rank - 1]
|
||||
if iteary[idx].nil?
|
||||
iteary = iteary[idx] = Array.new
|
||||
else
|
||||
iteary = iteary[idx]
|
||||
end
|
||||
end
|
||||
if block_given?
|
||||
iteary[position.last] = yield(v)
|
||||
else
|
||||
iteary[position.last] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def position
|
||||
@position
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def retrieve(idxary)
|
||||
data = @data
|
||||
for rank in 1..(idxary.size)
|
||||
idx = idxary[rank - 1]
|
||||
if data[idx].nil?
|
||||
data = data[idx] = Array.new
|
||||
else
|
||||
data = data[idx]
|
||||
end
|
||||
end
|
||||
data
|
||||
end
|
||||
|
||||
def traverse_data(data, rank = 1)
|
||||
for idx in 0..(ranksize(rank) - 1)
|
||||
if rank < @rank
|
||||
traverse_data(data[idx], rank + 1) do |*v|
|
||||
v[1, 0] = idx
|
||||
yield(*v)
|
||||
end
|
||||
else
|
||||
yield(data[idx], idx)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def ranksize(rank)
|
||||
@size[rank - 1]
|
||||
end
|
||||
|
||||
def offsetnext
|
||||
move = false
|
||||
idx = @offset.size - 1
|
||||
while !move && idx >= 0
|
||||
@offset[idx] += 1
|
||||
if @size_fixed
|
||||
if @offset[idx] < @size[idx]
|
||||
move = true
|
||||
else
|
||||
@offset[idx] = 0
|
||||
idx -= 1
|
||||
end
|
||||
else
|
||||
move = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Module function
|
||||
|
||||
public
|
||||
|
||||
def self.decode(elename, type, arytype)
|
||||
typestr, nofary = parse_type(arytype.name)
|
||||
rank = nofary.count(',') + 1
|
||||
plain_arytype = XSD::QName.new(arytype.namespace, typestr)
|
||||
o = SOAPArray.new(type, rank, plain_arytype)
|
||||
size = []
|
||||
nofary.split(',').each do |s|
|
||||
if s.empty?
|
||||
size.clear
|
||||
break
|
||||
else
|
||||
size << s.to_i
|
||||
end
|
||||
end
|
||||
unless size.empty?
|
||||
o.size = size
|
||||
o.size_fixed = true
|
||||
end
|
||||
o.elename = elename
|
||||
o
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.create_arytype(typename, rank)
|
||||
"#{ typename }[" << ',' * (rank - 1) << ']'
|
||||
end
|
||||
|
||||
TypeParseRegexp = Regexp.new('^(.+)\[([\d,]*)\]$')
|
||||
|
||||
def self.parse_type(string)
|
||||
TypeParseRegexp =~ string
|
||||
return $1, $2
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
require 'soap/mapping/typeMap'
|
||||
|
||||
|
||||
end
|
232
lib/soap/element.rb
Normal file
232
lib/soap/element.rb
Normal file
|
@ -0,0 +1,232 @@
|
|||
=begin
|
||||
SOAP4R - SOAP elements library
|
||||
Copyright (C) 2000, 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/qname'
|
||||
require 'soap/baseData'
|
||||
|
||||
|
||||
module SOAP
|
||||
|
||||
|
||||
###
|
||||
## SOAP elements
|
||||
#
|
||||
module SOAPEnvelopeElement; end
|
||||
|
||||
class SOAPFault < SOAPStruct
|
||||
include SOAPEnvelopeElement
|
||||
include SOAPCompoundtype
|
||||
|
||||
public
|
||||
|
||||
def faultcode
|
||||
self['faultcode']
|
||||
end
|
||||
|
||||
def faultstring
|
||||
self['faultstring']
|
||||
end
|
||||
|
||||
def faultactor
|
||||
self['faultactor']
|
||||
end
|
||||
|
||||
def detail
|
||||
self['detail']
|
||||
end
|
||||
|
||||
def faultcode=(rhs)
|
||||
self['faultcode'] = rhs
|
||||
end
|
||||
|
||||
def faultstring=(rhs)
|
||||
self['faultstring'] = rhs
|
||||
end
|
||||
|
||||
def faultactor=(rhs)
|
||||
self['faultactor'] = rhs
|
||||
end
|
||||
|
||||
def detail=(rhs)
|
||||
self['detail'] = rhs
|
||||
end
|
||||
|
||||
def initialize(faultcode = nil, faultstring = nil, faultactor = nil, detail = nil)
|
||||
super(EleFaultName)
|
||||
@elename = EleFaultName
|
||||
@encodingstyle = EncodingNamespace
|
||||
|
||||
if faultcode
|
||||
self.faultcode = faultcode
|
||||
self.faultstring = faultstring
|
||||
self.faultactor = faultactor
|
||||
self.detail = detail
|
||||
self.faultcode.elename = EleFaultCodeName if self.faultcode
|
||||
self.faultstring.elename = EleFaultStringName if self.faultstring
|
||||
self.faultactor.elename = EleFaultActorName if self.faultactor
|
||||
self.detail.elename = EleFaultDetailName if self.detail
|
||||
end
|
||||
end
|
||||
|
||||
def encode(buf, ns, attrs = {}, indent = '')
|
||||
SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace)
|
||||
SOAPGenerator.assign_ns(attrs, ns, EncodingNamespace)
|
||||
attrs[ns.name(AttrEncodingStyleName)] = EncodingNamespace
|
||||
name = ns.name(@elename)
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
yield(self.faultcode, false)
|
||||
yield(self.faultstring, false)
|
||||
yield(self.faultactor, false)
|
||||
yield(self.detail, false) if self.detail
|
||||
SOAPGenerator.encode_tag_end(buf, name, indent, true)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class SOAPBody < SOAPStruct
|
||||
include SOAPEnvelopeElement
|
||||
|
||||
public
|
||||
|
||||
def initialize(data = nil, is_fault = false)
|
||||
super(nil)
|
||||
@elename = EleBodyName
|
||||
@encodingstyle = nil
|
||||
add(data.elename.name, data) if data
|
||||
@is_fault = is_fault
|
||||
end
|
||||
|
||||
def encode(buf, ns, attrs = {}, indent = '')
|
||||
name = ns.name(@elename)
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
if @is_fault
|
||||
yield(@data, true)
|
||||
else
|
||||
@data.each do |data|
|
||||
yield(data, true)
|
||||
end
|
||||
end
|
||||
SOAPGenerator.encode_tag_end(buf, name, indent, true)
|
||||
end
|
||||
|
||||
def root_node
|
||||
@data.each do |node|
|
||||
if node.root == 1
|
||||
return node
|
||||
end
|
||||
end
|
||||
# No specified root...
|
||||
@data.each do |node|
|
||||
if node.root != 0
|
||||
return node
|
||||
end
|
||||
end
|
||||
|
||||
raise SOAPParser::FormatDecodeError.new('No root element.')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class SOAPHeaderItem < XSD::NSDBase
|
||||
include SOAPEnvelopeElement
|
||||
include SOAPCompoundtype
|
||||
|
||||
public
|
||||
|
||||
attr_accessor :content
|
||||
attr_accessor :mustunderstand
|
||||
attr_accessor :encodingstyle
|
||||
|
||||
def initialize(content, mustunderstand = true, encodingstyle = nil)
|
||||
super(nil)
|
||||
@content = content
|
||||
@mustunderstand = mustunderstand
|
||||
@encodingstyle = encodingstyle || LiteralNamespace
|
||||
end
|
||||
|
||||
def encode(buf, ns, attrs = {}, indent = '')
|
||||
attrs.each do |key, value|
|
||||
@content.attr[key] = value
|
||||
end
|
||||
@content.attr[ns.name(EnvelopeNamespace, AttrMustUnderstand)] =
|
||||
(@mustunderstand ? '1' : '0')
|
||||
if @encodingstyle
|
||||
@content.attr[ns.name(EnvelopeNamespace, AttrEncodingStyle)] =
|
||||
@encodingstyle
|
||||
end
|
||||
@content.encodingstyle = @encodingstyle if !@content.encodingstyle
|
||||
yield(@content, true)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class SOAPHeader < SOAPArray
|
||||
include SOAPEnvelopeElement
|
||||
|
||||
def initialize()
|
||||
super(nil, 1) # rank == 1
|
||||
@elename = EleHeaderName
|
||||
@encodingstyle = nil
|
||||
end
|
||||
|
||||
def encode(buf, ns, attrs = {}, indent = '')
|
||||
name = ns.name(@elename)
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
@data.each do |data|
|
||||
yield(data, true)
|
||||
end
|
||||
SOAPGenerator.encode_tag_end(buf, name, indent, true)
|
||||
end
|
||||
|
||||
def length
|
||||
@data.length
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class SOAPEnvelope < XSD::NSDBase
|
||||
include SOAPEnvelopeElement
|
||||
include SOAPCompoundtype
|
||||
|
||||
attr_accessor :header
|
||||
attr_accessor :body
|
||||
|
||||
def initialize(header = nil, body = nil)
|
||||
super(nil)
|
||||
@elename = EleEnvelopeName
|
||||
@encodingstyle = nil
|
||||
@header = header
|
||||
@body = body
|
||||
end
|
||||
|
||||
def encode(buf, ns, attrs = {}, indent = '')
|
||||
SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace,
|
||||
SOAPNamespaceTag)
|
||||
name = ns.name(@elename)
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
|
||||
yield(@header, true) if @header and @header.length > 0
|
||||
yield(@body, true)
|
||||
|
||||
SOAPGenerator.encode_tag_end(buf, name, indent, true)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
232
lib/soap/encodingstyle/aspDotNetHandler.rb
Normal file
232
lib/soap/encodingstyle/aspDotNetHandler.rb
Normal file
|
@ -0,0 +1,232 @@
|
|||
=begin
|
||||
SOAP4R - ASP.NET EncodingStyle handler library
|
||||
Copyright (C) 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'soap/encodingstyle/handler'
|
||||
|
||||
|
||||
module SOAP
|
||||
module EncodingStyle
|
||||
|
||||
|
||||
class ASPDotNetHandler < Handler
|
||||
Namespace = 'http://tempuri.org/ASP.NET'
|
||||
add_handler
|
||||
|
||||
def initialize(charset = nil)
|
||||
super(charset)
|
||||
@textbuf = ''
|
||||
@decode_typemap = nil
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
## encode interface.
|
||||
#
|
||||
def encode_data(buf, ns, qualified, data, parent, indent = '')
|
||||
attrs = {}
|
||||
name = if qualified and data.elename.namespace
|
||||
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace)
|
||||
ns.name(data.elename)
|
||||
else
|
||||
data.elename.name
|
||||
end
|
||||
|
||||
case data
|
||||
when SOAPRawString
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
buf << data.to_s
|
||||
when XSD::XSDString
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
buf << SOAPGenerator.encode_str(@charset ?
|
||||
XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
|
||||
when XSD::XSDAnySimpleType
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
buf << SOAPGenerator.encode_str(data.to_s)
|
||||
when SOAPStruct
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
data.each do |key, value|
|
||||
if !value.elename.namespace
|
||||
value.elename.namespace = data.elename.namespace
|
||||
end
|
||||
yield(value, true)
|
||||
end
|
||||
when SOAPArray
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
data.traverse do |child, *rank|
|
||||
data.position = nil
|
||||
yield(child, true)
|
||||
end
|
||||
else
|
||||
raise EncodingStyleError.new("Unknown object:#{ data } in this encodingSt
|
||||
yle.")
|
||||
end
|
||||
end
|
||||
|
||||
def encode_data_end(buf, ns, qualified, data, parent, indent = "")
|
||||
name = if qualified and data.elename.namespace
|
||||
ns.name(data.elename)
|
||||
else
|
||||
data.elename.name
|
||||
end
|
||||
cr = data.is_a?(SOAPCompoundtype)
|
||||
SOAPGenerator.encode_tag_end(buf, name, indent, cr)
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
## decode interface.
|
||||
#
|
||||
class SOAPTemporalObject
|
||||
attr_accessor :parent
|
||||
|
||||
def initialize
|
||||
@parent = nil
|
||||
end
|
||||
end
|
||||
|
||||
class SOAPUnknown < SOAPTemporalObject
|
||||
def initialize(handler, elename)
|
||||
super()
|
||||
@handler = handler
|
||||
@elename = elename
|
||||
end
|
||||
|
||||
def as_struct
|
||||
o = SOAPStruct.decode(@elename, XSD::AnyTypeName)
|
||||
o.parent = @parent
|
||||
o.type.name = @name
|
||||
@handler.decode_parent(@parent, o)
|
||||
o
|
||||
end
|
||||
|
||||
def as_string
|
||||
o = SOAPString.decode(@elename)
|
||||
o.parent = @parent
|
||||
@handler.decode_parent(@parent, o)
|
||||
o
|
||||
end
|
||||
|
||||
def as_nil
|
||||
o = SOAPNil.decode(@elename)
|
||||
o.parent = @parent
|
||||
@handler.decode_parent(@parent, o)
|
||||
o
|
||||
end
|
||||
end
|
||||
|
||||
def decode_tag(ns, elename, attrs, parent)
|
||||
# ToDo: check if @textbuf is empty...
|
||||
@textbuf = ''
|
||||
o = SOAPUnknown.new(self, elename)
|
||||
o.parent = parent
|
||||
o
|
||||
end
|
||||
|
||||
def decode_tag_end(ns, node)
|
||||
o = node.node
|
||||
if o.is_a?(SOAPUnknown)
|
||||
newnode = o.as_string
|
||||
# if /\A\s*\z/ =~ @textbuf
|
||||
# o.as_struct
|
||||
# else
|
||||
# o.as_string
|
||||
# end
|
||||
node.replace_node(newnode)
|
||||
o = node.node
|
||||
end
|
||||
|
||||
decode_textbuf(o)
|
||||
@textbuf = ''
|
||||
end
|
||||
|
||||
def decode_text(ns, text)
|
||||
# @textbuf is set at decode_tag_end.
|
||||
@textbuf << text
|
||||
end
|
||||
|
||||
def decode_prologue
|
||||
end
|
||||
|
||||
def decode_epilogue
|
||||
end
|
||||
|
||||
def decode_parent(parent, node)
|
||||
case parent.node
|
||||
when SOAPUnknown
|
||||
newparent = parent.node.as_struct
|
||||
node.parent = newparent
|
||||
parent.replace_node(newparent)
|
||||
decode_parent(parent, node)
|
||||
|
||||
when SOAPStruct
|
||||
data = parent.node[node.elename.name]
|
||||
case data
|
||||
when nil
|
||||
parent.node.add(node.elename.name, node)
|
||||
when SOAPArray
|
||||
name, type_ns = node.elename.name, node.type.namespace
|
||||
data.add(node)
|
||||
node.elename, node.type.namespace = name, type_ns
|
||||
else
|
||||
parent.node[node.elename.name] = SOAPArray.new
|
||||
name, type_ns = data.elename.name, data.type.namespace
|
||||
parent.node[node.elename.name].add(data)
|
||||
data.elename.name, data.type.namespace = name, type_ns
|
||||
name, type_ns = node.elename.name, node.type.namespace
|
||||
parent.node[node.elename.name].add(node)
|
||||
node.elename.name, node.type.namespace = name, type_ns
|
||||
end
|
||||
|
||||
when SOAPArray
|
||||
if node.position
|
||||
parent.node[*(decode_arypos(node.position))] = node
|
||||
parent.node.sparse = true
|
||||
else
|
||||
parent.node.add(node)
|
||||
end
|
||||
|
||||
when SOAPBasetype
|
||||
raise EncodingStyleError.new("SOAP base type must not have a child.")
|
||||
|
||||
else
|
||||
# SOAPUnknown does not have parent.
|
||||
# raise EncodingStyleError.new("Illegal parent: #{ parent }.")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def decode_textbuf(node)
|
||||
if node.is_a?(XSD::XSDString)
|
||||
if @charset
|
||||
node.set(XSD::Charset.encoding_from_xml(@textbuf, @charset))
|
||||
else
|
||||
node.set(@textbuf)
|
||||
end
|
||||
else
|
||||
# Nothing to do...
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ASPDotNetHandler.new
|
||||
|
||||
|
||||
end
|
||||
end
|
111
lib/soap/encodingstyle/handler.rb
Normal file
111
lib/soap/encodingstyle/handler.rb
Normal file
|
@ -0,0 +1,111 @@
|
|||
=begin
|
||||
SOAP4R - EncodingStyle handler library
|
||||
Copyright (C) 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'soap/soap'
|
||||
require 'soap/baseData'
|
||||
require 'soap/element'
|
||||
|
||||
|
||||
module SOAP
|
||||
module EncodingStyle
|
||||
|
||||
|
||||
class Handler
|
||||
@@handlers = {}
|
||||
|
||||
class EncodingStyleError < Error; end
|
||||
|
||||
class << self
|
||||
def uri
|
||||
self::Namespace
|
||||
end
|
||||
|
||||
def handler(uri)
|
||||
@@handlers[uri]
|
||||
end
|
||||
|
||||
def each
|
||||
@@handlers.each do |key, value|
|
||||
yield(value)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_handler
|
||||
@@handlers[self.uri] = self
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :charset
|
||||
attr_accessor :generate_explicit_type
|
||||
def decode_typemap=(complextypes)
|
||||
@decode_typemap = complextypes
|
||||
end
|
||||
|
||||
def initialize(charset)
|
||||
@charset = charset
|
||||
@generate_explicit_type = true
|
||||
@decode_typemap = nil
|
||||
end
|
||||
|
||||
###
|
||||
## encode interface.
|
||||
#
|
||||
# Returns a XML instance as a string.
|
||||
def encode_data(buf, ns, qualified, data, parent, indent)
|
||||
raise NotImplementError.new('Method encode_data must be defined in derived class.')
|
||||
end
|
||||
|
||||
def encode_data_end(buf, ns, qualified, data, parent, indent)
|
||||
raise NotImplementError.new('Method encode_data must be defined in derived class.')
|
||||
end
|
||||
|
||||
def encode_prologue
|
||||
end
|
||||
|
||||
def encode_epilogue
|
||||
end
|
||||
|
||||
###
|
||||
## decode interface.
|
||||
#
|
||||
# Returns SOAP/OM data.
|
||||
def decode_tag(ns, name, attrs, parent)
|
||||
raise NotImplementError.new('Method decode_tag must be defined in derived class.')
|
||||
end
|
||||
|
||||
def decode_tag_end(ns, name)
|
||||
raise NotImplementError.new('Method decode_tag_end must be defined in derived class.')
|
||||
end
|
||||
|
||||
def decode_text(ns, text)
|
||||
raise NotImplementError.new('Method decode_text must be defined in derived class.')
|
||||
end
|
||||
|
||||
def decode_prologue
|
||||
end
|
||||
|
||||
def decode_epilogue
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
218
lib/soap/encodingstyle/literalHandler.rb
Normal file
218
lib/soap/encodingstyle/literalHandler.rb
Normal file
|
@ -0,0 +1,218 @@
|
|||
=begin
|
||||
SOAP4R - XML Literal EncodingStyle handler library
|
||||
Copyright (C) 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'soap/encodingstyle/handler'
|
||||
|
||||
|
||||
module SOAP
|
||||
module EncodingStyle
|
||||
|
||||
|
||||
class LiteralHandler < Handler
|
||||
Namespace = SOAP::LiteralNamespace
|
||||
add_handler
|
||||
|
||||
def initialize(charset = nil)
|
||||
super(charset)
|
||||
@textbuf = ''
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
## encode interface.
|
||||
#
|
||||
def encode_data(buf, ns, qualified, data, parent, indent = '')
|
||||
attrs = {}
|
||||
name = if qualified and data.elename.namespace
|
||||
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace)
|
||||
ns.name(data.elename)
|
||||
else
|
||||
data.elename.name
|
||||
end
|
||||
|
||||
case data
|
||||
when SOAPRawString
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
buf << data.to_s
|
||||
when XSD::XSDString
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
buf << SOAPGenerator.encode_str(@charset ?
|
||||
XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
|
||||
when XSD::XSDAnySimpleType
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
buf << SOAPGenerator.encode_str(data.to_s)
|
||||
when SOAPStruct
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
data.each do |key, value|
|
||||
value.elename.namespace = data.elename.namespace if !value.elename.namespace
|
||||
yield(value, true)
|
||||
end
|
||||
when SOAPArray
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
data.traverse do |child, *rank|
|
||||
data.position = nil
|
||||
yield(child, true)
|
||||
end
|
||||
when SOAPElement
|
||||
SOAPGenerator.encode_tag(buf, name, attrs.update(data.extraattr),
|
||||
indent)
|
||||
buf << data.text if data.text
|
||||
data.each do |key, value|
|
||||
value.elename.namespace = data.elename.namespace if !value.elename.namespace
|
||||
#yield(value, data.qualified)
|
||||
yield(value, qualified)
|
||||
end
|
||||
else
|
||||
raise EncodingStyleError.new("Unknown object:#{ data } in this encodingStyle.")
|
||||
end
|
||||
end
|
||||
|
||||
def encode_data_end(buf, ns, qualified, data, parent, indent)
|
||||
name = if qualified and data.elename.namespace
|
||||
ns.name(data.elename)
|
||||
else
|
||||
data.elename.name
|
||||
end
|
||||
SOAPGenerator.encode_tag_end(buf, name, indent)
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
## decode interface.
|
||||
#
|
||||
class SOAPTemporalObject
|
||||
attr_accessor :parent
|
||||
|
||||
def initialize
|
||||
@parent = nil
|
||||
end
|
||||
end
|
||||
|
||||
class SOAPUnknown < SOAPTemporalObject
|
||||
def initialize(handler, elename)
|
||||
super()
|
||||
@handler = handler
|
||||
@elename = elename
|
||||
end
|
||||
|
||||
def as_struct
|
||||
o = SOAPStruct.decode(@elename, XSD::AnyTypeName)
|
||||
o.parent = @parent
|
||||
@handler.decode_parent(@parent, o)
|
||||
o
|
||||
end
|
||||
|
||||
def as_string
|
||||
o = SOAPString.decode(@elename)
|
||||
o.parent = @parent
|
||||
@handler.decode_parent(@parent, o)
|
||||
o
|
||||
end
|
||||
|
||||
def as_nil
|
||||
o = SOAPNil.decode(@elename)
|
||||
o.parent = @parent
|
||||
@handler.decode_parent(@parent, o)
|
||||
o
|
||||
end
|
||||
end
|
||||
|
||||
def decode_tag(ns, elename, attrs, parent)
|
||||
# ToDo: check if @textbuf is empty...
|
||||
@textbuf = ''
|
||||
o = SOAPUnknown.new(self, elename)
|
||||
o.parent = parent
|
||||
o
|
||||
end
|
||||
|
||||
def decode_tag_end(ns, node)
|
||||
o = node.node
|
||||
if o.is_a?(SOAPUnknown)
|
||||
newnode = if /\A\s*\z/ =~ @textbuf
|
||||
o.as_struct
|
||||
else
|
||||
o.as_string
|
||||
end
|
||||
node.replace_node(newnode)
|
||||
o = node.node
|
||||
end
|
||||
|
||||
decode_textbuf(o)
|
||||
@textbuf = ''
|
||||
end
|
||||
|
||||
def decode_text(ns, text)
|
||||
# @textbuf is set at decode_tag_end.
|
||||
@textbuf << text
|
||||
end
|
||||
|
||||
def decode_prologue
|
||||
end
|
||||
|
||||
def decode_epilogue
|
||||
end
|
||||
|
||||
def decode_parent(parent, node)
|
||||
case parent.node
|
||||
when SOAPUnknown
|
||||
newparent = parent.node.as_struct
|
||||
node.parent = newparent
|
||||
parent.replace_node(newparent)
|
||||
decode_parent(parent, node)
|
||||
|
||||
when SOAPStruct
|
||||
parent.node.add(node.name, node)
|
||||
|
||||
when SOAPArray
|
||||
if node.position
|
||||
parent.node[*(decode_arypos(node.position))] = node
|
||||
parent.node.sparse = true
|
||||
else
|
||||
parent.node.add(node)
|
||||
end
|
||||
|
||||
when SOAPBasetype
|
||||
raise EncodingStyleError.new("SOAP base type must not have a child.")
|
||||
|
||||
else
|
||||
# SOAPUnknown does not have parent.
|
||||
# raise EncodingStyleError.new("Illegal parent: #{ parent }.")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def decode_textbuf(node)
|
||||
if node.is_a?(XSD::XSDString)
|
||||
if @charset
|
||||
node.set(XSD::Charset.encoding_from_xml(@textbuf, @charset))
|
||||
else
|
||||
node.set(@textbuf)
|
||||
end
|
||||
else
|
||||
# Nothing to do...
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
LiteralHandler.new
|
||||
|
||||
|
||||
end
|
||||
end
|
548
lib/soap/encodingstyle/soapHandler.rb
Normal file
548
lib/soap/encodingstyle/soapHandler.rb
Normal file
|
@ -0,0 +1,548 @@
|
|||
=begin
|
||||
SOAP4R - SOAP EncodingStyle handler library
|
||||
Copyright (C) 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'soap/encodingstyle/handler'
|
||||
|
||||
|
||||
module SOAP
|
||||
module EncodingStyle
|
||||
|
||||
|
||||
class SOAPHandler < Handler
|
||||
Namespace = SOAP::EncodingNamespace
|
||||
add_handler
|
||||
|
||||
def initialize(charset = nil)
|
||||
super(charset)
|
||||
@refpool = []
|
||||
@idpool = []
|
||||
@textbuf = ''
|
||||
@is_first_top_ele = true
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
## encode interface.
|
||||
#
|
||||
def encode_data(buf, ns, qualified, data, parent, indent = '')
|
||||
attrs = encode_attrs(ns, qualified, data, parent)
|
||||
|
||||
if parent && parent.is_a?(SOAPArray) && parent.position
|
||||
attrs[ns.name(AttrPositionName)] = '[' << parent.position.join(',') << ']'
|
||||
end
|
||||
|
||||
name = nil
|
||||
if qualified and data.elename.namespace
|
||||
SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace)
|
||||
name = ns.name(data.elename)
|
||||
else
|
||||
name = data.elename.name
|
||||
end
|
||||
|
||||
if data.respond_to?(:encode)
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
return data.encode(buf, ns, attrs, indent)
|
||||
end
|
||||
|
||||
case data
|
||||
when SOAPReference
|
||||
attrs['href'] = '#' << data.refid
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
when SOAPRawString
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
buf << data.to_s
|
||||
when XSD::XSDString
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
buf << SOAPGenerator.encode_str(@charset ?
|
||||
XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
|
||||
when XSD::XSDAnySimpleType
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
buf << SOAPGenerator.encode_str(data.to_s)
|
||||
when SOAPStruct
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
data.each do |key, value|
|
||||
yield(value, false)
|
||||
end
|
||||
when SOAPArray
|
||||
SOAPGenerator.encode_tag(buf, name, attrs, indent)
|
||||
data.traverse do |child, *rank|
|
||||
data.position = data.sparse ? rank : nil
|
||||
yield(child, false)
|
||||
end
|
||||
else
|
||||
raise EncodingStyleError.new(
|
||||
"Unknown object:#{ data } in this encodingStyle.")
|
||||
end
|
||||
end
|
||||
|
||||
def encode_data_end(buf, ns, qualified, data, parent, indent = '')
|
||||
name = if qualified and data.elename.namespace
|
||||
ns.name(data.elename)
|
||||
else
|
||||
data.elename.name
|
||||
end
|
||||
cr = data.is_a?(SOAPCompoundtype)
|
||||
SOAPGenerator.encode_tag_end(buf, name, indent, cr)
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
## decode interface.
|
||||
#
|
||||
class SOAPTemporalObject
|
||||
attr_accessor :parent
|
||||
attr_accessor :position
|
||||
attr_accessor :id
|
||||
attr_accessor :root
|
||||
|
||||
def initialize
|
||||
@parent = nil
|
||||
@position = nil
|
||||
@id = nil
|
||||
@root = nil
|
||||
end
|
||||
end
|
||||
|
||||
class SOAPUnknown < SOAPTemporalObject
|
||||
attr_reader :type
|
||||
attr_accessor :definedtype
|
||||
attr_reader :extraattr
|
||||
|
||||
def initialize(handler, elename, type, extraattr)
|
||||
super()
|
||||
@handler = handler
|
||||
@elename = elename
|
||||
@type = type
|
||||
@extraattr = extraattr
|
||||
@definedtype = nil
|
||||
end
|
||||
|
||||
def as_struct
|
||||
o = SOAPStruct.decode(@elename, @type)
|
||||
o.id = @id
|
||||
o.root = @root
|
||||
o.parent = @parent
|
||||
o.position = @position
|
||||
o.extraattr.update(@extraattr)
|
||||
@handler.decode_parent(@parent, o)
|
||||
o
|
||||
end
|
||||
|
||||
def as_string
|
||||
o = SOAPString.decode(@elename)
|
||||
o.id = @id
|
||||
o.root = @root
|
||||
o.parent = @parent
|
||||
o.position = @position
|
||||
o.extraattr.update(@extraattr)
|
||||
@handler.decode_parent(@parent, o)
|
||||
o
|
||||
end
|
||||
|
||||
def as_nil
|
||||
o = SOAPNil.decode(@elename)
|
||||
o.id = @id
|
||||
o.root = @root
|
||||
o.parent = @parent
|
||||
o.position = @position
|
||||
o.extraattr.update(@extraattr)
|
||||
@handler.decode_parent(@parent, o)
|
||||
o
|
||||
end
|
||||
end
|
||||
|
||||
def decode_tag(ns, elename, attrs, parent)
|
||||
# ToDo: check if @textbuf is empty...
|
||||
@textbuf = ''
|
||||
is_nil, type, arytype, root, offset, position, href, id, extraattr =
|
||||
decode_attrs(ns, attrs)
|
||||
o = nil
|
||||
if is_nil
|
||||
o = SOAPNil.decode(elename)
|
||||
elsif href
|
||||
o = SOAPReference.decode(elename, href)
|
||||
@refpool << o
|
||||
elsif @decode_typemap &&
|
||||
(parent.node.class != SOAPBody || @is_first_top_ele)
|
||||
# multi-ref element should be parsed by decode_tag_by_type.
|
||||
@is_first_top_ele = false
|
||||
o = decode_tag_by_wsdl(ns, elename, type, parent.node, arytype, extraattr)
|
||||
else
|
||||
o = decode_tag_by_type(ns, elename, type, parent.node, arytype, extraattr)
|
||||
end
|
||||
|
||||
if o.is_a?(SOAPArray)
|
||||
if offset
|
||||
o.offset = decode_arypos(offset)
|
||||
o.sparse = true
|
||||
else
|
||||
o.sparse = false
|
||||
end
|
||||
end
|
||||
|
||||
o.parent = parent
|
||||
o.id = id
|
||||
o.root = root
|
||||
o.position = position
|
||||
|
||||
unless o.is_a?(SOAPTemporalObject)
|
||||
@idpool << o if o.id
|
||||
decode_parent(parent, o)
|
||||
end
|
||||
o
|
||||
end
|
||||
|
||||
def decode_tag_end(ns, node)
|
||||
o = node.node
|
||||
if o.is_a?(SOAPUnknown)
|
||||
newnode = if /\A\s*\z/ =~ @textbuf
|
||||
o.as_struct
|
||||
else
|
||||
o.as_string
|
||||
end
|
||||
if newnode.id
|
||||
@idpool << newnode
|
||||
end
|
||||
node.replace_node(newnode)
|
||||
o = node.node
|
||||
end
|
||||
if o.is_a?(SOAPCompoundtype)
|
||||
o.definedtype = nil
|
||||
end
|
||||
|
||||
decode_textbuf(o)
|
||||
@textbuf = ''
|
||||
end
|
||||
|
||||
def decode_text(ns, text)
|
||||
# @textbuf is set at decode_tag_end.
|
||||
@textbuf << text
|
||||
end
|
||||
|
||||
def decode_prologue
|
||||
@refpool.clear
|
||||
@idpool.clear
|
||||
@is_first_top_ele = true
|
||||
end
|
||||
|
||||
def decode_epilogue
|
||||
decode_resolve_id
|
||||
end
|
||||
|
||||
def decode_parent(parent, node)
|
||||
case parent.node
|
||||
when SOAPUnknown
|
||||
newparent = parent.node.as_struct
|
||||
node.parent = newparent
|
||||
if newparent.id
|
||||
@idpool << newparent
|
||||
end
|
||||
parent.replace_node(newparent)
|
||||
decode_parent(parent, node)
|
||||
|
||||
when SOAPStruct
|
||||
parent.node.add(node.elename.name, node)
|
||||
node.parent = parent.node
|
||||
|
||||
when SOAPArray
|
||||
if node.position
|
||||
parent.node[*(decode_arypos(node.position))] = node
|
||||
parent.node.sparse = true
|
||||
else
|
||||
parent.node.add(node)
|
||||
end
|
||||
node.parent = parent.node
|
||||
|
||||
when SOAPBasetype
|
||||
raise EncodingStyleError.new("SOAP base type must not have a child.")
|
||||
|
||||
else
|
||||
raise EncodingStyleError.new("Illegal parent: #{ parent.node }.")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def content_ranksize(typename)
|
||||
typename.scan(/\[[\d,]*\]$/)[0]
|
||||
end
|
||||
|
||||
def content_typename(typename)
|
||||
typename.sub(/\[,*\]$/, '')
|
||||
end
|
||||
|
||||
def create_arytype(ns, data)
|
||||
XSD::QName.new(data.arytype.namespace,
|
||||
content_typename(data.arytype.name) << '[' << data.size.join(',') << ']')
|
||||
end
|
||||
|
||||
def encode_attrs(ns, qualified, data, parent)
|
||||
return {} if data.is_a?(SOAPReference)
|
||||
attrs = {}
|
||||
|
||||
if !parent || parent.encodingstyle != EncodingNamespace
|
||||
if @generate_explicit_type
|
||||
SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace)
|
||||
SOAPGenerator.assign_ns(attrs, ns, EncodingNamespace)
|
||||
attrs[ns.name(AttrEncodingStyleName)] = EncodingNamespace
|
||||
end
|
||||
data.encodingstyle = EncodingNamespace
|
||||
end
|
||||
|
||||
if data.is_a?(SOAPNil)
|
||||
attrs[ns.name(XSD::AttrNilName)] = XSD::NilValue
|
||||
elsif @generate_explicit_type
|
||||
if data.type.namespace
|
||||
SOAPGenerator.assign_ns(attrs, ns, data.type.namespace)
|
||||
end
|
||||
if data.is_a?(SOAPArray)
|
||||
if data.arytype.namespace
|
||||
SOAPGenerator.assign_ns(attrs, ns, data.arytype.namespace)
|
||||
end
|
||||
attrs[ns.name(AttrArrayTypeName)] = ns.name(create_arytype(ns, data))
|
||||
if data.type.name
|
||||
attrs[ns.name(XSD::AttrTypeName)] = ns.name(data.type)
|
||||
end
|
||||
elsif parent && parent.is_a?(SOAPArray) && (parent.arytype == data.type)
|
||||
# No need to add.
|
||||
elsif !data.type.namespace
|
||||
# No need to add.
|
||||
else
|
||||
attrs[ns.name(XSD::AttrTypeName)] = ns.name(data.type)
|
||||
end
|
||||
end
|
||||
|
||||
data.extraattr.each do |key, value|
|
||||
SOAPGenerator.assign_ns(attrs, ns, key.namespace)
|
||||
attrs[ns.name(key)] = value # ns.name(value) ?
|
||||
end
|
||||
if data.id
|
||||
attrs['id'] = data.id
|
||||
end
|
||||
attrs
|
||||
end
|
||||
|
||||
def decode_tag_by_wsdl(ns, elename, typestr, parent, arytypestr, extraattr)
|
||||
if parent.class == SOAPBody
|
||||
# Unqualified name is allowed here.
|
||||
type = @decode_typemap[elename] || @decode_typemap.find_name(elename.name)
|
||||
unless type
|
||||
raise EncodingStyleError.new("Unknown operation '#{ elename }'.")
|
||||
end
|
||||
o = SOAPStruct.new(elename)
|
||||
o.definedtype = type
|
||||
return o
|
||||
end
|
||||
|
||||
if parent.type == XSD::AnyTypeName
|
||||
return decode_tag_by_type(ns, elename, typestr, parent, arytypestr,
|
||||
extraattr)
|
||||
end
|
||||
|
||||
# parent.definedtype is nil means the parent is SOAPUnknown. SOAPUnknown is
|
||||
# generated by decode_tag_by_type when its type is anyType.
|
||||
parenttype = parent.definedtype || @decode_typemap[parent.type]
|
||||
unless parenttype
|
||||
raise EncodingStyleError.new("Unknown type '#{ parent.type }'.")
|
||||
end
|
||||
typename = parenttype.child_type(elename)
|
||||
if typename
|
||||
if (klass = TypeMap[typename])
|
||||
return klass.decode(elename)
|
||||
elsif typename == XSD::AnyTypeName
|
||||
return decode_tag_by_type(ns, elename, typestr, parent, arytypestr,
|
||||
extraattr)
|
||||
end
|
||||
end
|
||||
|
||||
type = if typename
|
||||
@decode_typemap[typename]
|
||||
else
|
||||
parenttype.child_defined_complextype(elename)
|
||||
end
|
||||
unless type
|
||||
raise EncodingStyleError.new("Unknown type '#{ typename }'.")
|
||||
end
|
||||
|
||||
case type.compoundtype
|
||||
when :TYPE_STRUCT
|
||||
o = SOAPStruct.decode(elename, typename)
|
||||
o.definedtype = type
|
||||
return o
|
||||
when :TYPE_ARRAY
|
||||
expected_arytype = type.find_arytype
|
||||
actual_arytype = if arytypestr
|
||||
XSD::QName.new(expected_arytype.namespace,
|
||||
content_typename(expected_arytype.name) <<
|
||||
content_ranksize(arytypestr))
|
||||
else
|
||||
expected_arytype
|
||||
end
|
||||
o = SOAPArray.decode(elename, typename, actual_arytype)
|
||||
o.definedtype = type
|
||||
return o
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
def decode_tag_by_type(ns, elename, typestr, parent, arytypestr, extraattr)
|
||||
if arytypestr
|
||||
type = typestr ? ns.parse(typestr) : ValueArrayName
|
||||
node = SOAPArray.decode(elename, type, ns.parse(arytypestr))
|
||||
node.extraattr.update(extraattr)
|
||||
return node
|
||||
end
|
||||
|
||||
type = nil
|
||||
if typestr
|
||||
type = ns.parse(typestr)
|
||||
elsif parent.is_a?(SOAPArray)
|
||||
type = parent.arytype
|
||||
else
|
||||
# Since it's in dynamic(without any type) encoding process,
|
||||
# assumes entity as its type itself.
|
||||
# <SOAP-ENC:Array ...> => type Array in SOAP-ENC.
|
||||
# <Country xmlns="foo"> => type Country in foo.
|
||||
type = elename
|
||||
end
|
||||
|
||||
if (klass = TypeMap[type])
|
||||
klass.decode(elename)
|
||||
else
|
||||
# Unknown type... Struct or String
|
||||
SOAPUnknown.new(self, elename, type, extraattr)
|
||||
end
|
||||
end
|
||||
|
||||
def decode_textbuf(node)
|
||||
case node
|
||||
when XSD::XSDHexBinary, XSD::XSDBase64Binary
|
||||
node.set_encoded(@textbuf)
|
||||
when XSD::XSDString
|
||||
if @charset
|
||||
node.set(XSD::Charset.encoding_from_xml(@textbuf, @charset))
|
||||
else
|
||||
node.set(@textbuf)
|
||||
end
|
||||
when SOAPNil
|
||||
# Nothing to do.
|
||||
when SOAPBasetype
|
||||
node.set(@textbuf)
|
||||
else
|
||||
# Nothing to do...
|
||||
end
|
||||
end
|
||||
|
||||
NilLiteralMap = {
|
||||
'true' => true,
|
||||
'1' => true,
|
||||
'false' => false,
|
||||
'0' => false
|
||||
}
|
||||
RootLiteralMap = {
|
||||
'1' => 1,
|
||||
'0' => 0
|
||||
}
|
||||
def decode_attrs(ns, attrs)
|
||||
is_nil = false
|
||||
type = nil
|
||||
arytype = nil
|
||||
root = nil
|
||||
offset = nil
|
||||
position = nil
|
||||
href = nil
|
||||
id = nil
|
||||
extraattr = {}
|
||||
|
||||
attrs.each do |key, value|
|
||||
qname = ns.parse(key)
|
||||
case qname.namespace
|
||||
when XSD::InstanceNamespace
|
||||
case qname.name
|
||||
when XSD::NilLiteral
|
||||
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').")
|
||||
next
|
||||
when XSD::AttrType
|
||||
type = value
|
||||
next
|
||||
end
|
||||
when EncodingNamespace
|
||||
case qname.name
|
||||
when AttrArrayType
|
||||
arytype = value
|
||||
next
|
||||
when AttrRoot
|
||||
root = RootLiteralMap[value] or
|
||||
raise EncodingStyleError.new(
|
||||
"Illegal root attribute value: #{ value }.")
|
||||
next
|
||||
when AttrOffset
|
||||
offset = value
|
||||
next
|
||||
when AttrPosition
|
||||
position = value
|
||||
next
|
||||
end
|
||||
end
|
||||
if key == 'href'
|
||||
href = value
|
||||
next
|
||||
elsif key == 'id'
|
||||
id = value
|
||||
next
|
||||
end
|
||||
extraattr[qname] = value
|
||||
end
|
||||
|
||||
return is_nil, type, arytype, root, offset, position, href, id, extraattr
|
||||
end
|
||||
|
||||
def decode_arypos(position)
|
||||
/^\[(.+)\]$/ =~ position
|
||||
$1.split(',').collect { |s| s.to_i }
|
||||
end
|
||||
|
||||
def decode_resolve_id
|
||||
count = @refpool.length # To avoid infinite loop
|
||||
while !@refpool.empty? && count > 0
|
||||
@refpool = @refpool.find_all { |ref|
|
||||
o = @idpool.find { |item|
|
||||
('#' << item.id == ref.refid)
|
||||
}
|
||||
unless o
|
||||
raise EncodingStyleError.new("Unresolved reference: #{ ref.refid }.")
|
||||
end
|
||||
if o.is_a?(SOAPReference)
|
||||
true
|
||||
else
|
||||
ref.__setobj__(o)
|
||||
false
|
||||
end
|
||||
}
|
||||
count -= 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SOAPHandler.new
|
||||
|
||||
|
||||
end
|
||||
end
|
206
lib/soap/generator.rb
Normal file
206
lib/soap/generator.rb
Normal file
|
@ -0,0 +1,206 @@
|
|||
=begin
|
||||
SOAP4R - SOAP XML Instance Generator library.
|
||||
Copyright (C) 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/ns'
|
||||
require 'soap/soap'
|
||||
require 'soap/baseData'
|
||||
require 'soap/encodingstyle/handler'
|
||||
|
||||
|
||||
module SOAP
|
||||
|
||||
|
||||
###
|
||||
## CAUTION: MT-unsafe
|
||||
#
|
||||
class SOAPGenerator
|
||||
include SOAP
|
||||
|
||||
class FormatEncodeError < Error; end
|
||||
|
||||
public
|
||||
|
||||
attr_accessor :charset
|
||||
attr_accessor :default_encodingstyle
|
||||
attr_accessor :generate_explicit_type
|
||||
attr_accessor :pretty
|
||||
|
||||
def initialize(opt = {})
|
||||
@reftarget = nil
|
||||
@handlers = {}
|
||||
@charset = opt[:charset] || XSD::Charset.encoding_label
|
||||
@default_encodingstyle = opt[:default_encodingstyle] || EncodingNamespace
|
||||
@generate_explicit_type =
|
||||
opt.key?(:generate_explicit_type) ? opt[:generate_explicit_type] : true
|
||||
@pretty = true # opt[:pretty]
|
||||
end
|
||||
|
||||
def generate(obj, io = nil)
|
||||
prologue
|
||||
@handlers.each do |uri, handler|
|
||||
handler.encode_prologue
|
||||
end
|
||||
|
||||
io = '' if io.nil?
|
||||
|
||||
ns = XSD::NS.new
|
||||
io << xmldecl
|
||||
encode_data(io, ns, true, obj, nil, 0)
|
||||
|
||||
@handlers.each do |uri, handler|
|
||||
handler.encode_epilogue
|
||||
end
|
||||
epilogue
|
||||
|
||||
io
|
||||
end
|
||||
|
||||
def encode_data(buf, ns, qualified, obj, parent, indent)
|
||||
if obj.is_a?(SOAPEnvelopeElement)
|
||||
encode_element(buf, ns, qualified, obj, parent, indent)
|
||||
return
|
||||
end
|
||||
|
||||
if @reftarget && !obj.precedents.empty?
|
||||
@reftarget.add(obj.elename.name, obj)
|
||||
ref = SOAPReference.new
|
||||
ref.elename.name = obj.elename.name
|
||||
ref.__setobj__(obj)
|
||||
obj.precedents.clear # Avoid cyclic delay.
|
||||
obj.encodingstyle = parent.encodingstyle
|
||||
# SOAPReference is encoded here.
|
||||
obj = ref
|
||||
end
|
||||
|
||||
encodingstyle = obj.encodingstyle
|
||||
# Children's encodingstyle is derived from its parent.
|
||||
encodingstyle ||= parent.encodingstyle if parent
|
||||
obj.encodingstyle = encodingstyle
|
||||
|
||||
handler = find_handler(encodingstyle || @default_encodingstyle)
|
||||
unless handler
|
||||
raise FormatEncodeError.new("Unknown encodingStyle: #{ encodingstyle }.")
|
||||
end
|
||||
|
||||
if !obj.elename.name
|
||||
raise FormatEncodeError.new("Element name not defined: #{ obj }.")
|
||||
end
|
||||
|
||||
indent_str = ' ' * indent
|
||||
child_indent = @pretty ? indent + 2 : indent
|
||||
handler.encode_data(buf, ns, qualified, obj, parent, indent_str) do |child, child_q|
|
||||
encode_data(buf, ns.clone_ns, child_q, child, obj, child_indent)
|
||||
end
|
||||
handler.encode_data_end(buf, ns, qualified, obj, parent, indent_str)
|
||||
end
|
||||
|
||||
def encode_element(buf, ns, qualified, obj, parent, indent)
|
||||
indent_str = ' ' * indent
|
||||
child_indent = @pretty ? indent + 2 : indent
|
||||
attrs = {}
|
||||
if obj.is_a?(SOAPBody)
|
||||
@reftarget = obj
|
||||
obj.encode(buf, ns, attrs, indent_str) do |child, child_q|
|
||||
encode_data(buf, ns.clone_ns, child_q, child, obj, child_indent)
|
||||
end
|
||||
@reftarget = nil
|
||||
else
|
||||
if obj.is_a?(SOAPEnvelope)
|
||||
# xsi:nil="true" can appear even if dumping without explicit type.
|
||||
SOAPGenerator.assign_ns(attrs, ns,
|
||||
XSD::InstanceNamespace, XSINamespaceTag)
|
||||
if @generate_explicit_type
|
||||
SOAPGenerator.assign_ns(attrs, ns, XSD::Namespace, XSDNamespaceTag)
|
||||
end
|
||||
end
|
||||
obj.encode(buf, ns, attrs, indent_str) do |child, child_q|
|
||||
encode_data(buf, ns.clone_ns, child_q, child, obj, child_indent)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.assign_ns(attrs, ns, namespace, tag = nil)
|
||||
unless ns.assigned?(namespace)
|
||||
tag = ns.assign(namespace, tag)
|
||||
attrs['xmlns:' << tag] = namespace
|
||||
end
|
||||
end
|
||||
|
||||
def self.encode_tag(buf, elename, attrs = nil, indent = '')
|
||||
if attrs
|
||||
buf << "\n#{ indent }<#{ elename }" <<
|
||||
attrs.collect { |key, value|
|
||||
%Q[ #{ key }="#{ value }"]
|
||||
}.join <<
|
||||
'>'
|
||||
else
|
||||
buf << "\n#{ indent }<#{ elename }>"
|
||||
end
|
||||
end
|
||||
|
||||
def self.encode_tag_end(buf, elename, indent = '', cr = nil)
|
||||
if cr
|
||||
buf << "\n#{ indent }</#{ elename }>"
|
||||
else
|
||||
buf << "</#{ elename }>"
|
||||
end
|
||||
end
|
||||
|
||||
EncodeMap = {
|
||||
'&' => '&',
|
||||
'<' => '<',
|
||||
'>' => '>',
|
||||
'"' => '"',
|
||||
'\'' => ''',
|
||||
"\r" => '
'
|
||||
}
|
||||
EncodeCharRegexp = Regexp.new("[#{EncodeMap.keys.join}]")
|
||||
def self.encode_str(str)
|
||||
str.gsub(EncodeCharRegexp) { |c| EncodeMap[c] }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def prologue
|
||||
end
|
||||
|
||||
def epilogue
|
||||
end
|
||||
|
||||
def find_handler(encodingstyle)
|
||||
unless @handlers.key?(encodingstyle)
|
||||
handler = SOAP::EncodingStyle::Handler.handler(encodingstyle).new(@charset)
|
||||
handler.generate_explicit_type = @generate_explicit_type
|
||||
handler.encode_prologue
|
||||
@handlers[encodingstyle] = handler
|
||||
end
|
||||
@handlers[encodingstyle]
|
||||
end
|
||||
|
||||
def xmldecl
|
||||
if @charset
|
||||
%Q[<?xml version="1.0" encoding="#{ @charset }" ?>]
|
||||
else
|
||||
%Q[<?xml version="1.0" ?>]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
21
lib/soap/mapping.rb
Normal file
21
lib/soap/mapping.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
=begin
|
||||
SOAP4R - Ruby type mapping utility.
|
||||
Copyright (C) 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'soap/mapping/mapping'
|
||||
require 'soap/mapping/registry'
|
310
lib/soap/mapping/factory.rb
Normal file
310
lib/soap/mapping/factory.rb
Normal file
|
@ -0,0 +1,310 @@
|
|||
=begin
|
||||
SOAP4R - Mapping factory.
|
||||
Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
module SOAP
|
||||
module Mapping
|
||||
|
||||
|
||||
class Factory
|
||||
include TraverseSupport
|
||||
|
||||
def obj2soap(soap_class, obj, info, map)
|
||||
raise NotImplementError.new
|
||||
# return soap_obj
|
||||
end
|
||||
|
||||
def soap2obj(obj_class, node, info, map)
|
||||
raise NotImplementError.new
|
||||
# return convert_succeeded_or_not, obj
|
||||
end
|
||||
|
||||
if Object.respond_to?(:allocate)
|
||||
# ruby/1.7 or later.
|
||||
def create_empty_object(klass)
|
||||
klass.allocate
|
||||
end
|
||||
else
|
||||
def create_empty_object(klass)
|
||||
name = klass.name
|
||||
# Below line is from TANAKA, Akira's amarshal.rb.
|
||||
# See http://cvs.m17n.org/cgi-bin/viewcvs/amarshal/?cvsroot=ruby
|
||||
::Marshal.load(sprintf("\004\006o:%c%s\000", name.length + 5, name))
|
||||
end
|
||||
end
|
||||
|
||||
def set_instance_vars(obj, values)
|
||||
values.each do |name, value|
|
||||
setter = name + "="
|
||||
if obj.respond_to?(setter)
|
||||
obj.__send__(setter, value)
|
||||
else
|
||||
obj.instance_eval("@#{ name } = value")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def setiv2obj(obj, node, map)
|
||||
return if node.nil?
|
||||
vars = {}
|
||||
node.each do |name, value|
|
||||
vars[Mapping.elename2name(name)] = Mapping._soap2obj(value, map)
|
||||
end
|
||||
set_instance_vars(obj, vars)
|
||||
end
|
||||
|
||||
def setiv2soap(node, obj, map)
|
||||
obj.instance_variables.each do |var|
|
||||
name = var.sub(/^@/, '')
|
||||
node.add(Mapping.name2elename(name),
|
||||
Mapping._obj2soap(obj.instance_eval(var), map))
|
||||
end
|
||||
end
|
||||
|
||||
def addiv2soap(node, obj, map)
|
||||
return if obj.instance_variables.empty?
|
||||
ivars = SOAPStruct.new # Undefined type.
|
||||
setiv2soap(ivars, obj, map)
|
||||
node.add('ivars', ivars)
|
||||
end
|
||||
|
||||
# It breaks Thread.current[:SOAPMarshalDataKey].
|
||||
def mark_marshalled_obj(obj, soap_obj)
|
||||
Thread.current[:SOAPMarshalDataKey][obj.__id__] = soap_obj
|
||||
end
|
||||
|
||||
# It breaks Thread.current[:SOAPMarshalDataKey].
|
||||
def mark_unmarshalled_obj(node, obj)
|
||||
Thread.current[:SOAPMarshalDataKey][node.id] = obj
|
||||
end
|
||||
|
||||
def name2typename(name)
|
||||
capitalize(name)
|
||||
end
|
||||
|
||||
def capitalize(target)
|
||||
target.gsub(/^([a-z])/) { $1.tr!('[a-z]', '[A-Z]') }
|
||||
end
|
||||
end
|
||||
|
||||
class StringFactory_ < Factory
|
||||
def obj2soap(soap_class, obj, info, map)
|
||||
begin
|
||||
if XSD::Charset.is_ces(obj, $KCODE)
|
||||
encoded = XSD::Charset.encoding_conv(obj, $KCODE, XSD::Charset.encoding)
|
||||
soap_obj = soap_class.new(encoded)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
rescue XSD::ValueSpaceError
|
||||
return nil
|
||||
end
|
||||
mark_marshalled_obj(obj, soap_obj)
|
||||
soap_obj
|
||||
end
|
||||
|
||||
def soap2obj(obj_class, node, info, map)
|
||||
obj = XSD::Charset.encoding_conv(node.data, XSD::Charset.encoding, $KCODE)
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
return true, obj
|
||||
end
|
||||
end
|
||||
|
||||
class BasetypeFactory_ < Factory
|
||||
def obj2soap(soap_class, obj, info, map)
|
||||
soap_obj = nil
|
||||
begin
|
||||
soap_obj = soap_class.new(obj)
|
||||
rescue XSD::ValueSpaceError
|
||||
return nil
|
||||
end
|
||||
# Basetype except String should not be multiref-ed in SOAP/1.1.
|
||||
soap_obj
|
||||
end
|
||||
|
||||
def soap2obj(obj_class, node, info, map)
|
||||
obj = node.data
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
return true, obj
|
||||
end
|
||||
end
|
||||
|
||||
class DateTimeFactory_ < Factory
|
||||
def obj2soap(soap_class, obj, info, map)
|
||||
soap_obj = nil
|
||||
begin
|
||||
soap_obj = soap_class.new(obj)
|
||||
rescue XSD::ValueSpaceError
|
||||
return nil
|
||||
end
|
||||
mark_marshalled_obj(obj, soap_obj)
|
||||
soap_obj
|
||||
end
|
||||
|
||||
def soap2obj(obj_class, node, info, map)
|
||||
obj = nil
|
||||
if obj_class == Time
|
||||
obj = node.to_time
|
||||
if obj.nil?
|
||||
# Is out of range as a Time
|
||||
return false
|
||||
end
|
||||
elsif obj_class == Date
|
||||
obj = node.data
|
||||
else
|
||||
return false
|
||||
end
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
return true, obj
|
||||
end
|
||||
end
|
||||
|
||||
class Base64Factory_ < Factory
|
||||
def obj2soap(soap_class, obj, info, map)
|
||||
soap_obj = soap_class.new(obj)
|
||||
mark_marshalled_obj(obj, soap_obj) if soap_obj
|
||||
soap_obj
|
||||
end
|
||||
|
||||
def soap2obj(obj_class, node, info, map)
|
||||
obj = node.string
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
return true, obj
|
||||
end
|
||||
end
|
||||
|
||||
class ArrayFactory_ < Factory
|
||||
# [[1], [2]] is converted to Array of Array, not 2-D Array.
|
||||
# To create M-D Array, you must call Mapping.ary2md.
|
||||
def obj2soap(soap_class, obj, info, map)
|
||||
arytype = Mapping.obj2element(obj)
|
||||
if arytype.name
|
||||
arytype.namespace ||= RubyTypeNamespace
|
||||
else
|
||||
arytype = XSD::AnyTypeName
|
||||
end
|
||||
param = SOAPArray.new(ValueArrayName, 1, arytype)
|
||||
mark_marshalled_obj(obj, param)
|
||||
obj.each do |var|
|
||||
param.add(Mapping._obj2soap(var, map))
|
||||
end
|
||||
param
|
||||
end
|
||||
|
||||
def soap2obj(obj_class, node, info, map)
|
||||
obj = create_empty_object(obj_class)
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
node.soap2array(obj) do |elem|
|
||||
elem ? Mapping._soap2obj(elem, map) : nil
|
||||
end
|
||||
return true, obj
|
||||
end
|
||||
end
|
||||
|
||||
class TypedArrayFactory_ < Factory
|
||||
def obj2soap(soap_class, obj, info, map)
|
||||
arytype = info[:type] || info[0]
|
||||
param = SOAPArray.new(ValueArrayName, 1, arytype)
|
||||
mark_marshalled_obj(obj, param)
|
||||
obj.each do |var|
|
||||
param.add(Mapping._obj2soap(var, map))
|
||||
end
|
||||
param
|
||||
end
|
||||
|
||||
def soap2obj(obj_class, node, info, map)
|
||||
if node.rank > 1
|
||||
return false
|
||||
end
|
||||
arytype = info[:type] || info[0]
|
||||
unless node.arytype == arytype
|
||||
return false
|
||||
end
|
||||
obj = create_empty_object(obj_class)
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
node.soap2array(obj) do |elem|
|
||||
elem ? Mapping._soap2obj(elem, map) : nil
|
||||
end
|
||||
return true, obj
|
||||
end
|
||||
end
|
||||
|
||||
class TypedStructFactory_ < Factory
|
||||
def obj2soap(soap_class, obj, info, map)
|
||||
type = info[:type] || info[0]
|
||||
param = soap_class.new(type)
|
||||
mark_marshalled_obj(obj, param)
|
||||
if obj.class <= SOAP::Marshallable
|
||||
setiv2soap(param, obj, map)
|
||||
else
|
||||
setiv2soap(param, obj, map)
|
||||
end
|
||||
param
|
||||
end
|
||||
|
||||
def soap2obj(obj_class, node, info, map)
|
||||
type = info[:type] || info[0]
|
||||
unless node.type == type
|
||||
return false
|
||||
end
|
||||
obj = create_empty_object(obj_class)
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
setiv2obj(obj, node, map)
|
||||
return true, obj
|
||||
end
|
||||
end
|
||||
|
||||
MapQName = XSD::QName.new(ApacheSOAPTypeNamespace, 'Map')
|
||||
class HashFactory_ < Factory
|
||||
def obj2soap(soap_class, obj, info, map)
|
||||
if obj.default or
|
||||
(obj.respond_to?(:default_proc) and obj.default_proc)
|
||||
return nil
|
||||
end
|
||||
param = SOAPStruct.new(MapQName)
|
||||
mark_marshalled_obj(obj, param)
|
||||
obj.each do |key, value|
|
||||
elem = SOAPStruct.new
|
||||
elem.add("key", Mapping._obj2soap(key, map))
|
||||
elem.add("value", Mapping._obj2soap(value, map))
|
||||
# ApacheAxis allows only 'item' here.
|
||||
param.add("item", elem)
|
||||
end
|
||||
param
|
||||
end
|
||||
|
||||
def soap2obj(obj_class, node, info, map)
|
||||
unless node.type == MapQName
|
||||
return false
|
||||
end
|
||||
if node.key?('default')
|
||||
return false
|
||||
end
|
||||
obj = create_empty_object(obj_class)
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
node.each do |key, value|
|
||||
obj[Mapping._soap2obj(value['key'], map)] =
|
||||
Mapping._soap2obj(value['value'], map)
|
||||
end
|
||||
return true, obj
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
218
lib/soap/mapping/mapping.rb
Normal file
218
lib/soap/mapping/mapping.rb
Normal file
|
@ -0,0 +1,218 @@
|
|||
=begin
|
||||
SOAP4R - Ruby type mapping utility.
|
||||
Copyright (C) 2000, 2001, 2003 NAKAMURA Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
module SOAP
|
||||
|
||||
|
||||
module Mapping
|
||||
RubyTypeNamespace = 'http://www.ruby-lang.org/xmlns/ruby/type/1.6'
|
||||
RubyTypeInstanceNamespace =
|
||||
'http://www.ruby-lang.org/xmlns/ruby/type-instance'
|
||||
RubyCustomTypeNamespace = 'http://www.ruby-lang.org/xmlns/ruby/type/custom'
|
||||
ApacheSOAPTypeNamespace = 'http://xml.apache.org/xml-soap'
|
||||
|
||||
|
||||
# TraverseSupport breaks Thread.current[:SOAPMarshalDataKey].
|
||||
module TraverseSupport
|
||||
def mark_marshalled_obj(obj, soap_obj)
|
||||
Thread.current[:SOAPMarshalDataKey][obj.__id__] = soap_obj
|
||||
end
|
||||
|
||||
def mark_unmarshalled_obj(node, obj)
|
||||
# node.id is not Object#id but SOAPReference#id
|
||||
Thread.current[:SOAPMarshalDataKey][node.id] = obj
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def self.obj2soap(obj, registry = nil, type = nil)
|
||||
registry ||= Mapping::DefaultRegistry
|
||||
Thread.current[:SOAPMarshalDataKey] = {}
|
||||
soap_obj = _obj2soap(obj, registry, type)
|
||||
Thread.current[:SOAPMarshalDataKey] = nil
|
||||
soap_obj
|
||||
end
|
||||
|
||||
def self.soap2obj(node, registry = nil)
|
||||
registry ||= Mapping::DefaultRegistry
|
||||
Thread.current[:SOAPMarshalDataKey] = {}
|
||||
obj = _soap2obj(node, registry)
|
||||
Thread.current[:SOAPMarshalDataKey] = nil
|
||||
obj
|
||||
end
|
||||
|
||||
def self.ary2soap(ary, type_ns = XSD::Namespace, typename = XSD::AnyTypeLiteral, registry = nil)
|
||||
registry ||= Mapping::DefaultRegistry
|
||||
type = XSD::QName.new(type_ns, typename)
|
||||
soap_ary = SOAPArray.new(ValueArrayName, 1, type)
|
||||
Thread.current[:SOAPMarshalDataKey] = {}
|
||||
ary.each do |ele|
|
||||
soap_ary.add(_obj2soap(ele, registry, type))
|
||||
end
|
||||
Thread.current[:SOAPMarshalDataKey] = nil
|
||||
soap_ary
|
||||
end
|
||||
|
||||
def self.ary2md(ary, rank, type_ns = XSD::Namespace, typename = XSD::AnyTypeLiteral, registry = nil)
|
||||
registry ||= Mapping::DefaultRegistry
|
||||
type = XSD::QName.new(type_ns, typename)
|
||||
md_ary = SOAPArray.new(ValueArrayName, rank, type)
|
||||
Thread.current[:SOAPMarshalDataKey] = {}
|
||||
add_md_ary(md_ary, ary, [], registry)
|
||||
Thread.current[:SOAPMarshalDataKey] = nil
|
||||
md_ary
|
||||
end
|
||||
|
||||
def self.fault2exception(e, registry = nil)
|
||||
registry ||= Mapping::DefaultRegistry
|
||||
detail = if e.detail
|
||||
soap2obj(e.detail, registry) || ""
|
||||
else
|
||||
""
|
||||
end
|
||||
if detail.is_a?(Mapping::SOAPException)
|
||||
begin
|
||||
raise detail.to_e
|
||||
rescue Exception => e2
|
||||
detail.set_backtrace(e2)
|
||||
raise
|
||||
end
|
||||
else
|
||||
e.detail = detail
|
||||
e.set_backtrace(
|
||||
if detail.is_a?(Array)
|
||||
detail
|
||||
else
|
||||
[detail.to_s]
|
||||
end
|
||||
)
|
||||
raise
|
||||
end
|
||||
end
|
||||
|
||||
def self._obj2soap(obj, registry, type = nil)
|
||||
if referent = Thread.current[:SOAPMarshalDataKey][obj.__id__]
|
||||
soap_obj = SOAPReference.new
|
||||
soap_obj.__setobj__(referent)
|
||||
soap_obj
|
||||
else
|
||||
registry.obj2soap(obj.class, obj, type)
|
||||
end
|
||||
end
|
||||
|
||||
def self._soap2obj(node, registry)
|
||||
if node.is_a?(SOAPReference)
|
||||
target = node.__getobj__
|
||||
# target.id is not Object#id but SOAPReference#id
|
||||
if referent = Thread.current[:SOAPMarshalDataKey][target.id]
|
||||
return referent
|
||||
else
|
||||
return _soap2obj(target, registry)
|
||||
end
|
||||
end
|
||||
return registry.soap2obj(node.class, node)
|
||||
end
|
||||
|
||||
|
||||
# Allow only (Letter | '_') (Letter | Digit | '-' | '_')* here.
|
||||
# Caution: '.' is not allowed here.
|
||||
# To follow XML spec., it should be NCName.
|
||||
# (denied chars) => .[0-F][0-F]
|
||||
# ex. a.b => a.2eb
|
||||
#
|
||||
def self.name2elename(name)
|
||||
name.gsub(/([^a-zA-Z0-9:_\-]+)/n) {
|
||||
'.' << $1.unpack('H2' * $1.size).join('.')
|
||||
}.gsub(/::/n, '..')
|
||||
end
|
||||
|
||||
def self.elename2name(name)
|
||||
name.gsub(/\.\./n, '::').gsub(/((?:\.[0-9a-fA-F]{2})+)/n) {
|
||||
[$1.delete('.')].pack('H*')
|
||||
}
|
||||
end
|
||||
|
||||
def self.class_from_name(name)
|
||||
if /^[A-Z]/ !~ name
|
||||
return nil
|
||||
end
|
||||
klass = ::Object
|
||||
name.split('::').each do |klass_str|
|
||||
if klass.const_defined?(klass_str)
|
||||
klass = klass.const_get(klass_str)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
klass
|
||||
end
|
||||
|
||||
def self.class2qname(klass)
|
||||
name = if klass.class_variables.include?("@@schema_type")
|
||||
klass.class_eval("@@schema_type")
|
||||
else
|
||||
nil
|
||||
end
|
||||
namespace = if klass.class_variables.include?("@@schema_ns")
|
||||
klass.class_eval("@@schema_ns")
|
||||
else
|
||||
nil
|
||||
end
|
||||
XSD::QName.new(namespace, name)
|
||||
end
|
||||
|
||||
def self.class2element(klass)
|
||||
type = Mapping.class2qname(klass)
|
||||
type.name ||= Mapping.name2elename(klass.name)
|
||||
type.namespace ||= RubyCustomTypeNamespace
|
||||
type
|
||||
end
|
||||
|
||||
def self.obj2element(obj)
|
||||
name = namespace = nil
|
||||
ivars = obj.instance_variables
|
||||
if ivars.include?("@schema_type")
|
||||
name = obj.instance_eval("@schema_type")
|
||||
end
|
||||
if ivars.include?("@schema_ns")
|
||||
namespace = obj.instance_eval("@schema_ns")
|
||||
end
|
||||
if !name or !namespace
|
||||
class2qname(obj.class)
|
||||
else
|
||||
XSD::QName.new(namespace, name)
|
||||
end
|
||||
end
|
||||
|
||||
class << Mapping
|
||||
private
|
||||
def add_md_ary(md_ary, ary, indices, registry)
|
||||
for idx in 0..(ary.size - 1)
|
||||
if ary[idx].is_a?(Array)
|
||||
add_md_ary(md_ary, ary[idx], indices + [idx], registry)
|
||||
else
|
||||
md_ary[*(indices + [idx])] = _obj2soap(ary[idx], registry)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
408
lib/soap/mapping/registry.rb
Normal file
408
lib/soap/mapping/registry.rb
Normal file
|
@ -0,0 +1,408 @@
|
|||
=begin
|
||||
SOAP4R - Mapping registry.
|
||||
Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'soap/baseData'
|
||||
require 'soap/mapping/mapping'
|
||||
require 'soap/mapping/typeMap'
|
||||
require 'soap/mapping/factory'
|
||||
require 'soap/mapping/rubytypeFactory'
|
||||
|
||||
|
||||
module SOAP
|
||||
|
||||
|
||||
module Marshallable
|
||||
# @@type_ns = Mapping::RubyCustomTypeNamespace
|
||||
end
|
||||
|
||||
|
||||
module Mapping
|
||||
|
||||
|
||||
module MappedException; end
|
||||
|
||||
|
||||
RubyTypeName = XSD::QName.new(RubyTypeInstanceNamespace, 'rubyType')
|
||||
|
||||
|
||||
# Inner class to pass an exception.
|
||||
class SOAPException; include Marshallable
|
||||
attr_reader :excn_type_name, :message, :backtrace, :cause
|
||||
def initialize(e)
|
||||
@excn_type_name = Mapping.name2elename(e.class.to_s)
|
||||
@message = e.message
|
||||
@backtrace = e.backtrace
|
||||
@cause = e
|
||||
end
|
||||
|
||||
def to_e
|
||||
if @cause.is_a?(::Exception)
|
||||
@cause.extend(::SOAP::Mapping::MappedException)
|
||||
return @cause
|
||||
end
|
||||
klass = Mapping.class_from_name(
|
||||
Mapping.elename2name(@excn_type_name.to_s))
|
||||
if klass.nil?
|
||||
raise RuntimeError.new(@message)
|
||||
end
|
||||
unless klass <= ::Exception
|
||||
raise NameError.new
|
||||
end
|
||||
obj = klass.new(@message)
|
||||
obj.extend(::SOAP::Mapping::MappedException)
|
||||
obj
|
||||
end
|
||||
|
||||
def set_backtrace(e)
|
||||
e.set_backtrace(
|
||||
if @backtrace.is_a?(Array)
|
||||
@backtrace
|
||||
else
|
||||
[@backtrace.inspect]
|
||||
end
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# For anyType object: SOAP::Mapping::Object not ::Object
|
||||
class Object; include Marshallable
|
||||
def set_property(name, value)
|
||||
var_name = name
|
||||
begin
|
||||
instance_eval <<-EOS
|
||||
def #{ var_name }
|
||||
@#{ var_name }
|
||||
end
|
||||
|
||||
def #{ var_name }=(value)
|
||||
@#{ var_name } = value
|
||||
end
|
||||
EOS
|
||||
self.send(var_name + '=', value)
|
||||
rescue SyntaxError
|
||||
var_name = safe_name(var_name)
|
||||
retry
|
||||
end
|
||||
|
||||
var_name
|
||||
end
|
||||
|
||||
def members
|
||||
instance_variables.collect { |str| str[1..-1] }
|
||||
end
|
||||
|
||||
def [](name)
|
||||
if self.respond_to?(name)
|
||||
self.send(name)
|
||||
else
|
||||
self.send(safe_name(name))
|
||||
end
|
||||
end
|
||||
|
||||
def []=(name, value)
|
||||
if self.respond_to?(name)
|
||||
self.send(name + '=', value)
|
||||
else
|
||||
self.send(safe_name(name) + '=', value)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def safe_name(name)
|
||||
require 'md5'
|
||||
"var_" << MD5.new(name).hexdigest
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class MappingError < Error; end
|
||||
|
||||
|
||||
class Registry
|
||||
class Map
|
||||
def initialize(registry)
|
||||
@map = []
|
||||
@registry = registry
|
||||
end
|
||||
|
||||
def obj2soap(klass, obj)
|
||||
@map.each do |obj_class, soap_class, factory, info|
|
||||
if klass == obj_class or
|
||||
(info[:derived_class] and klass <= obj_class)
|
||||
ret = factory.obj2soap(soap_class, obj, info, @registry)
|
||||
return ret if ret
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def soap2obj(klass, node)
|
||||
@map.each do |obj_class, soap_class, factory, info|
|
||||
if klass == soap_class or
|
||||
(info[:derived_class] and klass <= soap_class)
|
||||
conv, obj = factory.soap2obj(obj_class, node, info, @registry)
|
||||
return true, obj if conv
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
# Give priority to former entry.
|
||||
def init(init_map = [])
|
||||
clear
|
||||
init_map.reverse_each do |obj_class, soap_class, factory, info|
|
||||
add(obj_class, soap_class, factory, info)
|
||||
end
|
||||
end
|
||||
|
||||
# Give priority to latter entry.
|
||||
def add(obj_class, soap_class, factory, info)
|
||||
info ||= {}
|
||||
@map.unshift([obj_class, soap_class, factory, info])
|
||||
end
|
||||
|
||||
def clear
|
||||
@map.clear
|
||||
end
|
||||
|
||||
def find_mapped_soap_class(target_obj_class)
|
||||
@map.each do |obj_class, soap_class, factory, info|
|
||||
if obj_class == target_obj_class
|
||||
return soap_class
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def find_mapped_obj_class(target_soap_class)
|
||||
@map.each do |obj_class, soap_class, factory, info|
|
||||
if soap_class == target_soap_class
|
||||
return obj_class
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
StringFactory = StringFactory_.new
|
||||
BasetypeFactory = BasetypeFactory_.new
|
||||
DateTimeFactory = DateTimeFactory_.new
|
||||
ArrayFactory = ArrayFactory_.new
|
||||
Base64Factory = Base64Factory_.new
|
||||
TypedArrayFactory = TypedArrayFactory_.new
|
||||
TypedStructFactory = TypedStructFactory_.new
|
||||
|
||||
HashFactory = HashFactory_.new
|
||||
|
||||
SOAPBaseMap = [
|
||||
[::NilClass, ::SOAP::SOAPNil, BasetypeFactory],
|
||||
[::TrueClass, ::SOAP::SOAPBoolean, BasetypeFactory],
|
||||
[::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPString, StringFactory],
|
||||
[::DateTime, ::SOAP::SOAPDateTime, BasetypeFactory],
|
||||
[::Date, ::SOAP::SOAPDateTime, BasetypeFactory],
|
||||
[::Date, ::SOAP::SOAPDate, BasetypeFactory],
|
||||
[::Time, ::SOAP::SOAPDateTime, BasetypeFactory],
|
||||
[::Time, ::SOAP::SOAPTime, BasetypeFactory],
|
||||
[::Float, ::SOAP::SOAPDouble, BasetypeFactory,
|
||||
{:derived_class => true}],
|
||||
[::Float, ::SOAP::SOAPFloat, BasetypeFactory,
|
||||
{:derived_class => true}],
|
||||
[::Integer, ::SOAP::SOAPInt, BasetypeFactory,
|
||||
{:derived_class => true}],
|
||||
[::Integer, ::SOAP::SOAPLong, BasetypeFactory,
|
||||
{:derived_class => true}],
|
||||
[::Integer, ::SOAP::SOAPInteger, BasetypeFactory,
|
||||
{:derived_class => true}],
|
||||
[::Integer, ::SOAP::SOAPShort, BasetypeFactory,
|
||||
{:derived_class => true}],
|
||||
[::URI::Generic, ::SOAP::SOAPAnyURI, BasetypeFactory,
|
||||
{:derived_class => true}],
|
||||
[::String, ::SOAP::SOAPBase64, Base64Factory],
|
||||
[::String, ::SOAP::SOAPHexBinary, Base64Factory],
|
||||
[::String, ::SOAP::SOAPDecimal, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPDuration, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPGYearMonth, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPGYear, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPGMonthDay, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPGDay, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPGMonth, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPQName, BasetypeFactory],
|
||||
|
||||
[::Array, ::SOAP::SOAPArray, ArrayFactory,
|
||||
{:derived_class => true}],
|
||||
|
||||
[::Hash, ::SOAP::SOAPStruct, HashFactory],
|
||||
[::SOAP::Mapping::SOAPException,
|
||||
::SOAP::SOAPStruct, TypedStructFactory,
|
||||
{:type => XSD::QName.new(RubyCustomTypeNamespace, "SOAPException")}],
|
||||
]
|
||||
|
||||
RubyOriginalMap = [
|
||||
[::NilClass, ::SOAP::SOAPNil, BasetypeFactory],
|
||||
[::TrueClass, ::SOAP::SOAPBoolean, BasetypeFactory],
|
||||
[::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPString, StringFactory],
|
||||
[::DateTime, ::SOAP::SOAPDateTime, BasetypeFactory],
|
||||
[::Date, ::SOAP::SOAPDateTime, BasetypeFactory],
|
||||
[::Date, ::SOAP::SOAPDate, BasetypeFactory],
|
||||
[::Time, ::SOAP::SOAPDateTime, BasetypeFactory],
|
||||
[::Time, ::SOAP::SOAPTime, BasetypeFactory],
|
||||
[::Float, ::SOAP::SOAPDouble, BasetypeFactory,
|
||||
{:derived_class => true}],
|
||||
[::Float, ::SOAP::SOAPFloat, BasetypeFactory,
|
||||
{:derived_class => true}],
|
||||
[::Integer, ::SOAP::SOAPInt, BasetypeFactory,
|
||||
{:derived_class => true}],
|
||||
[::Integer, ::SOAP::SOAPLong, BasetypeFactory,
|
||||
{:derived_class => true}],
|
||||
[::Integer, ::SOAP::SOAPInteger, BasetypeFactory,
|
||||
{:derived_class => true}],
|
||||
[::Integer, ::SOAP::SOAPShort, BasetypeFactory,
|
||||
{:derived_class => true}],
|
||||
[::URI::Generic, ::SOAP::SOAPAnyURI, BasetypeFactory,
|
||||
{:derived_class => true}],
|
||||
[::String, ::SOAP::SOAPBase64, Base64Factory],
|
||||
[::String, ::SOAP::SOAPHexBinary, Base64Factory],
|
||||
[::String, ::SOAP::SOAPDecimal, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPDuration, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPGYearMonth, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPGYear, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPGMonthDay, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPGDay, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPGMonth, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPQName, BasetypeFactory],
|
||||
|
||||
# Does not allow Array's subclass here.
|
||||
[::Array, ::SOAP::SOAPArray, ArrayFactory],
|
||||
|
||||
[::Hash, ::SOAP::SOAPStruct, HashFactory],
|
||||
[::SOAP::Mapping::SOAPException,
|
||||
::SOAP::SOAPStruct, TypedStructFactory,
|
||||
{:type => XSD::QName.new(RubyCustomTypeNamespace, "SOAPException")}],
|
||||
]
|
||||
|
||||
def initialize(config = {})
|
||||
@config = config
|
||||
@map = Map.new(self)
|
||||
if @config[:allow_original_mapping]
|
||||
allow_original_mapping = true
|
||||
@map.init(RubyOriginalMap)
|
||||
else
|
||||
allow_original_mapping = false
|
||||
@map.init(SOAPBaseMap)
|
||||
end
|
||||
|
||||
allow_untyped_struct = @config.key?(:allow_untyped_struct) ?
|
||||
@config[:allow_untyped_struct] : true
|
||||
@rubytype_factory = RubytypeFactory.new(
|
||||
:allow_untyped_struct => allow_untyped_struct,
|
||||
:allow_original_mapping => allow_original_mapping
|
||||
)
|
||||
@default_factory = @rubytype_factory
|
||||
@excn_handler_obj2soap = nil
|
||||
@excn_handler_soap2obj = nil
|
||||
end
|
||||
|
||||
def add(obj_class, soap_class, factory, info = nil)
|
||||
@map.add(obj_class, soap_class, factory, info)
|
||||
end
|
||||
alias :set :add
|
||||
|
||||
# This mapping registry ignores type hint.
|
||||
def obj2soap(klass, obj, type = nil)
|
||||
ret = nil
|
||||
if obj.is_a?(SOAPStruct) || obj.is_a?(SOAPArray)
|
||||
obj.replace do |ele|
|
||||
Mapping._obj2soap(ele, self)
|
||||
end
|
||||
return obj
|
||||
elsif obj.is_a?(SOAPBasetype)
|
||||
return obj
|
||||
end
|
||||
begin
|
||||
ret = @map.obj2soap(klass, obj) ||
|
||||
@default_factory.obj2soap(klass, obj, nil, self)
|
||||
rescue MappingError
|
||||
end
|
||||
return ret if ret
|
||||
|
||||
if @excn_handler_obj2soap
|
||||
ret = @excn_handler_obj2soap.call(obj) { |yield_obj|
|
||||
Mapping._obj2soap(yield_obj, self)
|
||||
}
|
||||
end
|
||||
return ret if ret
|
||||
|
||||
raise MappingError.new("Cannot map #{ klass.name } to SOAP/OM.")
|
||||
end
|
||||
|
||||
def soap2obj(klass, node)
|
||||
if node.extraattr.key?(RubyTypeName)
|
||||
conv, obj = @rubytype_factory.soap2obj(klass, node, nil, self)
|
||||
return obj if conv
|
||||
else
|
||||
conv, obj = @map.soap2obj(klass, node)
|
||||
return obj if conv
|
||||
conv, obj = @default_factory.soap2obj(klass, node, nil, self)
|
||||
return obj if conv
|
||||
end
|
||||
|
||||
if @excn_handler_soap2obj
|
||||
begin
|
||||
return @excn_handler_soap2obj.call(node) { |yield_node|
|
||||
Mapping._soap2obj(yield_node, self)
|
||||
}
|
||||
rescue Exception
|
||||
end
|
||||
end
|
||||
|
||||
raise MappingError.new("Cannot map #{ node.type.name } to Ruby object.")
|
||||
end
|
||||
|
||||
def default_factory=(factory)
|
||||
@default_factory = factory
|
||||
end
|
||||
|
||||
def excn_handler_obj2soap=(handler)
|
||||
@excn_handler_obj2soap = handler
|
||||
end
|
||||
|
||||
def excn_handler_soap2obj=(handler)
|
||||
@excn_handler_soap2obj = handler
|
||||
end
|
||||
|
||||
def find_mapped_soap_class(obj_class)
|
||||
@map.find_mapped_soap_class(obj_class)
|
||||
end
|
||||
|
||||
def find_mapped_obj_class(soap_class)
|
||||
@map.find_mapped_obj_class(soap_class)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
DefaultRegistry = Registry.new
|
||||
RubyOriginalRegistry = Registry.new(:allow_original_mapping => true)
|
||||
|
||||
|
||||
end
|
||||
end
|
437
lib/soap/mapping/rubytypeFactory.rb
Normal file
437
lib/soap/mapping/rubytypeFactory.rb
Normal file
|
@ -0,0 +1,437 @@
|
|||
=begin
|
||||
SOAP4R - Ruby type mapping factory.
|
||||
Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
module SOAP
|
||||
module Mapping
|
||||
|
||||
|
||||
class RubytypeFactory < Factory
|
||||
TYPE_STRING = 'String'
|
||||
TYPE_ARRAY = 'Array'
|
||||
TYPE_REGEXP = 'Regexp'
|
||||
TYPE_RANGE = 'Range'
|
||||
TYPE_CLASS = 'Class'
|
||||
TYPE_MODULE = 'Module'
|
||||
TYPE_SYMBOL = 'Symbol'
|
||||
TYPE_STRUCT = 'Struct'
|
||||
TYPE_HASH = 'Map'
|
||||
|
||||
def initialize(config = {})
|
||||
@config = config
|
||||
@allow_untyped_struct = @config.key?(:allow_untyped_struct) ?
|
||||
@config[:allow_untyped_struct] : true
|
||||
@allow_original_mapping = @config.key?(:allow_original_mapping) ?
|
||||
@config[:allow_original_mapping] : false
|
||||
end
|
||||
|
||||
def obj2soap(soap_class, obj, info, map)
|
||||
param = nil
|
||||
case obj
|
||||
when String
|
||||
unless @allow_original_mapping
|
||||
return nil
|
||||
end
|
||||
unless XSD::Charset.is_ces(obj, $KCODE)
|
||||
return nil
|
||||
end
|
||||
encoded = XSD::Charset.encoding_conv(obj, $KCODE, XSD::Charset.encoding)
|
||||
param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_STRING))
|
||||
mark_marshalled_obj(obj, param)
|
||||
param.add('string', SOAPString.new(encoded))
|
||||
if obj.class != String
|
||||
param.extraattr[RubyTypeName] = obj.class.name
|
||||
end
|
||||
addiv2soap(param, obj, map)
|
||||
when Array
|
||||
unless @allow_original_mapping
|
||||
return nil
|
||||
end
|
||||
arytype = Mapping.obj2element(obj)
|
||||
if arytype.name
|
||||
arytype.namespace ||= RubyTypeNamespace
|
||||
else
|
||||
arytype = XSD::AnyTypeName
|
||||
end
|
||||
if obj.instance_variables.empty?
|
||||
param = SOAPArray.new(ValueArrayName, 1, arytype)
|
||||
mark_marshalled_obj(obj, param)
|
||||
obj.each do |var|
|
||||
param.add(Mapping._obj2soap(var, map))
|
||||
end
|
||||
else
|
||||
param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_ARRAY))
|
||||
mark_marshalled_obj(obj, param)
|
||||
ary = SOAPArray.new(ValueArrayName, 1, arytype)
|
||||
obj.each do |var|
|
||||
ary.add(Mapping._obj2soap(var, map))
|
||||
end
|
||||
param.add('array', ary)
|
||||
addiv2soap(param, obj, map)
|
||||
end
|
||||
if obj.class != Array
|
||||
param.extraattr[RubyTypeName] = obj.class.name
|
||||
end
|
||||
when Regexp
|
||||
param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_REGEXP))
|
||||
mark_marshalled_obj(obj, param)
|
||||
if obj.class != Regexp
|
||||
param.extraattr[RubyTypeName] = obj.class.name
|
||||
end
|
||||
param.add('source', SOAPBase64.new(obj.source))
|
||||
if obj.respond_to?('options')
|
||||
# Regexp#options is from Ruby/1.7
|
||||
options = obj.options
|
||||
else
|
||||
options = 0
|
||||
obj.inspect.sub(/^.*\//, '').each_byte do |c|
|
||||
options += case c
|
||||
when ?i
|
||||
1
|
||||
when ?x
|
||||
2
|
||||
when ?m
|
||||
4
|
||||
when ?n
|
||||
16
|
||||
when ?e
|
||||
32
|
||||
when ?s
|
||||
48
|
||||
when ?u
|
||||
64
|
||||
end
|
||||
end
|
||||
end
|
||||
param.add('options', SOAPInt.new(options))
|
||||
addiv2soap(param, obj, map)
|
||||
when Range
|
||||
param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_RANGE))
|
||||
mark_marshalled_obj(obj, param)
|
||||
if obj.class != Range
|
||||
param.extraattr[RubyTypeName] = obj.class.name
|
||||
end
|
||||
param.add('begin', Mapping._obj2soap(obj.begin, map))
|
||||
param.add('end', Mapping._obj2soap(obj.end, map))
|
||||
param.add('exclude_end', SOAP::SOAPBoolean.new(obj.exclude_end?))
|
||||
addiv2soap(param, obj, map)
|
||||
when Hash
|
||||
unless @allow_original_mapping
|
||||
return nil
|
||||
end
|
||||
if obj.respond_to?(:default_proc) && obj.default_proc
|
||||
raise TypeError.new("cannot dump hash with default proc")
|
||||
end
|
||||
param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_HASH))
|
||||
mark_marshalled_obj(obj, param)
|
||||
if obj.class != Hash
|
||||
param.extraattr[RubyTypeName] = obj.class.name
|
||||
end
|
||||
obj.each do |key, value|
|
||||
elem = SOAPStruct.new # Undefined type.
|
||||
elem.add("key", Mapping._obj2soap(key, map))
|
||||
elem.add("value", Mapping._obj2soap(value, map))
|
||||
param.add("item", elem)
|
||||
end
|
||||
param.add('default', Mapping._obj2soap(obj.default, map))
|
||||
addiv2soap(param, obj, map)
|
||||
when Class
|
||||
if obj.name.empty?
|
||||
raise TypeError.new("Can't dump anonymous class #{ obj }.")
|
||||
end
|
||||
param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_CLASS))
|
||||
mark_marshalled_obj(obj, param)
|
||||
param.add('name', SOAPString.new(obj.name))
|
||||
addiv2soap(param, obj, map)
|
||||
when Module
|
||||
if obj.name.empty?
|
||||
raise TypeError.new("Can't dump anonymous module #{ obj }.")
|
||||
end
|
||||
param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_MODULE))
|
||||
mark_marshalled_obj(obj, param)
|
||||
param.add('name', SOAPString.new(obj.name))
|
||||
addiv2soap(param, obj, map)
|
||||
when Symbol
|
||||
param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_SYMBOL))
|
||||
mark_marshalled_obj(obj, param)
|
||||
param.add('id', SOAPString.new(obj.id2name))
|
||||
addiv2soap(param, obj, map)
|
||||
when Exception
|
||||
typestr = Mapping.name2elename(obj.class.to_s)
|
||||
param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, typestr))
|
||||
mark_marshalled_obj(obj, param)
|
||||
param.add('message', Mapping._obj2soap(obj.message, map))
|
||||
param.add('backtrace', Mapping._obj2soap(obj.backtrace, map))
|
||||
addiv2soap(param, obj, map)
|
||||
when Struct
|
||||
param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_STRUCT))
|
||||
mark_marshalled_obj(obj, param)
|
||||
param.add('type', ele_type = SOAPString.new(obj.class.to_s))
|
||||
ele_member = SOAPStruct.new
|
||||
obj.members.each do |member|
|
||||
ele_member.add(Mapping.name2elename(member),
|
||||
Mapping._obj2soap(obj[member], map))
|
||||
end
|
||||
param.add('member', ele_member)
|
||||
addiv2soap(param, obj, map)
|
||||
when IO, Binding, Continuation, Data, Dir, File::Stat, MatchData, Method,
|
||||
Proc, Thread, ThreadGroup
|
||||
return nil
|
||||
when ::SOAP::Mapping::Object
|
||||
param = SOAPStruct.new(XSD::AnyTypeName)
|
||||
mark_marshalled_obj(obj, param)
|
||||
setiv2soap(param, obj, map) # addiv2soap?
|
||||
else
|
||||
if obj.class.name.empty?
|
||||
raise TypeError.new("Can't dump anonymous class #{ obj }.")
|
||||
end
|
||||
if check_singleton(obj)
|
||||
raise TypeError.new("singleton can't be dumped #{ obj }")
|
||||
end
|
||||
type = Mapping.class2element(obj.class)
|
||||
param = SOAPStruct.new(type)
|
||||
mark_marshalled_obj(obj, param)
|
||||
if obj.class <= Marshallable
|
||||
setiv2soap(param, obj, map)
|
||||
else
|
||||
setiv2soap(param, obj, map) # Should not be marshalled?
|
||||
end
|
||||
end
|
||||
param
|
||||
end
|
||||
|
||||
def soap2obj(obj_class, node, info, map)
|
||||
rubytype = node.extraattr[RubyTypeName]
|
||||
if rubytype or node.type.namespace == RubyTypeNamespace
|
||||
rubytype2obj(node, map, rubytype)
|
||||
elsif node.type == XSD::AnyTypeName or node.type == XSD::AnySimpleTypeName
|
||||
anytype2obj(node, map)
|
||||
else
|
||||
unknowntype2obj(node, map)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_singleton(obj)
|
||||
unless singleton_methods_true(obj).empty?
|
||||
return true
|
||||
end
|
||||
singleton_class = class << obj; self; end
|
||||
if !singleton_class.instance_variables.empty? or
|
||||
!(singleton_class.ancestors - obj.class.ancestors).empty?
|
||||
return true
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
if RUBY_VERSION >= '1.8.0'
|
||||
def singleton_methods_true(obj)
|
||||
obj.singleton_methods(true)
|
||||
end
|
||||
else
|
||||
def singleton_methods_true(obj)
|
||||
obj.singleton_methods
|
||||
end
|
||||
end
|
||||
|
||||
def rubytype2obj(node, map, rubytype)
|
||||
obj = nil
|
||||
case node.class
|
||||
when SOAPString
|
||||
obj = string2obj(node, map, rubytype)
|
||||
obj.replace(node.data)
|
||||
return true, obj
|
||||
when SOAPArray
|
||||
obj = array2obj(node, map, rubytype)
|
||||
node.soap2array(obj) do |elem|
|
||||
elem ? Mapping._soap2obj(elem, map) : nil
|
||||
end
|
||||
return true, obj
|
||||
end
|
||||
|
||||
case node.type.name
|
||||
when TYPE_STRING
|
||||
obj = string2obj(node, map, rubytype)
|
||||
obj.replace(node['string'].data)
|
||||
setiv2obj(obj, node['ivars'], map)
|
||||
when TYPE_ARRAY
|
||||
obj = array2obj(node, map, rubytype)
|
||||
node['array'].soap2array(obj) do |elem|
|
||||
elem ? Mapping._soap2obj(elem, map) : nil
|
||||
end
|
||||
setiv2obj(obj, node['ivars'], map)
|
||||
when TYPE_REGEXP
|
||||
klass = rubytype ? Mapping.class_from_name(rubytype) : Regexp
|
||||
obj = create_empty_object(klass)
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
source = node['source'].string
|
||||
options = node['options'].data || 0
|
||||
obj.instance_eval { initialize(source, options) }
|
||||
setiv2obj(obj, node['ivars'], map)
|
||||
when TYPE_RANGE
|
||||
klass = rubytype ? Mapping.class_from_name(rubytype) : Range
|
||||
obj = create_empty_object(klass)
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
first = Mapping._soap2obj(node['begin'], map)
|
||||
last = Mapping._soap2obj(node['end'], map)
|
||||
exclude_end = node['exclude_end'].data
|
||||
obj.instance_eval { initialize(first, last, exclude_end) }
|
||||
setiv2obj(obj, node['ivars'], map)
|
||||
when TYPE_HASH
|
||||
unless @allow_original_mapping
|
||||
return false
|
||||
end
|
||||
klass = rubytype ? Mapping.class_from_name(rubytype) : Hash
|
||||
obj = create_empty_object(klass)
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
node.each do |key, value|
|
||||
next unless key == 'item'
|
||||
obj[Mapping._soap2obj(value['key'], map)] =
|
||||
Mapping._soap2obj(value['value'], map)
|
||||
end
|
||||
if node.key?('default')
|
||||
obj.default = Mapping._soap2obj(node['default'], map)
|
||||
end
|
||||
setiv2obj(obj, node['ivars'], map)
|
||||
when TYPE_CLASS
|
||||
obj = Mapping.class_from_name(node['name'].data)
|
||||
setiv2obj(obj, node['ivars'], map)
|
||||
when TYPE_MODULE
|
||||
obj = Mapping.class_from_name(node['name'].data)
|
||||
setiv2obj(obj, node['ivars'], map)
|
||||
when TYPE_SYMBOL
|
||||
obj = node['id'].data.intern
|
||||
setiv2obj(obj, node['ivars'], map)
|
||||
when TYPE_STRUCT
|
||||
typestr = Mapping.elename2name(node['type'].data)
|
||||
klass = Mapping.class_from_name(typestr)
|
||||
if klass.nil?
|
||||
klass = Mapping.class_from_name(name2typename(typestr))
|
||||
end
|
||||
if klass.nil?
|
||||
return false
|
||||
end
|
||||
unless klass <= ::Struct
|
||||
return false
|
||||
end
|
||||
obj = create_empty_object(klass)
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
node['member'].each do |name, value|
|
||||
obj[Mapping.elename2name(name)] =
|
||||
Mapping._soap2obj(value, map)
|
||||
end
|
||||
setiv2obj(obj, node['ivars'], map)
|
||||
else
|
||||
conv, obj = exception2obj(node, map)
|
||||
unless conv
|
||||
return false
|
||||
end
|
||||
setiv2obj(obj, node['ivars'], map)
|
||||
end
|
||||
return true, obj
|
||||
end
|
||||
|
||||
def exception2obj(node, map)
|
||||
typestr = Mapping.elename2name(node.type.name)
|
||||
klass = Mapping.class_from_name(typestr)
|
||||
if klass.nil?
|
||||
return false
|
||||
end
|
||||
unless klass <= Exception
|
||||
return false
|
||||
end
|
||||
message = Mapping._soap2obj(node['message'], map)
|
||||
backtrace = Mapping._soap2obj(node['backtrace'], map)
|
||||
obj = create_empty_object(klass)
|
||||
obj = obj.exception(message)
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
obj.set_backtrace(backtrace)
|
||||
setiv2obj(obj, node['ivars'], map)
|
||||
return true, obj
|
||||
end
|
||||
|
||||
def anytype2obj(node, map)
|
||||
case node
|
||||
when SOAPBasetype
|
||||
return true, node.data
|
||||
when SOAPStruct
|
||||
klass = ::SOAP::Mapping::Object
|
||||
obj = klass.new
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
node.each do |name, value|
|
||||
obj.set_property(name, Mapping._soap2obj(value, map))
|
||||
end
|
||||
return true, obj
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def unknowntype2obj(node, map)
|
||||
if node.is_a?(SOAPStruct)
|
||||
obj = struct2obj(node, map)
|
||||
return true, obj if obj
|
||||
if !@allow_untyped_struct
|
||||
return false
|
||||
end
|
||||
return anytype2obj(node, map)
|
||||
else
|
||||
# Basetype which is not defined...
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def struct2obj(node, map)
|
||||
obj = nil
|
||||
typestr = Mapping.elename2name(node.type.name)
|
||||
klass = Mapping.class_from_name(typestr)
|
||||
if klass.nil?
|
||||
klass = Mapping.class_from_name(name2typename(typestr))
|
||||
end
|
||||
if klass.nil?
|
||||
return nil
|
||||
end
|
||||
klass_type = Mapping.class2qname(klass)
|
||||
return nil unless node.type.match(klass_type)
|
||||
obj = create_empty_object(klass)
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
setiv2obj(obj, node, map)
|
||||
obj
|
||||
end
|
||||
|
||||
# Only creates empty array. Do String#replace it with real string.
|
||||
def array2obj(node, map, rubytype)
|
||||
klass = rubytype ? Mapping.class_from_name(rubytype) : Array
|
||||
obj = create_empty_object(klass)
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
obj
|
||||
end
|
||||
|
||||
# Only creates empty string. Do String#replace it with real string.
|
||||
def string2obj(node, map, rubytype)
|
||||
klass = rubytype ? Mapping.class_from_name(rubytype) : String
|
||||
obj = create_empty_object(klass)
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
obj
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
52
lib/soap/mapping/typeMap.rb
Normal file
52
lib/soap/mapping/typeMap.rb
Normal file
|
@ -0,0 +1,52 @@
|
|||
=begin
|
||||
SOAP4R - Base type mapping definition
|
||||
Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
module SOAP
|
||||
|
||||
|
||||
TypeMap = {
|
||||
XSD::XSDAnySimpleType::Type => SOAPAnySimpleType,
|
||||
XSD::XSDString::Type => SOAPString,
|
||||
XSD::XSDBoolean::Type => SOAPBoolean,
|
||||
XSD::XSDDecimal::Type => SOAPDecimal,
|
||||
XSD::XSDFloat::Type => SOAPFloat,
|
||||
XSD::XSDDouble::Type => SOAPDouble,
|
||||
XSD::XSDDuration::Type => SOAPDuration,
|
||||
XSD::XSDDateTime::Type => SOAPDateTime,
|
||||
XSD::XSDTime::Type => SOAPTime,
|
||||
XSD::XSDDate::Type => SOAPDate,
|
||||
XSD::XSDGYearMonth::Type => SOAPGYearMonth,
|
||||
XSD::XSDGYear::Type => SOAPGYear,
|
||||
XSD::XSDGMonthDay::Type => SOAPGMonthDay,
|
||||
XSD::XSDGDay::Type => SOAPGDay,
|
||||
XSD::XSDGMonth::Type => SOAPGMonth,
|
||||
XSD::XSDHexBinary::Type => SOAPHexBinary,
|
||||
XSD::XSDBase64Binary::Type => SOAPBase64,
|
||||
XSD::XSDAnyURI::Type => SOAPAnyURI,
|
||||
XSD::XSDQName::Type => SOAPQName,
|
||||
XSD::XSDInteger::Type => SOAPInteger,
|
||||
XSD::XSDLong::Type => SOAPLong,
|
||||
XSD::XSDInt::Type => SOAPInt,
|
||||
XSD::XSDShort::Type => SOAPShort,
|
||||
|
||||
SOAP::SOAPBase64::Type => SOAPBase64,
|
||||
}
|
||||
|
||||
|
||||
end
|
146
lib/soap/mapping/wsdlRegistry.rb
Normal file
146
lib/soap/mapping/wsdlRegistry.rb
Normal file
|
@ -0,0 +1,146 @@
|
|||
=begin
|
||||
SOAP4R - WSDL mapping registry.
|
||||
Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'soap/baseData'
|
||||
require 'soap/mapping/mapping'
|
||||
require 'soap/mapping/typeMap'
|
||||
|
||||
|
||||
module SOAP
|
||||
module Mapping
|
||||
|
||||
|
||||
class WSDLRegistry
|
||||
include TraverseSupport
|
||||
|
||||
attr_reader :complextypes
|
||||
|
||||
def initialize(complextypes, config = {})
|
||||
@complextypes = complextypes
|
||||
@config = config
|
||||
@excn_handler_obj2soap = nil
|
||||
# For mapping AnyType element.
|
||||
@rubytype_factory = RubytypeFactory.new(
|
||||
:allow_untyped_struct => true,
|
||||
:allow_original_mapping => true
|
||||
)
|
||||
end
|
||||
|
||||
def obj2soap(klass, obj, type_qname)
|
||||
soap_obj = nil
|
||||
if obj.nil?
|
||||
soap_obj = SOAPNil.new
|
||||
elsif obj.is_a?(XSD::NSDBase)
|
||||
soap_obj = soap2soap(obj, type_qname)
|
||||
elsif (type = @complextypes[type_qname])
|
||||
case type.compoundtype
|
||||
when :TYPE_STRUCT
|
||||
soap_obj = struct2soap(obj, type_qname, type)
|
||||
when :TYPE_ARRAY
|
||||
soap_obj = array2soap(obj, type_qname, type)
|
||||
end
|
||||
elsif (type = TypeMap[type_qname])
|
||||
soap_obj = base2soap(obj, type)
|
||||
elsif type_qname == XSD::AnyTypeName
|
||||
soap_obj = @rubytype_factory.obj2soap(nil, obj, nil, nil)
|
||||
end
|
||||
return soap_obj if soap_obj
|
||||
|
||||
if @excn_handler_obj2soap
|
||||
soap_obj = @excn_handler_obj2soap.call(obj) { |yield_obj|
|
||||
Mapping._obj2soap(yield_obj, self)
|
||||
}
|
||||
end
|
||||
return soap_obj if soap_obj
|
||||
|
||||
raise MappingError.new("Cannot map #{ klass.name } to SOAP/OM.")
|
||||
end
|
||||
|
||||
def soap2obj(klass, node)
|
||||
raise RuntimeError.new("#{ self } is for obj2soap only.")
|
||||
end
|
||||
|
||||
def excn_handler_obj2soap=(handler)
|
||||
@excn_handler_obj2soap = handler
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def soap2soap(obj, type_qname)
|
||||
if obj.is_a?(SOAPBasetype)
|
||||
obj
|
||||
elsif obj.is_a?(SOAPStruct) && (type = @complextypes[type_qname])
|
||||
soap_obj = obj
|
||||
mark_marshalled_obj(obj, soap_obj)
|
||||
elements2soap(obj, soap_obj, type.content.elements)
|
||||
soap_obj
|
||||
elsif obj.is_a?(SOAPArray) && (type = @complextypes[type_qname])
|
||||
soap_obj = obj
|
||||
contenttype = type.child_type
|
||||
mark_marshalled_obj(obj, soap_obj)
|
||||
obj.replace do |ele|
|
||||
Mapping._obj2soap(ele, self, contenttype)
|
||||
end
|
||||
soap_obj
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def base2soap(obj, type)
|
||||
soap_obj = nil
|
||||
if type <= XSD::XSDString
|
||||
soap_obj = type.new(XSD::Charset.is_ces(obj, $KCODE) ?
|
||||
XSD::Charset.encoding_conv(obj, $KCODE, XSD::Charset.encoding) : obj)
|
||||
mark_marshalled_obj(obj, soap_obj)
|
||||
else
|
||||
soap_obj = type.new(obj)
|
||||
end
|
||||
soap_obj
|
||||
end
|
||||
|
||||
def struct2soap(obj, type_qname, type)
|
||||
soap_obj = SOAPStruct.new(type_qname)
|
||||
mark_marshalled_obj(obj, soap_obj)
|
||||
elements2soap(obj, soap_obj, type.content.elements)
|
||||
soap_obj
|
||||
end
|
||||
|
||||
def array2soap(obj, type_qname, type)
|
||||
contenttype = type.child_type
|
||||
soap_obj = SOAPArray.new(ValueArrayName, 1, contenttype)
|
||||
mark_marshalled_obj(obj, soap_obj)
|
||||
obj.each do |item|
|
||||
soap_obj.add(Mapping._obj2soap(item, self, contenttype))
|
||||
end
|
||||
soap_obj
|
||||
end
|
||||
|
||||
def elements2soap(obj, soap_obj, elements)
|
||||
elements.each do |element|
|
||||
name = element.name.name
|
||||
child_obj = obj.instance_eval("@#{ name }")
|
||||
soap_obj.add(name, Mapping._obj2soap(child_obj, self, element.type))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
71
lib/soap/marshal.rb
Normal file
71
lib/soap/marshal.rb
Normal file
|
@ -0,0 +1,71 @@
|
|||
=begin
|
||||
SOAP4R - Marshalling/Unmarshalling Ruby's object using SOAP Encoding.
|
||||
Copyright (C) 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
# The original version of the marshal.rb to marshal/unmarshal Ruby's object
|
||||
# using SOAP Encoding was written by Michael Neumann. His valuable comments
|
||||
# and his program inspired me to write this. Thanks.
|
||||
|
||||
|
||||
require "soap/mapping"
|
||||
require "soap/processor"
|
||||
|
||||
|
||||
module SOAP
|
||||
|
||||
|
||||
module Marshal
|
||||
# Trying xsd:dateTime data to be recovered as aTime. aDateTime if it fails.
|
||||
MarshalMappingRegistry = Mapping::Registry.new(:allow_original_mapping => true)
|
||||
MarshalMappingRegistry.add(
|
||||
Time,
|
||||
::SOAP::SOAPDateTime,
|
||||
::SOAP::Mapping::Registry::DateTimeFactory
|
||||
)
|
||||
|
||||
class << self
|
||||
public
|
||||
def dump(obj, io = nil)
|
||||
marshal(obj, MarshalMappingRegistry, io)
|
||||
end
|
||||
|
||||
def load(stream)
|
||||
unmarshal(stream, MarshalMappingRegistry)
|
||||
end
|
||||
|
||||
def marshal(obj, mapping_registry = MarshalMappingRegistry, io = nil)
|
||||
elename = Mapping.name2elename(obj.class.to_s)
|
||||
soap_obj = Mapping.obj2soap(obj, mapping_registry)
|
||||
body = SOAPBody.new
|
||||
body.add(elename, soap_obj)
|
||||
SOAP::Processor.marshal(nil, body, {}, io)
|
||||
end
|
||||
|
||||
def unmarshal(stream, mapping_registry = MarshalMappingRegistry)
|
||||
header, body = SOAP::Processor.unmarshal(stream)
|
||||
Mapping.soap2obj(body.root_node, mapping_registry)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
SOAPMarshal = SOAP::Marshal
|
101
lib/soap/netHttpClient.rb
Normal file
101
lib/soap/netHttpClient.rb
Normal file
|
@ -0,0 +1,101 @@
|
|||
=begin
|
||||
SOAP4R - net/http wrapper
|
||||
Copyright (C) 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'net/http'
|
||||
|
||||
|
||||
module SOAP
|
||||
|
||||
|
||||
class NetHttpClient
|
||||
|
||||
attr_accessor :proxy
|
||||
attr_accessor :debug_dev
|
||||
attr_reader :session_manager
|
||||
|
||||
class SessionManager
|
||||
attr_accessor :connect_timeout
|
||||
attr_accessor :send_timeout
|
||||
attr_accessor :receive_timeout
|
||||
end
|
||||
|
||||
class Response
|
||||
attr_reader :content
|
||||
attr_reader :status
|
||||
attr_reader :reason
|
||||
attr_reader :contenttype
|
||||
|
||||
def initialize(res)
|
||||
@status = res.code.to_i
|
||||
@reason = res.message
|
||||
@contenttype = res['content-type']
|
||||
@content = res.body
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(proxy = nil, agent = nil)
|
||||
@proxy = proxy ? URI.parse(proxy) : nil
|
||||
@agent = agent
|
||||
@debug_dev = nil
|
||||
@session_manager = SessionManager.new
|
||||
end
|
||||
|
||||
def reset(url)
|
||||
# ignored.
|
||||
end
|
||||
|
||||
def post(url, req_body, header = {})
|
||||
url = URI.parse(url)
|
||||
extra = header.dup
|
||||
extra['User-Agent'] = @agent if @agent
|
||||
res = start(url) { |http|
|
||||
http.post(url.instance_eval('path_query'), req_body, extra)
|
||||
}
|
||||
Response.new(res)
|
||||
end
|
||||
|
||||
def get_content(url, header = {})
|
||||
url = URI.parse(url)
|
||||
extra = header.dup
|
||||
extra['User-Agent'] = @agent if @agent
|
||||
res = start(url) { |http|
|
||||
http.get(url.instance_eval('path_query'), extra)
|
||||
}
|
||||
res.body
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def start(url)
|
||||
proxy_host = @proxy ? @proxy.host : nil
|
||||
proxy_port = @proxy ? @proxy.port : nil
|
||||
response = nil
|
||||
Net::HTTP::Proxy(proxy_host, proxy_port).start(url.host, url.port) { |http|
|
||||
if http.respond_to?(:set_debug_output)
|
||||
http.set_debug_output(@debug_dev)
|
||||
end
|
||||
response, = yield(http)
|
||||
http.finish
|
||||
}
|
||||
response
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
252
lib/soap/parser.rb
Normal file
252
lib/soap/parser.rb
Normal file
|
@ -0,0 +1,252 @@
|
|||
=begin
|
||||
SOAP4R - SOAP XML Instance Parser library.
|
||||
Copyright (C) 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/ns'
|
||||
require 'xsd/xmlparser'
|
||||
require 'soap/soap'
|
||||
require 'soap/baseData'
|
||||
require 'soap/encodingstyle/handler'
|
||||
|
||||
|
||||
module SOAP
|
||||
|
||||
|
||||
class Parser
|
||||
include SOAP
|
||||
|
||||
class ParseError < Error; end
|
||||
class FormatDecodeError < ParseError; end
|
||||
class UnexpectedElementError < ParseError; end
|
||||
|
||||
private
|
||||
|
||||
class ParseFrame
|
||||
attr_reader :node
|
||||
attr_reader :name
|
||||
attr_reader :ns, :encodingstyle
|
||||
|
||||
class NodeContainer
|
||||
def initialize(node)
|
||||
@node = node
|
||||
end
|
||||
|
||||
def node
|
||||
@node
|
||||
end
|
||||
|
||||
def replace_node(node)
|
||||
@node = node
|
||||
end
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
def initialize(ns, name, node, encodingstyle)
|
||||
@ns = ns
|
||||
@name = name
|
||||
self.node = node
|
||||
@encodingstyle = encodingstyle
|
||||
end
|
||||
|
||||
def node=(node)
|
||||
@node = NodeContainer.new(node)
|
||||
end
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
attr_accessor :default_encodingstyle
|
||||
attr_accessor :decode_typemap
|
||||
attr_accessor :allow_unqualified_element
|
||||
|
||||
def initialize(opt = {})
|
||||
@parser = XSD::XMLParser.create_parser(self, opt)
|
||||
@parsestack = nil
|
||||
@lastnode = nil
|
||||
@handlers = {}
|
||||
@default_encodingstyle = opt[:default_encodingstyle] || EncodingNamespace
|
||||
@decode_typemap = opt[:decode_typemap] || nil
|
||||
@allow_unqualified_element = opt[:allow_unqualified_element] || false
|
||||
end
|
||||
|
||||
def charset
|
||||
@parser.charset
|
||||
end
|
||||
|
||||
def parse(string_or_readable)
|
||||
@parsestack = []
|
||||
@lastnode = nil
|
||||
|
||||
@handlers.each do |uri, handler|
|
||||
handler.decode_prologue
|
||||
end
|
||||
|
||||
@parser.do_parse(string_or_readable)
|
||||
|
||||
unless @parsestack.empty?
|
||||
raise FormatDecodeError.new("Unbalanced tag in XML.")
|
||||
end
|
||||
|
||||
@handlers.each do |uri, handler|
|
||||
handler.decode_epilogue
|
||||
end
|
||||
|
||||
@lastnode
|
||||
end
|
||||
|
||||
def start_element(name, attrs)
|
||||
lastframe = @parsestack.last
|
||||
ns = parent = parent_encodingstyle = nil
|
||||
if lastframe
|
||||
ns = lastframe.ns.clone_ns
|
||||
parent = lastframe.node
|
||||
parent_encodingstyle = lastframe.encodingstyle
|
||||
else
|
||||
ns = XSD::NS.new
|
||||
parent = ParseFrame::NodeContainer.new(nil)
|
||||
parent_encodingstyle = nil
|
||||
end
|
||||
|
||||
attrs = XSD::XMLParser.filter_ns(ns, attrs)
|
||||
encodingstyle = find_encodingstyle(ns, attrs)
|
||||
|
||||
# Children's encodingstyle is derived from its parent.
|
||||
encodingstyle ||= parent_encodingstyle || @default_encodingstyle
|
||||
|
||||
node = decode_tag(ns, name, attrs, parent, encodingstyle)
|
||||
|
||||
@parsestack << ParseFrame.new(ns, name, node, encodingstyle)
|
||||
end
|
||||
|
||||
def characters(text)
|
||||
lastframe = @parsestack.last
|
||||
if lastframe
|
||||
# Need not to be cloned because character does not have attr.
|
||||
ns = lastframe.ns
|
||||
parent = lastframe.node
|
||||
encodingstyle = lastframe.encodingstyle
|
||||
decode_text(ns, text, encodingstyle)
|
||||
else
|
||||
# Ignore Text outside of SOAP Envelope.
|
||||
p text if $DEBUG
|
||||
end
|
||||
end
|
||||
|
||||
def end_element(name)
|
||||
lastframe = @parsestack.pop
|
||||
unless name == lastframe.name
|
||||
raise UnexpectedElementError.new("Closing element name '#{ name }' does not match with opening element '#{ lastframe.name }'.")
|
||||
end
|
||||
decode_tag_end(lastframe.ns, lastframe.node, lastframe.encodingstyle)
|
||||
@lastnode = lastframe.node.node
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_encodingstyle(ns, attrs)
|
||||
attrs.each do |key, value|
|
||||
if (ns.compare(EnvelopeNamespace, AttrEncodingStyle, key))
|
||||
return value
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def decode_tag(ns, name, attrs, parent, encodingstyle)
|
||||
ele = ns.parse(name)
|
||||
|
||||
# Envelope based parsing.
|
||||
if ((ele.namespace == EnvelopeNamespace) ||
|
||||
(@allow_unqualified_element && ele.namespace.nil?))
|
||||
o = decode_soap_envelope(ns, ele, attrs, parent)
|
||||
return o if o
|
||||
end
|
||||
|
||||
# Encoding based parsing.
|
||||
handler = find_handler(encodingstyle)
|
||||
if handler
|
||||
return handler.decode_tag(ns, ele, attrs, parent)
|
||||
else
|
||||
raise FormatDecodeError.new("Unknown encodingStyle: #{ encodingstyle }.")
|
||||
end
|
||||
end
|
||||
|
||||
def decode_tag_end(ns, node, encodingstyle)
|
||||
return unless encodingstyle
|
||||
|
||||
handler = find_handler(encodingstyle)
|
||||
if handler
|
||||
return handler.decode_tag_end(ns, node)
|
||||
else
|
||||
raise FormatDecodeError.new("Unknown encodingStyle: #{ encodingstyle }.")
|
||||
end
|
||||
end
|
||||
|
||||
def decode_text(ns, text, encodingstyle)
|
||||
handler = find_handler(encodingstyle)
|
||||
|
||||
if handler
|
||||
handler.decode_text(ns, text)
|
||||
else
|
||||
# How should I do?
|
||||
end
|
||||
end
|
||||
|
||||
def decode_soap_envelope(ns, ele, attrs, parent)
|
||||
o = nil
|
||||
if ele.name == EleEnvelope
|
||||
o = SOAPEnvelope.new
|
||||
elsif ele.name == EleHeader
|
||||
unless parent.node.is_a?(SOAPEnvelope)
|
||||
raise FormatDecodeError.new("Header should be a child of Envelope.")
|
||||
end
|
||||
o = SOAPHeader.new
|
||||
parent.node.header = o
|
||||
elsif ele.name == EleBody
|
||||
unless parent.node.is_a?(SOAPEnvelope)
|
||||
raise FormatDecodeError.new("Body should be a child of Envelope.")
|
||||
end
|
||||
o = SOAPBody.new
|
||||
parent.node.body = o
|
||||
elsif ele.name == EleFault
|
||||
unless parent.node.is_a?(SOAPBody)
|
||||
raise FormatDecodeError.new("Fault should be a child of Body.")
|
||||
end
|
||||
o = SOAPFault.new
|
||||
parent.node.fault = o
|
||||
end
|
||||
o.parent = parent if o
|
||||
o
|
||||
end
|
||||
|
||||
def find_handler(encodingstyle)
|
||||
unless @handlers.key?(encodingstyle)
|
||||
handler_factory = SOAP::EncodingStyle::Handler.handler(encodingstyle) ||
|
||||
SOAP::EncodingStyle::Handler.handler(EncodingNamespace)
|
||||
handler = handler_factory.new(@parser.charset)
|
||||
handler.decode_typemap = @decode_typemap
|
||||
handler.decode_prologue
|
||||
@handlers[encodingstyle] = handler
|
||||
end
|
||||
@handlers[encodingstyle]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
79
lib/soap/processor.rb
Normal file
79
lib/soap/processor.rb
Normal file
|
@ -0,0 +1,79 @@
|
|||
=begin
|
||||
SOAP4R - marshal/unmarshal interface.
|
||||
Copyright (C) 2000, 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/datatypes'
|
||||
require 'soap/soap'
|
||||
require 'soap/element'
|
||||
require 'soap/parser'
|
||||
require 'soap/generator'
|
||||
require 'soap/encodingstyle/soapHandler'
|
||||
require 'soap/encodingstyle/literalHandler'
|
||||
require 'soap/encodingstyle/aspDotNetHandler'
|
||||
|
||||
|
||||
module SOAP
|
||||
|
||||
|
||||
module Processor
|
||||
@@default_parser_option = {}
|
||||
|
||||
class << self
|
||||
public
|
||||
|
||||
def marshal(header, body, opt = {}, io = nil)
|
||||
env = SOAPEnvelope.new(header, body)
|
||||
generator = create_generator(opt)
|
||||
generator.generate(env, io)
|
||||
end
|
||||
|
||||
def unmarshal(stream, opt = {})
|
||||
parser = create_parser(opt)
|
||||
env = parser.parse(stream)
|
||||
if env
|
||||
return env.header, env.body
|
||||
else
|
||||
return nil, nil
|
||||
end
|
||||
end
|
||||
|
||||
def default_parser_option=(rhs)
|
||||
@@default_parser_option = rhs
|
||||
end
|
||||
|
||||
def default_parser_option
|
||||
@@default_parser_option
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_generator(opt)
|
||||
SOAPGenerator.new(opt)
|
||||
end
|
||||
|
||||
def create_parser(opt)
|
||||
if opt.empty?
|
||||
opt = @@default_parser_option
|
||||
end
|
||||
::SOAP::Parser.new(opt)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
214
lib/soap/rpc/cgistub.rb
Normal file
214
lib/soap/rpc/cgistub.rb
Normal file
|
@ -0,0 +1,214 @@
|
|||
=begin
|
||||
SOAP4R - CGI stub library
|
||||
Copyright (C) 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'soap/streamHandler'
|
||||
require 'webrick/httpresponse'
|
||||
require 'webrick/httpstatus'
|
||||
require 'logger'
|
||||
require 'soap/rpc/router'
|
||||
|
||||
|
||||
module SOAP
|
||||
module RPC
|
||||
|
||||
|
||||
###
|
||||
# SYNOPSIS
|
||||
# CGIStub.new
|
||||
#
|
||||
# DESCRIPTION
|
||||
# To be written...
|
||||
#
|
||||
class CGIStub < Logger::Application
|
||||
include SOAP
|
||||
|
||||
# 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
|
||||
ALLOWED_LENGTH = 1024 * 1024
|
||||
|
||||
def initialize(stream = $stdin)
|
||||
@method = ENV['REQUEST_METHOD']
|
||||
@size = ENV['CONTENT_LENGTH'].to_i || 0
|
||||
@contenttype = ENV['CONTENT_TYPE']
|
||||
@charset = nil
|
||||
@soapaction = ENV['HTTP_SOAPAction']
|
||||
@source = stream
|
||||
@body = nil
|
||||
end
|
||||
|
||||
def init
|
||||
validate
|
||||
@charset = StreamHandler.parse_media_type(@contenttype)
|
||||
@body = @source.read(@size)
|
||||
self
|
||||
end
|
||||
|
||||
def dump
|
||||
@body.dup
|
||||
end
|
||||
|
||||
def soapaction
|
||||
@soapaction
|
||||
end
|
||||
|
||||
def charset
|
||||
@charset
|
||||
end
|
||||
|
||||
def to_s
|
||||
"method: #{ @method }, size: #{ @size }"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate # raise CGIError
|
||||
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
|
||||
|
||||
def initialize(appname, default_namespace)
|
||||
super(appname)
|
||||
set_log(STDERR)
|
||||
self.level = INFO
|
||||
@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'
|
||||
@request = nil
|
||||
@response = nil
|
||||
@mediatype = MediaType
|
||||
on_init
|
||||
end
|
||||
|
||||
def add_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
|
||||
|
||||
def on_init
|
||||
# Override this method in derived class to call 'add_method' to add methods.
|
||||
end
|
||||
|
||||
def mapping_registry
|
||||
@router.mapping_registry
|
||||
end
|
||||
|
||||
def mapping_registry=(value)
|
||||
@router.mapping_registry = value
|
||||
end
|
||||
|
||||
def add_method(receiver, name, *param)
|
||||
add_method_with_namespace_as(@default_namespace, receiver,
|
||||
name, name, *param)
|
||||
end
|
||||
|
||||
def add_method_as(receiver, name, name_as, *param)
|
||||
add_method_with_namespace_as(@default_namespace, receiver,
|
||||
name, name_as, *param)
|
||||
end
|
||||
|
||||
def add_method_with_namespace(namespace, receiver, name, *param)
|
||||
add_method_with_namespace_as(namespace, receiver, name, name, *param)
|
||||
end
|
||||
|
||||
def add_method_with_namespace_as(namespace, receiver, name, name_as, *param)
|
||||
param_def = if param.size == 1 and param[0].is_a?(Array)
|
||||
param[0]
|
||||
else
|
||||
SOAP::RPC::SOAPMethod.create_param_def(param)
|
||||
end
|
||||
qname = XSD::QName.new(namespace, name_as)
|
||||
@router.add_method(receiver, qname, nil, name, param_def)
|
||||
end
|
||||
|
||||
def route(request_string, charset)
|
||||
@router.route(request_string, charset)
|
||||
end
|
||||
|
||||
def create_fault_response(e)
|
||||
@router.create_fault_response(e)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def run
|
||||
prologue
|
||||
|
||||
httpversion = WEBrick::HTTPVersion.new('1.0')
|
||||
@response = WEBrick::HTTPResponse.new({:HTTPVersion => httpversion})
|
||||
begin
|
||||
log(INFO) { "Received a request from '#{ @remote_user }@#{ @remote_host }'." }
|
||||
# SOAP request parsing.
|
||||
@request = SOAPRequest.new.init
|
||||
req_charset = @request.charset
|
||||
req_string = @request.dump
|
||||
log(DEBUG) { "XML Request: #{req_string}" }
|
||||
res_string, is_fault = route(req_string, req_charset)
|
||||
log(DEBUG) { "XML Response: #{res_string}" }
|
||||
|
||||
@response['Cache-Control'] = 'private'
|
||||
if req_charset
|
||||
@response['content-type'] = "#{@mediatype}; charset=\"#{req_charset}\""
|
||||
else
|
||||
@response['content-type'] = @mediatype
|
||||
end
|
||||
if is_fault
|
||||
@response.status = WEBrick::HTTPStatus::RC_INTERNAL_SERVER_ERROR
|
||||
end
|
||||
@response.body = res_string
|
||||
rescue Exception
|
||||
res_string = create_fault_response($!)
|
||||
@response['Cache-Control'] = 'private'
|
||||
@response['content-type'] = @mediatype
|
||||
@response.status = WEBrick::HTTPStatus::RC_INTERNAL_SERVER_ERROR
|
||||
ensure
|
||||
buf = ''
|
||||
@response.send_response(buf)
|
||||
buf.sub!(/^[^\r]+\r\n/, '') # Trim status line.
|
||||
log(DEBUG) { "SOAP CGI Response:\n#{ buf }" }
|
||||
print buf
|
||||
epilogue
|
||||
end
|
||||
|
||||
0
|
||||
end
|
||||
|
||||
def prologue; end
|
||||
def epilogue; end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
189
lib/soap/rpc/driver.rb
Normal file
189
lib/soap/rpc/driver.rb
Normal file
|
@ -0,0 +1,189 @@
|
|||
=begin
|
||||
SOAP4R - SOAP RPC driver
|
||||
Copyright (C) 2000, 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'soap/soap'
|
||||
require 'soap/mapping'
|
||||
require 'soap/rpc/rpc'
|
||||
require 'soap/rpc/proxy'
|
||||
require 'soap/rpc/element'
|
||||
require 'soap/streamHandler'
|
||||
|
||||
|
||||
module SOAP
|
||||
module RPC
|
||||
|
||||
|
||||
class Driver
|
||||
public
|
||||
class EmptyResponseError < Error; end
|
||||
|
||||
attr_accessor :mapping_registry
|
||||
attr_accessor :soapaction
|
||||
attr_reader :endpoint_url
|
||||
attr_reader :wiredump_dev
|
||||
attr_reader :wiredump_file_base
|
||||
attr_reader :httpproxy
|
||||
|
||||
def initialize(endpoint_url, namespace, soapaction = nil)
|
||||
@endpoint_url = endpoint_url
|
||||
@namespace = namespace
|
||||
@mapping_registry = nil # for unmarshal
|
||||
@soapaction = soapaction
|
||||
@wiredump_dev = nil
|
||||
@wiredump_file_base = nil
|
||||
@httpproxy = ENV['httpproxy'] || ENV['HTTP_PROXY']
|
||||
@handler = HTTPPostStreamHandler.new(@endpoint_url, @httpproxy,
|
||||
XSD::Charset.encoding_label)
|
||||
@proxy = Proxy.new(@handler, @soapaction)
|
||||
@proxy.allow_unqualified_element = true
|
||||
end
|
||||
|
||||
def endpoint_url=(endpoint_url)
|
||||
@endpoint_url = endpoint_url
|
||||
if @handler
|
||||
@handler.endpoint_url = @endpoint_url
|
||||
@handler.reset
|
||||
end
|
||||
end
|
||||
|
||||
def wiredump_dev=(dev)
|
||||
@wiredump_dev = dev
|
||||
if @handler
|
||||
@handler.wiredump_dev = @wiredump_dev
|
||||
@handler.reset
|
||||
end
|
||||
end
|
||||
|
||||
def wiredump_file_base=(base)
|
||||
@wiredump_file_base = base
|
||||
end
|
||||
|
||||
def httpproxy=(httpproxy)
|
||||
@httpproxy = httpproxy
|
||||
if @handler
|
||||
@handler.proxy = @httpproxy
|
||||
@handler.reset
|
||||
end
|
||||
end
|
||||
|
||||
def default_encodingstyle
|
||||
@proxy.default_encodingstyle
|
||||
end
|
||||
|
||||
def default_encodingstyle=(encodingstyle)
|
||||
@proxy.default_encodingstyle = encodingstyle
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
## Method definition interfaces.
|
||||
#
|
||||
# params: [[param_def...]] or [paramname, paramname, ...]
|
||||
# param_def: See proxy.rb. Sorry.
|
||||
|
||||
def add_method(name, *params)
|
||||
add_method_with_soapaction_as(name, name, @soapaction, *params)
|
||||
end
|
||||
|
||||
def add_method_as(name, name_as, *params)
|
||||
add_method_with_soapaction_as(name, name_as, @soapaction, *params)
|
||||
end
|
||||
|
||||
def add_method_with_soapaction(name, soapaction, *params)
|
||||
add_method_with_soapaction_as(name, name, soapaction, *params)
|
||||
end
|
||||
|
||||
def add_method_with_soapaction_as(name, name_as, soapaction, *params)
|
||||
param_def = if params.size == 1 and params[0].is_a?(Array)
|
||||
params[0]
|
||||
else
|
||||
SOAPMethod.create_param_def(params)
|
||||
end
|
||||
qname = XSD::QName.new(@namespace, name_as)
|
||||
@proxy.add_method(qname, soapaction, name, param_def)
|
||||
add_rpc_method_interface(name, param_def)
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
## Driving interface.
|
||||
#
|
||||
def invoke(headers, body)
|
||||
if @wiredump_file_base
|
||||
@handler.wiredump_file_base =
|
||||
@wiredump_file_base + '_' << body.elename.name
|
||||
end
|
||||
@proxy.invoke(headers, body)
|
||||
end
|
||||
|
||||
def call(name, *params)
|
||||
# Convert parameters: params array => SOAPArray => members array
|
||||
params = Mapping.obj2soap(params, @mapping_registry).to_a
|
||||
if @wiredump_file_base
|
||||
@handler.wiredump_file_base = @wiredump_file_base + '_' << name
|
||||
end
|
||||
|
||||
# Then, call @proxy.call like the following.
|
||||
header, body = @proxy.call(nil, name, *params)
|
||||
unless body
|
||||
raise EmptyResponseError.new("Empty response.")
|
||||
end
|
||||
|
||||
begin
|
||||
@proxy.check_fault(body)
|
||||
rescue SOAP::FaultError => e
|
||||
Mapping.fault2exception(e)
|
||||
end
|
||||
|
||||
ret = body.response ? Mapping.soap2obj(body.response, @mapping_registry) : nil
|
||||
if body.outparams
|
||||
outparams = body.outparams.collect { |outparam| Mapping.soap2obj(outparam) }
|
||||
return [ret].concat(outparams)
|
||||
else
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
def reset_stream
|
||||
@handler.reset
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_rpc_method_interface(name, param_def)
|
||||
param_names = []
|
||||
i = 0
|
||||
@proxy.method[name].each_param_name(RPC::SOAPMethod::IN,
|
||||
RPC::SOAPMethod::INOUT) do |param_name|
|
||||
i += 1
|
||||
param_names << "arg#{ i }"
|
||||
end
|
||||
|
||||
callparam = (param_names.collect { |pname| ", " + pname }).join
|
||||
self.instance_eval <<-EOS
|
||||
def #{ name }(#{ param_names.join(", ") })
|
||||
call("#{ name }"#{ callparam })
|
||||
end
|
||||
EOS
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
278
lib/soap/rpc/element.rb
Normal file
278
lib/soap/rpc/element.rb
Normal file
|
@ -0,0 +1,278 @@
|
|||
=begin
|
||||
SOAP4R - RPC element definition.
|
||||
Copyright (C) 2000, 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'soap/baseData'
|
||||
|
||||
|
||||
module SOAP
|
||||
|
||||
# Add method definitions for RPC to common definition in element.rb
|
||||
class SOAPBody < SOAPStruct
|
||||
public
|
||||
|
||||
def request
|
||||
root_node
|
||||
end
|
||||
|
||||
def response
|
||||
if !@is_fault
|
||||
if void?
|
||||
nil
|
||||
else
|
||||
# Initial element is [retval].
|
||||
root_node[0]
|
||||
end
|
||||
else
|
||||
root_node
|
||||
end
|
||||
end
|
||||
|
||||
def outparams
|
||||
if !@is_fault and !void?
|
||||
op = root_node[1..-1]
|
||||
op = nil if op && op.empty?
|
||||
op
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def void?
|
||||
root_node.nil? # || root_node.is_a?(SOAPNil)
|
||||
end
|
||||
|
||||
def fault
|
||||
if @is_fault
|
||||
self['fault']
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def fault=(fault)
|
||||
@is_fault = true
|
||||
add_member('fault', fault)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module RPC
|
||||
|
||||
|
||||
class RPCError < Error; end
|
||||
class MethodDefinitionError < RPCError; end
|
||||
class ParameterError < RPCError; end
|
||||
|
||||
class SOAPMethod < SOAPStruct
|
||||
RETVAL = 'retval'
|
||||
IN = 'in'
|
||||
OUT = 'out'
|
||||
INOUT = 'inout'
|
||||
|
||||
attr_reader :param_def
|
||||
attr_reader :inparam
|
||||
attr_reader :outparam
|
||||
|
||||
def initialize(qname, param_def = nil)
|
||||
super(nil)
|
||||
@elename = qname
|
||||
@encodingstyle = nil
|
||||
|
||||
@param_def = param_def
|
||||
|
||||
@signature = []
|
||||
@inparam_names = []
|
||||
@inoutparam_names = []
|
||||
@outparam_names = []
|
||||
|
||||
@inparam = {}
|
||||
@outparam = {}
|
||||
@retval_name = nil
|
||||
|
||||
init_param(@param_def) if @param_def
|
||||
end
|
||||
|
||||
def have_outparam?
|
||||
@outparam_names.size > 0
|
||||
end
|
||||
|
||||
def each_param_name(*type)
|
||||
@signature.each do |io_type, name, param_type|
|
||||
if type.include?(io_type)
|
||||
yield(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def set_param(params)
|
||||
params.each do |param, data|
|
||||
@inparam[param] = data
|
||||
data.elename.name = param
|
||||
end
|
||||
end
|
||||
|
||||
def set_outparam(params)
|
||||
params.each do |param, data|
|
||||
@outparam[param] = data
|
||||
data.elename.name = param
|
||||
end
|
||||
end
|
||||
|
||||
def SOAPMethod.create_param_def(param_names)
|
||||
param_def = []
|
||||
param_names.each do |param_name|
|
||||
param_def.push([IN, param_name, nil])
|
||||
end
|
||||
param_def.push([RETVAL, 'return', nil])
|
||||
param_def
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init_param(param_def)
|
||||
param_def.each do |io_type, name, param_type|
|
||||
case io_type
|
||||
when IN
|
||||
@signature.push([IN, name, param_type])
|
||||
@inparam_names.push(name)
|
||||
when OUT
|
||||
@signature.push([OUT, name, param_type])
|
||||
@outparam_names.push(name)
|
||||
when INOUT
|
||||
@signature.push([INOUT, name, param_type])
|
||||
@inoutparam_names.push(name)
|
||||
when RETVAL
|
||||
if (@retval_name)
|
||||
raise MethodDefinitionError.new('Duplicated retval')
|
||||
end
|
||||
@retval_name = name
|
||||
else
|
||||
raise MethodDefinitionError.new("Unknown type: #{ io_type }")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class SOAPMethodRequest < SOAPMethod
|
||||
attr_accessor :soapaction
|
||||
|
||||
def SOAPMethodRequest.create_request(qname, *params)
|
||||
param_def = []
|
||||
param_value = []
|
||||
i = 0
|
||||
params.each do |param|
|
||||
param_name = "p#{ i }"
|
||||
i += 1
|
||||
param_def << [IN, nil, param_name]
|
||||
param_value << [param_name, param]
|
||||
end
|
||||
param_def << [RETVAL, nil, 'return']
|
||||
o = new(qname, param_def)
|
||||
o.set_param(param_value)
|
||||
o
|
||||
end
|
||||
|
||||
def initialize(qname, param_def = nil, soapaction = nil)
|
||||
check_elename(qname)
|
||||
super(qname, param_def)
|
||||
@soapaction = soapaction
|
||||
end
|
||||
|
||||
def each
|
||||
each_param_name(IN, INOUT) do |name|
|
||||
unless @inparam[name]
|
||||
raise ParameterError.new("Parameter: #{ name } was not given.")
|
||||
end
|
||||
yield(name, @inparam[name])
|
||||
end
|
||||
end
|
||||
|
||||
def dup
|
||||
req = self.class.new(@elename.dup, @param_def, @soapaction)
|
||||
req.encodingstyle = @encodingstyle
|
||||
req
|
||||
end
|
||||
|
||||
def create_method_response
|
||||
SOAPMethodResponse.new(
|
||||
XSD::QName.new(@elename.namespace, @elename.name + 'Response'),
|
||||
@param_def)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_elename(qname)
|
||||
# NCName & ruby's method name
|
||||
unless /\A[\w_][\w\d_\-]*\z/ =~ qname.name
|
||||
raise MethodDefinitionError.new("Element name '#{qname.name}' not allowed")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class SOAPMethodResponse < SOAPMethod
|
||||
|
||||
def initialize(qname, param_def = nil)
|
||||
super(qname, param_def)
|
||||
@retval = nil
|
||||
end
|
||||
|
||||
def retval=(retval)
|
||||
@retval = retval
|
||||
@retval.elename = @retval.elename.dup_name('return')
|
||||
end
|
||||
|
||||
def each
|
||||
if @retval_name and !@retval.is_a?(SOAPVoid)
|
||||
yield(@retval_name, @retval)
|
||||
end
|
||||
|
||||
each_param_name(OUT, INOUT) do |param_name|
|
||||
unless @outparam[param_name]
|
||||
raise ParameterError.new("Parameter: #{ param_name } was not given.")
|
||||
end
|
||||
yield(param_name, @outparam[param_name])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# To return(?) void explicitly.
|
||||
# def foo(input_var)
|
||||
# ...
|
||||
# return SOAP::RPC::SOAPVoid.new
|
||||
# end
|
||||
class SOAPVoid < XSD::XSDAnySimpleType
|
||||
include SOAPBasetype
|
||||
extend SOAPModuleUtils
|
||||
Name = XSD::QName.new(Mapping::RubyCustomTypeNamespace, nil)
|
||||
|
||||
public
|
||||
def initialize()
|
||||
@elename = Name
|
||||
@id = nil
|
||||
@precedents = []
|
||||
@parent = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
147
lib/soap/rpc/proxy.rb
Normal file
147
lib/soap/rpc/proxy.rb
Normal file
|
@ -0,0 +1,147 @@
|
|||
=begin
|
||||
SOAP4R - RPC Proxy library.
|
||||
Copyright (C) 2000, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'soap/soap'
|
||||
require 'soap/processor'
|
||||
require 'soap/mapping'
|
||||
require 'soap/rpc/rpc'
|
||||
require 'soap/rpc/element'
|
||||
require 'soap/streamHandler'
|
||||
|
||||
|
||||
module SOAP
|
||||
module RPC
|
||||
|
||||
|
||||
class Proxy
|
||||
include SOAP
|
||||
|
||||
public
|
||||
|
||||
attr_accessor :soapaction
|
||||
attr_accessor :allow_unqualified_element, :default_encodingstyle
|
||||
attr_reader :method
|
||||
|
||||
def initialize(stream_handler, soapaction = nil)
|
||||
@handler = stream_handler
|
||||
@soapaction = soapaction
|
||||
@method = {}
|
||||
@allow_unqualified_element = false
|
||||
@default_encodingstyle = nil
|
||||
end
|
||||
|
||||
class Request
|
||||
include RPC
|
||||
|
||||
public
|
||||
|
||||
attr_reader :method
|
||||
attr_reader :namespace
|
||||
attr_reader :name
|
||||
|
||||
def initialize(model, values)
|
||||
@method = model.dup
|
||||
@namespace = @method.elename.namespace
|
||||
@name = @method.elename.name
|
||||
|
||||
params = {}
|
||||
|
||||
if ((values.size == 1) and (values[0].is_a?(Hash)))
|
||||
params = values[0]
|
||||
else
|
||||
i = 0
|
||||
@method.each_param_name(SOAPMethod::IN, SOAPMethod::INOUT) do |name|
|
||||
params[name] = values[i] || SOAPNil.new
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
@method.set_param(params)
|
||||
end
|
||||
end
|
||||
|
||||
def add_method(qname, soapaction, name, param_def)
|
||||
@method[name] = SOAPMethodRequest.new(qname, param_def, soapaction)
|
||||
end
|
||||
|
||||
def create_request(name, *values)
|
||||
if (@method.key?(name))
|
||||
method = @method[name]
|
||||
method.encodingstyle = @default_encodingstyle if @default_encodingstyle
|
||||
else
|
||||
raise SOAP::RPC::MethodDefinitionError.new(
|
||||
"Method: #{ name } not defined.")
|
||||
end
|
||||
|
||||
Request.new(method, values)
|
||||
end
|
||||
|
||||
def invoke(req_header, req_body, soapaction = nil)
|
||||
if req_header and !req_header.is_a?(SOAPHeader)
|
||||
req_header = create_header(req_header)
|
||||
end
|
||||
if !req_body.is_a?(SOAPBody)
|
||||
req_body = SOAPBody.new(req_body)
|
||||
end
|
||||
opt = create_options
|
||||
send_string = Processor.marshal(req_header, req_body, opt)
|
||||
data = @handler.send(send_string, soapaction)
|
||||
if data.receive_string.empty?
|
||||
return nil, nil
|
||||
end
|
||||
res_charset = StreamHandler.parse_media_type(data.receive_contenttype)
|
||||
opt = create_options
|
||||
opt[:charset] = res_charset
|
||||
res_header, res_body = Processor.unmarshal(data.receive_string, opt)
|
||||
return res_header, res_body
|
||||
end
|
||||
|
||||
def call(headers, name, *values)
|
||||
req = create_request(name, *values)
|
||||
return invoke(headers, req.method, req.method.soapaction || @soapaction)
|
||||
end
|
||||
|
||||
def check_fault(body)
|
||||
if body.fault
|
||||
raise SOAP::FaultError.new(body.fault)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_header(headers)
|
||||
header = SOAPHeader.new()
|
||||
headers.each do |content, mustunderstand, encodingstyle|
|
||||
header.add(SOAPHeaderItem.new(content, mustunderstand, encodingstyle))
|
||||
end
|
||||
header
|
||||
end
|
||||
|
||||
def create_options
|
||||
opt = {}
|
||||
opt[:default_encodingstyle] = @default_encodingstyle
|
||||
if @allow_unqualified_element
|
||||
opt[:allow_unqualified_element] = true
|
||||
end
|
||||
opt
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
176
lib/soap/rpc/router.rb
Normal file
176
lib/soap/rpc/router.rb
Normal file
|
@ -0,0 +1,176 @@
|
|||
=begin
|
||||
SOAP4R - RPC Routing library
|
||||
Copyright (C) 2001, 2002 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'soap/soap'
|
||||
require 'soap/processor'
|
||||
require 'soap/mapping'
|
||||
require 'soap/rpc/rpc'
|
||||
require 'soap/rpc/element'
|
||||
|
||||
|
||||
module SOAP
|
||||
module RPC
|
||||
|
||||
|
||||
class Router
|
||||
include SOAP
|
||||
|
||||
attr_reader :actor
|
||||
attr_accessor :allow_unqualified_element
|
||||
attr_accessor :default_encodingstyle
|
||||
attr_accessor :mapping_registry
|
||||
|
||||
def initialize(actor)
|
||||
@actor = actor
|
||||
@receiver = {}
|
||||
@method_name = {}
|
||||
@method = {}
|
||||
@allow_unqualified_element = false
|
||||
@default_encodingstyle = nil
|
||||
@mapping_registry = nil
|
||||
end
|
||||
|
||||
def add_method(receiver, qname, soapaction, name, param_def)
|
||||
fqname = fqname(qname)
|
||||
@receiver[fqname] = receiver
|
||||
@method_name[fqname] = name
|
||||
@method[fqname] = RPC::SOAPMethodRequest.new(qname, param_def, soapaction)
|
||||
end
|
||||
|
||||
def add_header_handler
|
||||
raise NotImplementedError.new
|
||||
end
|
||||
|
||||
# Routing...
|
||||
def route(soap_string, charset = nil)
|
||||
opt = options
|
||||
opt[:charset] = charset
|
||||
is_fault = false
|
||||
begin
|
||||
header, body = Processor.unmarshal(soap_string, opt)
|
||||
# So far, header is omitted...
|
||||
soap_request = body.request
|
||||
unless soap_request.is_a?(SOAPStruct)
|
||||
raise RPCRoutingError.new("Not an RPC style.")
|
||||
end
|
||||
soap_response = dispatch(soap_request)
|
||||
rescue Exception
|
||||
soap_response = fault($!)
|
||||
is_fault = true
|
||||
end
|
||||
|
||||
header = SOAPHeader.new
|
||||
body = SOAPBody.new(soap_response)
|
||||
response_string = Processor.marshal(header, body, opt)
|
||||
|
||||
return response_string, is_fault
|
||||
end
|
||||
|
||||
# Create fault response string.
|
||||
def create_fault_response(e, charset = nil)
|
||||
header = SOAPHeader.new
|
||||
soap_response = fault(e)
|
||||
body = SOAPBody.new(soap_response)
|
||||
opt = options
|
||||
opt[:charset] = charset
|
||||
Processor.marshal(header, body, opt)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Create new response.
|
||||
def create_response(qname, result)
|
||||
name = fqname(qname)
|
||||
if (@method.key?(name))
|
||||
method = @method[name]
|
||||
else
|
||||
raise RPCRoutingError.new("Method: #{ name } not defined.")
|
||||
end
|
||||
|
||||
soap_response = method.create_method_response
|
||||
if soap_response.have_outparam?
|
||||
unless result.is_a?(Array)
|
||||
raise RPCRoutingError.new("Out parameter was not returned.")
|
||||
end
|
||||
outparams = {}
|
||||
i = 1
|
||||
soap_response.each_param_name('out', 'inout') do |outparam|
|
||||
outparams[outparam] = Mapping.obj2soap(result[i], @mapping_registry)
|
||||
i += 1
|
||||
end
|
||||
soap_response.set_outparam(outparams)
|
||||
soap_response.retval = Mapping.obj2soap(result[0], @mapping_registry)
|
||||
else
|
||||
soap_response.retval = Mapping.obj2soap(result, @mapping_registry)
|
||||
end
|
||||
soap_response
|
||||
end
|
||||
|
||||
# Create fault response.
|
||||
def fault(e)
|
||||
detail = Mapping::SOAPException.new(e)
|
||||
SOAPFault.new(
|
||||
SOAPString.new('Server'),
|
||||
SOAPString.new(e.to_s),
|
||||
SOAPString.new(@actor),
|
||||
Mapping.obj2soap(detail, @mapping_registry))
|
||||
end
|
||||
|
||||
# Dispatch to defined method.
|
||||
def dispatch(soap_method)
|
||||
request_struct = Mapping.soap2obj(soap_method, @mapping_registry)
|
||||
values = soap_method.collect { |key, value| request_struct[key] }
|
||||
method = lookup(soap_method.elename, values)
|
||||
unless method
|
||||
raise RPCRoutingError.new(
|
||||
"Method: #{ soap_method.elename } not supported.")
|
||||
end
|
||||
|
||||
result = method.call(*values)
|
||||
create_response(soap_method.elename, result)
|
||||
end
|
||||
|
||||
# Method lookup
|
||||
def lookup(qname, values)
|
||||
name = fqname(qname)
|
||||
# It may be necessary to check all part of method signature...
|
||||
if @method.member?(name)
|
||||
@receiver[name].method(@method_name[name].intern)
|
||||
else
|
||||
nil
|
||||
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
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
36
lib/soap/rpc/rpc.rb
Normal file
36
lib/soap/rpc/rpc.rb
Normal file
|
@ -0,0 +1,36 @@
|
|||
=begin
|
||||
SOAP4R - RPC utility.
|
||||
Copyright (C) 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
module SOAP
|
||||
|
||||
|
||||
module RPC
|
||||
ServerException = Mapping::MappedException
|
||||
|
||||
def self.defined_methods(obj)
|
||||
if obj.is_a?(Module)
|
||||
obj.methods - Module.methods
|
||||
else
|
||||
obj.methods - Kernel.instance_methods(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
167
lib/soap/rpc/soaplet.rb
Normal file
167
lib/soap/rpc/soaplet.rb
Normal file
|
@ -0,0 +1,167 @@
|
|||
=begin
|
||||
SOAP4R - SOAP handler servlet for WEBrick
|
||||
Copyright (C) 2001, 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'webrick/httpservlet/abstract'
|
||||
require 'webrick/httpstatus'
|
||||
require 'soap/rpc/router'
|
||||
require 'soap/streamHandler'
|
||||
|
||||
module SOAP
|
||||
module RPC
|
||||
|
||||
|
||||
class SOAPlet < WEBrick::HTTPServlet::AbstractServlet
|
||||
public
|
||||
attr_reader :app_scope_router
|
||||
|
||||
def initialize
|
||||
@router_map = {}
|
||||
@app_scope_router = ::SOAP::RPC::Router.new(self.class.name)
|
||||
end
|
||||
|
||||
# Add servant klass whose object has request scope. A servant object is
|
||||
# instanciated for each request.
|
||||
#
|
||||
# Bare in mind that servant klasses 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 klass.
|
||||
# I mean, use Driver#add_method_with_soapaction instead of Driver#add_method
|
||||
# at client side.
|
||||
#
|
||||
def add_rpc_request_servant(klass, namespace, mapping_registry = nil)
|
||||
router = RequestRouter.new(klass, namespace, mapping_registry)
|
||||
add_router(namespace, router)
|
||||
end
|
||||
|
||||
# Add servant object which has application scope.
|
||||
def add_rpc_servant(obj, namespace)
|
||||
router = @app_scope_router
|
||||
SOAPlet.add_servant_to_router(router, obj, namespace)
|
||||
add_router(namespace, router)
|
||||
end
|
||||
alias add_servant add_rpc_servant
|
||||
|
||||
|
||||
###
|
||||
## Servlet interfaces for WEBrick.
|
||||
#
|
||||
def get_instance(config, *options)
|
||||
@config = config
|
||||
self
|
||||
end
|
||||
|
||||
def require_path_info?
|
||||
false
|
||||
end
|
||||
|
||||
def do_GET(req, res)
|
||||
res.header['Allow'] = 'POST'
|
||||
raise WEBrick::HTTPStatus::MethodNotAllowed, "GET request not allowed."
|
||||
end
|
||||
|
||||
def do_POST(req, res)
|
||||
namespace = parse_soapaction(req.meta_vars['HTTP_SOAPACTION'])
|
||||
router = lookup_router(namespace)
|
||||
|
||||
is_fault = false
|
||||
|
||||
charset = ::SOAP::StreamHandler.parse_media_type(req['content-type'])
|
||||
begin
|
||||
response_stream, is_fault = router.route(req.body, charset)
|
||||
rescue Exception => e
|
||||
response_stream = router.create_fault_response(e)
|
||||
is_fault = true
|
||||
end
|
||||
|
||||
res.body = response_stream
|
||||
res['content-type'] = "text/xml; charset=\"#{charset}\""
|
||||
if response_stream.is_a?(IO)
|
||||
res.chunked = true
|
||||
end
|
||||
|
||||
if is_fault
|
||||
res.status = WEBrick::HTTPStatus::RC_INTERNAL_SERVER_ERROR
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
class RequestRouter < ::SOAP::RPC::Router
|
||||
def initialize(klass, namespace, mapping_registry = nil)
|
||||
super(namespace)
|
||||
if mapping_registry
|
||||
self.mapping_registry = mapping_registry
|
||||
end
|
||||
@klass = klass
|
||||
@namespace = namespace
|
||||
end
|
||||
|
||||
def route(soap_string)
|
||||
obj = @klass.new
|
||||
namespace = self.actor
|
||||
router = ::SOAP::RPC::Router.new(@namespace)
|
||||
SOAPlet.add_servant_to_router(router, obj, namespace)
|
||||
router.route(soap_string)
|
||||
end
|
||||
end
|
||||
|
||||
def add_router(namespace, router)
|
||||
@router_map[namespace] = router
|
||||
end
|
||||
|
||||
def parse_soapaction(soapaction)
|
||||
if /^"(.*)"$/ =~ soapaction
|
||||
soapaction = $1
|
||||
end
|
||||
if soapaction.empty?
|
||||
return nil
|
||||
end
|
||||
soapaction
|
||||
end
|
||||
|
||||
def lookup_router(namespace)
|
||||
if namespace
|
||||
@router_map[namespace] || @app_scope_router
|
||||
else
|
||||
@app_scope_router
|
||||
end
|
||||
end
|
||||
|
||||
class << self
|
||||
public
|
||||
def add_servant_to_router(router, obj, namespace)
|
||||
::SOAP::RPC.defined_methods(obj).each do |name|
|
||||
add_servant_method_to_router(router, obj, namespace, name)
|
||||
end
|
||||
end
|
||||
|
||||
def add_servant_method_to_router(router, obj, namespace, name)
|
||||
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 }" })
|
||||
router.add_method(obj, qname, soapaction, name, param_def)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
116
lib/soap/rpc/standaloneServer.rb
Normal file
116
lib/soap/rpc/standaloneServer.rb
Normal file
|
@ -0,0 +1,116 @@
|
|||
=begin
|
||||
SOAP4R - WEBrick Server
|
||||
Copyright (C) 2003 by NAKAMURA, Hiroshi
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'logger'
|
||||
require 'soap/rpc/soaplet'
|
||||
require 'soap/streamHandler'
|
||||
|
||||
# require 'webrick'
|
||||
require 'webrick/compat.rb'
|
||||
require 'webrick/version.rb'
|
||||
require 'webrick/config.rb'
|
||||
require 'webrick/log.rb'
|
||||
require 'webrick/server.rb'
|
||||
require 'webrick/utils.rb'
|
||||
require 'webrick/accesslog'
|
||||
# require 'webrick/htmlutils.rb'
|
||||
require 'webrick/httputils.rb'
|
||||
# require 'webrick/cookie.rb'
|
||||
require 'webrick/httpversion.rb'
|
||||
require 'webrick/httpstatus.rb'
|
||||
require 'webrick/httprequest.rb'
|
||||
require 'webrick/httpresponse.rb'
|
||||
require 'webrick/httpserver.rb'
|
||||
# require 'webrick/httpservlet.rb'
|
||||
# require 'webrick/httpauth.rb'
|
||||
|
||||
|
||||
module SOAP
|
||||
module RPC
|
||||
|
||||
|
||||
class StandaloneServer < Logger::Application
|
||||
attr_reader :server
|
||||
|
||||
def initialize(app_name, namespace, host = "0.0.0.0", port = 8080)
|
||||
super(app_name)
|
||||
@logdev = Logger.new(STDERR)
|
||||
@logdev.level = INFO
|
||||
@namespace = namespace
|
||||
@server = WEBrick::HTTPServer.new(
|
||||
:BindAddress => host,
|
||||
:Logger => logdev,
|
||||
:AccessLog => [[logdev, WEBrick::AccessLog::COMBINED_LOG_FORMAT]],
|
||||
:Port => port
|
||||
)
|
||||
@soaplet = ::SOAP::RPC::SOAPlet.new
|
||||
on_init
|
||||
@server.mount('/', @soaplet)
|
||||
end
|
||||
|
||||
def on_init
|
||||
# define extra methods in derived class.
|
||||
end
|
||||
|
||||
def add_rpc_request_servant(klass, namespace = @namespace, mapping_registry = nil)
|
||||
@soaplet.add_rpc_request_servant(klass, namespace, mapping_registry)
|
||||
end
|
||||
|
||||
def add_rpc_servant(obj, namespace = @namespace)
|
||||
@soaplet.add_rpc_servant(obj, namespace)
|
||||
end
|
||||
alias add_servant add_rpc_servant
|
||||
|
||||
def mapping_registry
|
||||
@soaplet.app_scope_router.mapping_registry
|
||||
end
|
||||
|
||||
def mapping_registry=(mapping_registry)
|
||||
@soaplet.app_scope_router.mapping_registry = mapping_registry
|
||||
end
|
||||
|
||||
def add_method(obj, name, *param)
|
||||
add_method_as(obj, name, name, *param)
|
||||
end
|
||||
|
||||
def add_method_as(obj, name, name_as, *param)
|
||||
qname = XSD::QName.new(@namespace, name_as)
|
||||
soapaction = nil
|
||||
method = obj.method(name)
|
||||
param_def = if param.size == 1 and param[0].is_a?(Array)
|
||||
param[0]
|
||||
elsif param.empty?
|
||||
::SOAP::RPC::SOAPMethod.create_param_def(
|
||||
(1..method.arity.abs).collect { |i| "p#{ i }" })
|
||||
else
|
||||
SOAP::RPC::SOAPMethod.create_param_def(param)
|
||||
end
|
||||
@soaplet.app_scope_router.add_method(obj, qname, soapaction, name, param_def)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def run
|
||||
@server.start
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
112
lib/soap/soap.rb
Normal file
112
lib/soap/soap.rb
Normal file
|
@ -0,0 +1,112 @@
|
|||
=begin
|
||||
SOAP4R - Base definitions.
|
||||
Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/qname'
|
||||
require 'xsd/charset'
|
||||
|
||||
|
||||
module SOAP
|
||||
|
||||
|
||||
Version = '1.5.0'
|
||||
|
||||
EnvelopeNamespace = 'http://schemas.xmlsoap.org/soap/envelope/'
|
||||
EncodingNamespace = 'http://schemas.xmlsoap.org/soap/encoding/'
|
||||
LiteralNamespace = 'http://xml.apache.org/xml-soap/literalxml'
|
||||
|
||||
NextActor = 'http://schemas.xmlsoap.org/soap/actor/next'
|
||||
|
||||
EleEnvelope = 'Envelope'
|
||||
EleHeader = 'Header'
|
||||
EleBody = 'Body'
|
||||
EleFault = 'Fault'
|
||||
EleFaultString = 'faultstring'
|
||||
EleFaultActor = 'faultactor'
|
||||
EleFaultCode = 'faultcode'
|
||||
EleFaultDetail = 'detail'
|
||||
|
||||
AttrMustUnderstand = 'mustUnderstand'
|
||||
AttrEncodingStyle = 'encodingStyle'
|
||||
AttrActor = 'actor'
|
||||
AttrRoot = 'root'
|
||||
AttrArrayType = 'arrayType'
|
||||
AttrOffset = 'offset'
|
||||
AttrPosition = 'position'
|
||||
ValueArray = 'Array'
|
||||
|
||||
EleEnvelopeName = XSD::QName.new(EnvelopeNamespace, EleEnvelope)
|
||||
EleHeaderName = XSD::QName.new(EnvelopeNamespace, EleHeader)
|
||||
EleBodyName = XSD::QName.new(EnvelopeNamespace, EleBody)
|
||||
EleFaultName = XSD::QName.new(EnvelopeNamespace, EleFault)
|
||||
EleFaultStringName = XSD::QName.new(nil, EleFaultString)
|
||||
EleFaultActorName = XSD::QName.new(nil, EleFaultActor)
|
||||
EleFaultCodeName = XSD::QName.new(nil, EleFaultCode)
|
||||
EleFaultDetailName = XSD::QName.new(nil, EleFaultDetail)
|
||||
AttrEncodingStyleName = XSD::QName.new(EnvelopeNamespace, AttrEncodingStyle)
|
||||
AttrRootName = XSD::QName.new(EncodingNamespace, AttrRoot)
|
||||
AttrArrayTypeName = XSD::QName.new(EncodingNamespace, AttrArrayType)
|
||||
AttrOffsetName = XSD::QName.new(EncodingNamespace, AttrOffset)
|
||||
AttrPositionName = XSD::QName.new(EncodingNamespace, AttrPosition)
|
||||
ValueArrayName = XSD::QName.new(EncodingNamespace, ValueArray)
|
||||
|
||||
Base64Literal = 'base64'
|
||||
|
||||
SOAPNamespaceTag = 'env'
|
||||
XSDNamespaceTag = 'xsd'
|
||||
XSINamespaceTag = 'xsi'
|
||||
|
||||
MediaType = 'text/xml'
|
||||
|
||||
class Error < StandardError; end
|
||||
|
||||
class StreamError < Error; end
|
||||
class HTTPStreamError < StreamError; end
|
||||
class PostUnavailableError < HTTPStreamError; end
|
||||
class MPostUnavailableError < HTTPStreamError; end
|
||||
|
||||
class ArrayIndexOutOfBoundsError < Error; end
|
||||
class ArrayStoreError < Error; end
|
||||
|
||||
class RPCRoutingError < Error; end
|
||||
|
||||
class FaultError < Error
|
||||
attr_reader :faultcode
|
||||
attr_reader :faultstring
|
||||
attr_reader :faultactor
|
||||
attr_accessor :detail
|
||||
|
||||
def initialize(fault)
|
||||
@faultcode = fault.faultcode
|
||||
@faultstring = fault.faultstring
|
||||
@faultactor = fault.faultactor
|
||||
@detail = fault.detail
|
||||
super(self.to_s)
|
||||
end
|
||||
|
||||
def to_s
|
||||
str = nil
|
||||
if @faultstring && @faultstring.respond_to?('data')
|
||||
str = @faultstring.data
|
||||
end
|
||||
str || '(No faultstring)'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
188
lib/soap/streamHandler.rb
Normal file
188
lib/soap/streamHandler.rb
Normal file
|
@ -0,0 +1,188 @@
|
|||
=begin
|
||||
SOAP4R - Stream handler.
|
||||
Copyright (C) 2000, 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'soap/soap'
|
||||
|
||||
|
||||
module SOAP
|
||||
|
||||
|
||||
class StreamHandler
|
||||
Client = begin
|
||||
require 'http-access2'
|
||||
if HTTPAccess2::VERSION < "2.0"
|
||||
raise LoadError.new("http-access/2.0 or later is required.")
|
||||
end
|
||||
HTTPAccess2::Client
|
||||
rescue LoadError
|
||||
STDERR.puts "Loading http-access2 failed. Net/http is used." if $DEBUG
|
||||
require 'soap/netHttpClient'
|
||||
SOAP::NetHttpClient
|
||||
end
|
||||
|
||||
RUBY_VERSION_STRING = "ruby #{ RUBY_VERSION } (#{ RUBY_RELEASE_DATE }) [#{ RUBY_PLATFORM }]"
|
||||
%q$Id$ =~ /: (\S+),v (\S+)/
|
||||
RCS_FILE, RCS_REVISION = $1, $2
|
||||
|
||||
class ConnectionData
|
||||
attr_accessor :send_string
|
||||
attr_accessor :send_contenttype
|
||||
attr_accessor :receive_string
|
||||
attr_accessor :receive_contenttype
|
||||
|
||||
def initialize
|
||||
@send_string = nil
|
||||
@send_contenttype = nil
|
||||
@receive_string = nil
|
||||
@receive_contenttype = nil
|
||||
@bag = {}
|
||||
end
|
||||
|
||||
def [](idx)
|
||||
@bag[idx]
|
||||
end
|
||||
|
||||
def []=(idx, value)
|
||||
@bag[idx] = value
|
||||
end
|
||||
end
|
||||
|
||||
attr_accessor :endpoint_url
|
||||
|
||||
def initialize(endpoint_url)
|
||||
@endpoint_url = endpoint_url
|
||||
end
|
||||
|
||||
def self.parse_media_type(str)
|
||||
if /^#{ MediaType }(?:\s*;\s*charset=([^"]+|"[^"]+"))?$/i !~ str
|
||||
raise StreamError.new("Illegal media type.");
|
||||
end
|
||||
charset = $1
|
||||
charset.gsub!(/"/, '') if charset
|
||||
charset
|
||||
end
|
||||
|
||||
def self.create_media_type(charset)
|
||||
"#{ MediaType }; charset=#{ charset }"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class HTTPPostStreamHandler < StreamHandler
|
||||
include SOAP
|
||||
|
||||
public
|
||||
|
||||
attr_accessor :wiredump_dev
|
||||
attr_accessor :wiredump_file_base
|
||||
attr_accessor :charset
|
||||
|
||||
NofRetry = 10 # [times]
|
||||
ConnectTimeout = 20 # [sec]
|
||||
SendTimeout = 60 # [sec]
|
||||
ReceiveTimeout = 60 # [sec]
|
||||
|
||||
def initialize(endpoint_url, proxy = nil, charset = nil)
|
||||
super(endpoint_url)
|
||||
@proxy = proxy || ENV['http_proxy'] || ENV['HTTP_PROXY']
|
||||
@charset = charset || XSD::Charset.charset_label($KCODE)
|
||||
@wiredump_dev = nil # Set an IO to get wiredump.
|
||||
@wiredump_file_base = nil
|
||||
@client = Client.new(@proxy, "SOAP4R/#{ Version }")
|
||||
@client.session_manager.connect_timeout = ConnectTimeout
|
||||
@client.session_manager.send_timeout = SendTimeout
|
||||
@client.session_manager.receive_timeout = ReceiveTimeout
|
||||
end
|
||||
|
||||
def proxy=(proxy)
|
||||
@proxy = proxy
|
||||
@client.proxy = @proxy
|
||||
end
|
||||
|
||||
def send(soap_string, soapaction = nil, charset = @charset)
|
||||
send_post(soap_string, soapaction, charset)
|
||||
end
|
||||
|
||||
def reset
|
||||
@client.reset(@endpoint_url)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def send_post(soap_string, soapaction, charset)
|
||||
data = ConnectionData.new
|
||||
data.send_string = soap_string
|
||||
data.send_contenttype = StreamHandler.create_media_type(charset)
|
||||
|
||||
wiredump_dev = if @wiredump_dev && @wiredump_dev.respond_to?("<<")
|
||||
@wiredump_dev
|
||||
else
|
||||
nil
|
||||
end
|
||||
@client.debug_dev = wiredump_dev
|
||||
|
||||
if @wiredump_file_base
|
||||
filename = @wiredump_file_base + '_request.xml'
|
||||
f = File.open(filename, "w")
|
||||
f << soap_string
|
||||
f.close
|
||||
end
|
||||
|
||||
extra = {}
|
||||
extra['Content-Type'] = data.send_contenttype
|
||||
extra['SOAPAction'] = "\"#{ soapaction }\""
|
||||
|
||||
wiredump_dev << "Wire dump:\n\n" if wiredump_dev
|
||||
begin
|
||||
res = @client.post(@endpoint_url, soap_string, extra)
|
||||
rescue
|
||||
@client.reset(@endpoint_url)
|
||||
raise
|
||||
end
|
||||
wiredump_dev << "\n\n" if wiredump_dev
|
||||
|
||||
receive_string = res.content
|
||||
|
||||
if @wiredump_file_base
|
||||
filename = @wiredump_file_base + '_response.xml'
|
||||
f = File.open(filename, "w")
|
||||
f << receive_string
|
||||
f.close
|
||||
end
|
||||
|
||||
case res.status
|
||||
when 405
|
||||
raise PostUnavailableError.new("#{ res.status }: #{ res.reason }")
|
||||
when 200, 500
|
||||
# Nothing to do.
|
||||
else
|
||||
raise HTTPStreamError.new("#{ res.status }: #{ res.reason }")
|
||||
end
|
||||
|
||||
data.receive_string = receive_string
|
||||
data.receive_contenttype = res.contenttype
|
||||
|
||||
return data
|
||||
end
|
||||
|
||||
CRLF = "\r\n"
|
||||
end
|
||||
|
||||
|
||||
end
|
490
lib/soap/wsdlDriver.rb
Normal file
490
lib/soap/wsdlDriver.rb
Normal file
|
@ -0,0 +1,490 @@
|
|||
=begin
|
||||
SOAP4R - SOAP WSDL driver
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/parser'
|
||||
require 'wsdl/importer'
|
||||
require 'xsd/qname'
|
||||
require 'soap/element'
|
||||
require 'soap/baseData'
|
||||
require 'soap/streamHandler'
|
||||
require 'soap/mapping'
|
||||
require 'soap/mapping/wsdlRegistry'
|
||||
require 'soap/rpc/rpc'
|
||||
require 'soap/rpc/element'
|
||||
require 'soap/processor'
|
||||
require 'logger'
|
||||
|
||||
|
||||
module SOAP
|
||||
|
||||
|
||||
class WSDLDriverFactory
|
||||
class FactoryError < StandardError; end
|
||||
|
||||
attr_reader :wsdl
|
||||
|
||||
def initialize(wsdl, logdev = nil)
|
||||
@logdev = logdev
|
||||
@wsdl = import(wsdl)
|
||||
end
|
||||
|
||||
def create_driver(servicename = nil, portname = nil, opt = {})
|
||||
service = if servicename
|
||||
@wsdl.service(XSD::QName.new(@wsdl.targetnamespace, servicename))
|
||||
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, opt)
|
||||
end
|
||||
|
||||
# Backward compatibility.
|
||||
alias createDriver create_driver
|
||||
|
||||
private
|
||||
|
||||
def import(location)
|
||||
WSDL::Importer.import(location)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class WSDLDriver
|
||||
class << self
|
||||
def __attr_proxy(symbol, assignable = false)
|
||||
name = symbol.to_s
|
||||
module_eval <<-EOD
|
||||
def #{name}
|
||||
@servant.#{name}
|
||||
end
|
||||
EOD
|
||||
if assignable
|
||||
module_eval <<-EOD
|
||||
def #{name}=(rhs)
|
||||
@servant.#{name} = rhs
|
||||
end
|
||||
EOD
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
__attr_proxy :opt
|
||||
__attr_proxy :logdev, true
|
||||
__attr_proxy :mapping_registry, true # for RPC unmarshal
|
||||
__attr_proxy :wsdl_mapping_registry, true # for RPC marshal
|
||||
__attr_proxy :endpoint_url, true
|
||||
__attr_proxy :wiredump_dev, true
|
||||
__attr_proxy :wiredump_file_base, true
|
||||
__attr_proxy :httpproxy, true
|
||||
|
||||
__attr_proxy :default_encodingstyle, true
|
||||
__attr_proxy :allow_unqualified_element, true
|
||||
__attr_proxy :generate_explicit_type, true
|
||||
|
||||
def reset_stream
|
||||
@servant.reset_stream
|
||||
end
|
||||
|
||||
# Backward compatibility.
|
||||
alias generateEncodeType= generate_explicit_type=
|
||||
|
||||
class Servant__
|
||||
include Logger::Severity
|
||||
include SOAP
|
||||
|
||||
attr_reader :opt
|
||||
attr_accessor :logdev
|
||||
attr_accessor :mapping_registry
|
||||
attr_accessor :wsdl_mapping_registry
|
||||
attr_reader :endpoint_url
|
||||
attr_reader :wiredump_dev
|
||||
attr_reader :wiredump_file_base
|
||||
attr_reader :httpproxy
|
||||
|
||||
attr_accessor :default_encodingstyle
|
||||
attr_accessor :allow_unqualified_element
|
||||
attr_accessor :generate_explicit_type
|
||||
|
||||
class Mapper
|
||||
def initialize(elements, types)
|
||||
@elements = elements
|
||||
@types = types
|
||||
end
|
||||
|
||||
def obj2ele(obj, name)
|
||||
if ele = @elements[name]
|
||||
_obj2ele(obj, ele)
|
||||
elsif type = @types[name]
|
||||
obj2type(obj, type)
|
||||
else
|
||||
raise RuntimeError.new("Cannot find name #{name} in schema.")
|
||||
end
|
||||
end
|
||||
|
||||
def ele2obj(ele, *arg)
|
||||
raise NotImplementedError.new
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def _obj2ele(obj, ele)
|
||||
o = nil
|
||||
if ele.type
|
||||
if type = @types[ele.type]
|
||||
o = obj2type(obj, type)
|
||||
elsif type = TypeMap[ele.type]
|
||||
o = base2soap(obj, type)
|
||||
else
|
||||
raise RuntimeError.new("Cannot find type #{ele.type}.")
|
||||
end
|
||||
o.elename = ele.name
|
||||
elsif ele.local_complextype
|
||||
o = SOAPElement.new(ele.name)
|
||||
ele.local_complextype.each_element do |child_name, child_ele|
|
||||
o.add(_obj2ele(find_attribute(obj, child_name.name), child_ele))
|
||||
end
|
||||
else
|
||||
raise RuntimeError.new("Illegal schema?")
|
||||
end
|
||||
o
|
||||
end
|
||||
|
||||
def obj2type(obj, type)
|
||||
o = SOAPElement.new(type.name)
|
||||
type.each_element do |child_name, child_ele|
|
||||
o.add(_obj2ele(find_attribute(obj, child_name.name), child_ele))
|
||||
end
|
||||
o
|
||||
end
|
||||
|
||||
def _ele2obj(ele)
|
||||
raise NotImplementedError.new
|
||||
end
|
||||
|
||||
def base2soap(obj, type)
|
||||
soap_obj = nil
|
||||
if type <= XSD::XSDString
|
||||
soap_obj = type.new(XSD::Charset.is_ces(obj, $KCODE) ?
|
||||
XSD::Charset.encoding_conv(obj, $KCODE, XSD::Charset.encoding) : obj)
|
||||
else
|
||||
soap_obj = type.new(obj)
|
||||
end
|
||||
soap_obj
|
||||
end
|
||||
|
||||
def find_attribute(obj, attr_name)
|
||||
if obj.respond_to?(attr_name)
|
||||
obj.__send__(attr_name)
|
||||
elsif obj.is_a?(Hash)
|
||||
obj[attr_name] || obj[attr_name.intern]
|
||||
else
|
||||
obj.instance_eval("@#{ attr_name }")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(host, wsdl, port, logdev, opt)
|
||||
@host = host
|
||||
@wsdl = wsdl
|
||||
@port = port
|
||||
@logdev = logdev
|
||||
@opt = opt.dup
|
||||
@mapping_registry = nil # for rpc unmarshal
|
||||
@wsdl_mapping_registry = nil # for rpc marshal
|
||||
@endpoint_url = nil
|
||||
@wiredump_dev = nil
|
||||
@wiredump_file_base = nil
|
||||
@httpproxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
||||
|
||||
@wsdl_elements = @wsdl.collect_elements
|
||||
@wsdl_types = @wsdl.collect_complextypes
|
||||
@rpc_decode_typemap = @wsdl_types + @wsdl.soap_rpc_complextypes(port.find_binding)
|
||||
@wsdl_mapping_registry = Mapping::WSDLRegistry.new(@rpc_decode_typemap)
|
||||
@doc_mapper = Mapper.new(@wsdl_elements, @wsdl_types)
|
||||
@default_encodingstyle = EncodingNamespace
|
||||
@allow_unqualified_element = true
|
||||
@generate_explicit_type = false
|
||||
|
||||
create_handler
|
||||
@operations = {}
|
||||
# Convert a map which key is QName, to a Hash which key is String.
|
||||
@port.inputoperation_map.each do |op_name, op_info|
|
||||
@operations[op_name.name] = op_info
|
||||
add_method_interface(op_info)
|
||||
end
|
||||
end
|
||||
|
||||
def endpoint_url=(endpoint_url)
|
||||
@endpoint_url = endpoint_url
|
||||
if @handler
|
||||
@handler.endpoint_url = @endpoint_url
|
||||
@handler.reset
|
||||
end
|
||||
log(DEBUG) { "endpoint_url=: set endpoint_url #{ @endpoint_url }." }
|
||||
end
|
||||
|
||||
def wiredump_dev=(dev)
|
||||
@wiredump_dev = dev
|
||||
if @handler
|
||||
@handler.wiredump_dev = @wiredump_dev
|
||||
@handler.reset
|
||||
end
|
||||
end
|
||||
|
||||
def wiredump_file_base=(base)
|
||||
@wiredump_file_base = base
|
||||
end
|
||||
|
||||
def httpproxy=(httpproxy)
|
||||
@httpproxy = httpproxy
|
||||
if @handler
|
||||
@handler.proxy = @httpproxy
|
||||
@handler.reset
|
||||
end
|
||||
log(DEBUG) { "httpproxy=: set httpproxy #{ @httpproxy }." }
|
||||
end
|
||||
|
||||
def reset_stream
|
||||
@handler.reset
|
||||
end
|
||||
|
||||
def rpc_send(method_name, *params)
|
||||
log(INFO) { "call: calling method '#{ method_name }'." }
|
||||
log(DEBUG) { "call: parameters '#{ params.inspect }'." }
|
||||
|
||||
op_info = @operations[method_name]
|
||||
parts_names = op_info.bodyparts.collect { |part| part.name }
|
||||
obj = create_method_obj(parts_names, params)
|
||||
method = Mapping.obj2soap(obj, @wsdl_mapping_registry, op_info.optype_name)
|
||||
method.elename = op_info.op_name
|
||||
method.type = XSD::QName.new # Request should not be typed.
|
||||
req_header = nil
|
||||
req_body = SOAPBody.new(method)
|
||||
|
||||
if @wiredump_file_base
|
||||
@handler.wiredump_file_base = @wiredump_file_base + '_' << method_name
|
||||
end
|
||||
|
||||
begin
|
||||
opt = create_options
|
||||
opt[:decode_typemap] = @rpc_decode_typemap
|
||||
res_header, res_body = invoke(req_header, req_body, op_info, opt)
|
||||
if res_body.fault
|
||||
raise SOAP::FaultError.new(res_body.fault)
|
||||
end
|
||||
rescue SOAP::FaultError => e
|
||||
Mapping.fault2exception(e)
|
||||
end
|
||||
|
||||
ret = res_body.response ?
|
||||
Mapping.soap2obj(res_body.response, @mapping_registry) : nil
|
||||
|
||||
if res_body.outparams
|
||||
outparams = res_body.outparams.collect { |outparam|
|
||||
Mapping.soap2obj(outparam)
|
||||
}
|
||||
return [ret].concat(outparams)
|
||||
else
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
# req_header: [[element, mustunderstand, encodingstyle(QName/String)], ...]
|
||||
# req_body: SOAPBasetype/SOAPCompoundtype
|
||||
def document_send(name, header_obj, body_obj)
|
||||
log(INFO) { "document_send: sending document '#{ name }'." }
|
||||
op_info = @operations[name]
|
||||
req_header = header_from_obj(header_obj, op_info)
|
||||
req_body = body_from_obj(body_obj, op_info)
|
||||
opt = create_options
|
||||
res_header, res_body = invoke(req_header, req_body, op_info, opt)
|
||||
if res_body.fault
|
||||
raise SOAP::FaultError.new(res_body.fault)
|
||||
end
|
||||
res_body_obj = res_body.response ?
|
||||
Mapping.soap2obj(res_body.response, @mapping_registry) : nil
|
||||
return res_header, res_body_obj
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_handler
|
||||
endpoint_url = @endpoint_url || @port.soap_address.location
|
||||
@handler = HTTPPostStreamHandler.new(endpoint_url, @httpproxy,
|
||||
XSD::Charset.encoding_label)
|
||||
@handler.wiredump_dev = @wiredump_dev
|
||||
end
|
||||
|
||||
def create_method_obj(names, params)
|
||||
o = Object.new
|
||||
for idx in 0 ... params.length
|
||||
o.instance_eval("@#{ names[idx] } = params[idx]")
|
||||
end
|
||||
o
|
||||
end
|
||||
|
||||
def invoke(req_header, req_body, op_info, opt)
|
||||
send_string = Processor.marshal(req_header, req_body, opt)
|
||||
log(DEBUG) { "invoke: sending string #{ send_string }" }
|
||||
data = @handler.send(send_string, op_info.soapaction)
|
||||
log(DEBUG) { "invoke: received string #{ data.receive_string }" }
|
||||
if data.receive_string.empty?
|
||||
return nil, nil
|
||||
end
|
||||
res_charset = StreamHandler.parse_media_type(data.receive_contenttype)
|
||||
opt[:charset] = res_charset
|
||||
res_header, res_body = Processor.unmarshal(data.receive_string, opt)
|
||||
return res_header, res_body
|
||||
end
|
||||
|
||||
def header_from_obj(obj, op_info)
|
||||
if obj.is_a?(SOAPHeader)
|
||||
obj
|
||||
elsif op_info.headerparts.empty?
|
||||
if obj.nil?
|
||||
nil
|
||||
else
|
||||
raise RuntimeError.new("No header definition in schema.")
|
||||
end
|
||||
elsif op_info.headerparts.size == 1
|
||||
part = op_info.headerparts[0]
|
||||
header = SOAPHeader.new()
|
||||
header.add(headeritem_from_obj(obj, part.element || part.eletype))
|
||||
header
|
||||
else
|
||||
header = SOAPHeader.new()
|
||||
op_info.headerparts.each do |part|
|
||||
child = obj[part.elename.name]
|
||||
ele = headeritem_from_obj(child, part.element || part.eletype)
|
||||
header.add(ele)
|
||||
end
|
||||
header
|
||||
end
|
||||
end
|
||||
|
||||
def headeritem_from_obj(obj, name)
|
||||
if obj.nil?
|
||||
SOAPElement.new(name)
|
||||
elsif obj.is_a?(SOAPHeaderItem)
|
||||
obj
|
||||
else
|
||||
@doc_mapper.obj2ele(obj, name)
|
||||
end
|
||||
end
|
||||
|
||||
def body_from_obj(obj, op_info)
|
||||
if obj.is_a?(SOAPBody)
|
||||
obj
|
||||
elsif op_info.bodyparts.empty?
|
||||
if obj.nil?
|
||||
nil
|
||||
else
|
||||
raise RuntimeError.new("No body found in schema.")
|
||||
end
|
||||
elsif op_info.bodyparts.size == 1
|
||||
part = op_info.bodyparts[0]
|
||||
ele = bodyitem_from_obj(obj, part.element || part.type)
|
||||
SOAPBody.new(ele)
|
||||
else
|
||||
body = SOAPBody.new
|
||||
op_info.bodyparts.each do |part|
|
||||
child = obj[part.elename.name]
|
||||
ele = bodyitem_from_obj(child, part.element || part.type)
|
||||
body.add(ele.elename.name, ele)
|
||||
end
|
||||
body
|
||||
end
|
||||
end
|
||||
|
||||
def bodyitem_from_obj(obj, name)
|
||||
if obj.nil?
|
||||
SOAPElement.new(name)
|
||||
elsif obj.is_a?(SOAPElement)
|
||||
obj
|
||||
else
|
||||
@doc_mapper.obj2ele(obj, name)
|
||||
end
|
||||
end
|
||||
|
||||
def add_method_interface(op_info)
|
||||
case op_info.style
|
||||
when :document
|
||||
add_document_method_interface(op_info.op_name.name)
|
||||
when :rpc
|
||||
parts_names = op_info.bodyparts.collect { |part| part.name }
|
||||
add_rpc_method_interface(op_info.op_name.name, parts_names)
|
||||
else
|
||||
raise RuntimeError.new("Unknown style: #{op_info.style}")
|
||||
end
|
||||
end
|
||||
|
||||
def add_document_method_interface(name)
|
||||
@host.instance_eval <<-EOS
|
||||
def #{ name }(headers, body)
|
||||
@servant.document_send(#{ name.dump }, headers, body)
|
||||
end
|
||||
EOS
|
||||
end
|
||||
|
||||
def add_rpc_method_interface(name, parts_names)
|
||||
i = 0
|
||||
param_names = parts_names.collect { |orgname| i += 1; "arg#{ i }" }
|
||||
callparam_str = (param_names.collect { |pname| ", " + pname }).join
|
||||
@host.instance_eval <<-EOS
|
||||
def #{ name }(#{ param_names.join(", ") })
|
||||
@servant.rpc_send(#{ name.dump }#{ callparam_str })
|
||||
end
|
||||
EOS
|
||||
end
|
||||
|
||||
def create_options
|
||||
opt = @opt.dup
|
||||
opt[:default_encodingstyle] = @default_encodingstyle
|
||||
opt[:allow_unqualified_element] = @allow_unqualified_element
|
||||
opt[:generate_explicit_type] = @generate_explicit_type
|
||||
opt
|
||||
end
|
||||
|
||||
def log(sev)
|
||||
@logdev.add(sev, nil, self.class) { yield } if @logdev
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(wsdl, port, logdev, opt)
|
||||
@servant = Servant__.new(self, wsdl, port, logdev, opt)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
76
lib/wsdl/binding.rb
Normal file
76
lib/wsdl/binding.rb
Normal file
|
@ -0,0 +1,76 @@
|
|||
=begin
|
||||
WSDL4R - WSDL binding definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
require 'xsd/namedelements'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class Binding < Info
|
||||
attr_reader :name # required
|
||||
attr_reader :type # required
|
||||
attr_reader :operations
|
||||
attr_reader :soapbinding
|
||||
|
||||
def initialize
|
||||
super
|
||||
@name = nil
|
||||
@type = nil
|
||||
@operations = XSD::NamedElements.new
|
||||
@soapbinding = nil
|
||||
end
|
||||
|
||||
def targetnamespace
|
||||
parent.targetnamespace
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when OperationName
|
||||
o = OperationBinding.new
|
||||
@operations << o
|
||||
o
|
||||
when SOAPBindingName
|
||||
o = WSDL::SOAP::Binding.new
|
||||
@soapbinding = o
|
||||
o
|
||||
when DocumentationName
|
||||
o = Documentation.new
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when NameAttrName
|
||||
@name = XSD::QName.new(targetnamespace, value)
|
||||
when TypeAttrName
|
||||
@type = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
73
lib/wsdl/data.rb
Normal file
73
lib/wsdl/data.rb
Normal file
|
@ -0,0 +1,73 @@
|
|||
=begin
|
||||
WSDL4R - WSDL data definitions.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/documentation'
|
||||
require 'wsdl/definitions'
|
||||
require 'wsdl/types'
|
||||
require 'wsdl/message'
|
||||
require 'wsdl/part'
|
||||
require 'wsdl/portType'
|
||||
require 'wsdl/operation'
|
||||
require 'wsdl/param'
|
||||
require 'wsdl/binding'
|
||||
require 'wsdl/operationBinding'
|
||||
require 'wsdl/service'
|
||||
require 'wsdl/port'
|
||||
require 'wsdl/import'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
BindingName = XSD::QName.new(Namespace, 'binding')
|
||||
DefinitionsName = XSD::QName.new(Namespace, 'definitions')
|
||||
DocumentationName = XSD::QName.new(Namespace, 'documentation')
|
||||
FaultName = XSD::QName.new(Namespace, 'fault')
|
||||
ImportName = XSD::QName.new(Namespace, 'import')
|
||||
InputName = XSD::QName.new(Namespace, 'input')
|
||||
MessageName = XSD::QName.new(Namespace, 'message')
|
||||
OperationName = XSD::QName.new(Namespace, 'operation')
|
||||
OutputName = XSD::QName.new(Namespace, 'output')
|
||||
PartName = XSD::QName.new(Namespace, 'part')
|
||||
PortName = XSD::QName.new(Namespace, 'port')
|
||||
PortTypeName = XSD::QName.new(Namespace, 'portType')
|
||||
ServiceName = XSD::QName.new(Namespace, 'service')
|
||||
TypesName = XSD::QName.new(Namespace, 'types')
|
||||
|
||||
SchemaName = XSD::QName.new(XSD::Namespace, 'schema')
|
||||
|
||||
SOAPAddressName = XSD::QName.new(SOAPBindingNamespace, 'address')
|
||||
SOAPBindingName = XSD::QName.new(SOAPBindingNamespace, 'binding')
|
||||
SOAPHeaderName = XSD::QName.new(SOAPBindingNamespace, 'header')
|
||||
SOAPBodyName = XSD::QName.new(SOAPBindingNamespace, 'body')
|
||||
SOAPFaultName = XSD::QName.new(SOAPBindingNamespace, 'fault')
|
||||
SOAPOperationName = XSD::QName.new(SOAPBindingNamespace, 'operation')
|
||||
|
||||
BindingAttrName = XSD::QName.new(nil, 'binding')
|
||||
ElementAttrName = XSD::QName.new(nil, 'element')
|
||||
LocationAttrName = XSD::QName.new(nil, 'location')
|
||||
MessageAttrName = XSD::QName.new(nil, 'message')
|
||||
NameAttrName = XSD::QName.new(nil, 'name')
|
||||
NamespaceAttrName = XSD::QName.new(nil, 'namespace')
|
||||
ParameterOrderAttrName = XSD::QName.new(nil, 'parameterOrder')
|
||||
TargetNamespaceAttrName = XSD::QName.new(nil, 'targetNamespace')
|
||||
TypeAttrName = XSD::QName.new(nil, 'type')
|
||||
|
||||
|
||||
end
|
233
lib/wsdl/definitions.rb
Normal file
233
lib/wsdl/definitions.rb
Normal file
|
@ -0,0 +1,233 @@
|
|||
=begin
|
||||
WSDL4R - WSDL definitions.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
require 'xsd/namedelements'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class Definitions < Info
|
||||
attr_reader :name
|
||||
attr_reader :targetnamespace
|
||||
attr_reader :imports
|
||||
|
||||
# Overrides Info#root
|
||||
def root
|
||||
@root
|
||||
end
|
||||
|
||||
def root=(root)
|
||||
@root = root
|
||||
end
|
||||
|
||||
def initialize
|
||||
super
|
||||
@name = nil
|
||||
@targetnamespace = nil
|
||||
@types = nil
|
||||
@imports = []
|
||||
@messages = XSD::NamedElements.new
|
||||
@porttypes = XSD::NamedElements.new
|
||||
@bindings = XSD::NamedElements.new
|
||||
@services = XSD::NamedElements.new
|
||||
|
||||
@anontypes = XSD::NamedElements.new
|
||||
@root = self
|
||||
end
|
||||
|
||||
def targetnamespace=(targetnamespace)
|
||||
@targetnamespace = targetnamespace
|
||||
if @name
|
||||
@name = XSD::QName.new(@targetnamespace, @name.name)
|
||||
end
|
||||
end
|
||||
|
||||
def collect_elements
|
||||
result = XSD::NamedElements.new
|
||||
if @types
|
||||
@types.schemas.each do |schema|
|
||||
result.concat(schema.elements)
|
||||
end
|
||||
end
|
||||
@imports.each do |import|
|
||||
result.concat(import.content.collect_elements)
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def collect_complextypes
|
||||
result = @anontypes.dup
|
||||
if @types
|
||||
@types.schemas.each do |schema|
|
||||
result.concat(schema.complextypes)
|
||||
end
|
||||
end
|
||||
@imports.each do |import|
|
||||
result.concat(import.content.collect_complextypes)
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def add_type(complextype)
|
||||
@anontypes << complextype
|
||||
end
|
||||
|
||||
def messages
|
||||
result = @messages.dup
|
||||
@imports.each do |import|
|
||||
result.concat(import.content.messages) if self.class === import.content
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def porttypes
|
||||
result = @porttypes.dup
|
||||
@imports.each do |import|
|
||||
result.concat(import.content.porttypes) if self.class === import.content
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def bindings
|
||||
result = @bindings.dup
|
||||
@imports.each do |import|
|
||||
result.concat(import.content.bindings) if self.class === import.content
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def services
|
||||
result = @services.dup
|
||||
@imports.each do |import|
|
||||
result.concat(import.content.services) if self.class === import.content
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def message(name)
|
||||
message = @messages[name]
|
||||
return message if message
|
||||
@imports.each do |import|
|
||||
message = import.content.message(name) if self.class === import.content
|
||||
return message if message
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def porttype(name)
|
||||
porttype = @porttypes[name]
|
||||
return porttype if porttype
|
||||
@imports.each do |import|
|
||||
porttype = import.content.porttype(name) if self.class === import.content
|
||||
return porttype if porttype
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def binding(name)
|
||||
binding = @bindings[name]
|
||||
return binding if binding
|
||||
@imports.each do |import|
|
||||
binding = import.content.binding(name) if self.class === import.content
|
||||
return binding if binding
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def service(name)
|
||||
service = @services[name]
|
||||
return service if service
|
||||
@imports.each do |import|
|
||||
service = import.content.service(name) if self.class === import.content
|
||||
return service if service
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def porttype_binding(name)
|
||||
binding = @bindings.find { |item| item.type == name }
|
||||
return binding if binding
|
||||
@imports.each do |import|
|
||||
binding = import.content.porttype_binding(name) if self.class === import.content
|
||||
return binding if binding
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when ImportName
|
||||
o = Import.new
|
||||
@imports << o
|
||||
o
|
||||
when TypesName
|
||||
o = Types.new
|
||||
@types = o
|
||||
o
|
||||
when MessageName
|
||||
o = Message.new
|
||||
@messages << o
|
||||
o
|
||||
when PortTypeName
|
||||
o = PortType.new
|
||||
@porttypes << o
|
||||
o
|
||||
when BindingName
|
||||
o = Binding.new
|
||||
@bindings << o
|
||||
o
|
||||
when ServiceName
|
||||
o = Service.new
|
||||
@services << o
|
||||
o
|
||||
when DocumentationName
|
||||
o = Documentation.new
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when NameAttrName
|
||||
@name = XSD::QName.new(@targetnamespace, value)
|
||||
when TargetNamespaceAttrName
|
||||
self.targetnamespace = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def self.parse_element(element)
|
||||
if element == DefinitionsName
|
||||
Definitions.new
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
43
lib/wsdl/documentation.rb
Normal file
43
lib/wsdl/documentation.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
=begin
|
||||
WSDL4R - WSDL SOAP documentation element.
|
||||
Copyright (C) 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class Documentation < 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
|
81
lib/wsdl/import.rb
Normal file
81
lib/wsdl/import.rb
Normal file
|
@ -0,0 +1,81 @@
|
|||
=begin
|
||||
WSDL4R - WSDL import definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
require 'wsdl/importer'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class Import < Info
|
||||
attr_reader :namespace
|
||||
attr_reader :location
|
||||
attr_reader :content
|
||||
|
||||
def initialize
|
||||
super
|
||||
@namespace = nil
|
||||
@location = nil
|
||||
@content = nil
|
||||
@web_client = nil
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when DocumentationName
|
||||
o = Documentation.new
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when NamespaceAttrName
|
||||
@namespace = value
|
||||
if @content
|
||||
@content.targetnamespace = @namespace
|
||||
end
|
||||
@namespace
|
||||
when LocationAttrName
|
||||
@location = value
|
||||
@content = import(@location)
|
||||
if @content.is_a?(Definitions)
|
||||
@content.root = root
|
||||
if @namespace
|
||||
@content.targetnamespace = @namespace
|
||||
end
|
||||
end
|
||||
@location
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def import(location)
|
||||
Importer.import(location)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
75
lib/wsdl/importer.rb
Normal file
75
lib/wsdl/importer.rb
Normal file
|
@ -0,0 +1,75 @@
|
|||
=begin
|
||||
WSDL4R - WSDL importer library.
|
||||
Copyright (C) 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class Importer
|
||||
def self.import(location)
|
||||
new.import(location)
|
||||
end
|
||||
|
||||
def initialize
|
||||
@web_client = nil
|
||||
end
|
||||
|
||||
def import(location)
|
||||
content = nil
|
||||
if FileTest.exist?(location)
|
||||
content = File.open(location).read
|
||||
else
|
||||
proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
||||
content = web_client.new(proxy, "WSDL4R").get_content(location)
|
||||
end
|
||||
opt = {} # charset?
|
||||
begin
|
||||
WSDL::Parser.new(opt).parse(content)
|
||||
rescue WSDL::Parser::ParseError => orgexcn
|
||||
begin
|
||||
require 'wsdl/xmlSchema/parser'
|
||||
WSDL::XMLSchema::Parser.new(opt).parse(content)
|
||||
rescue
|
||||
raise orgexcn
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
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
|
||||
STDERR.puts "Loading http-access2 failed. Net/http is used." if $DEBUG
|
||||
require 'soap/netHttpClient'
|
||||
::SOAP::NetHttpClient
|
||||
end
|
||||
@web_client
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
44
lib/wsdl/info.rb
Normal file
44
lib/wsdl/info.rb
Normal file
|
@ -0,0 +1,44 @@
|
|||
=begin
|
||||
WSDL4R - WSDL information base.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class Info
|
||||
attr_accessor :parent
|
||||
attr_accessor :id
|
||||
|
||||
def initialize
|
||||
@parent = nil
|
||||
@id = nil
|
||||
end
|
||||
|
||||
def root
|
||||
@parent.root
|
||||
end
|
||||
|
||||
def parse_element(element); end # abstract
|
||||
|
||||
def parse_attr(attr, value); end # abstract
|
||||
|
||||
def parse_epilogue; end # abstract
|
||||
end
|
||||
|
||||
|
||||
end
|
65
lib/wsdl/message.rb
Normal file
65
lib/wsdl/message.rb
Normal file
|
@ -0,0 +1,65 @@
|
|||
=begin
|
||||
WSDL4R - WSDL message definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class Message < Info
|
||||
attr_reader :name # required
|
||||
attr_reader :parts
|
||||
|
||||
def initialize
|
||||
super
|
||||
@name = nil
|
||||
@parts = []
|
||||
end
|
||||
|
||||
def targetnamespace
|
||||
parent.targetnamespace
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when PartName
|
||||
o = Part.new
|
||||
@parts << o
|
||||
o
|
||||
when DocumentationName
|
||||
o = Documentation.new
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when NameAttrName
|
||||
@name = XSD::QName.new(parent.targetnamespace, value)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
144
lib/wsdl/operation.rb
Normal file
144
lib/wsdl/operation.rb
Normal file
|
@ -0,0 +1,144 @@
|
|||
=begin
|
||||
WSDL4R - WSDL operation definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class Operation < Info
|
||||
class NameInfo
|
||||
attr_reader :op_name
|
||||
attr_reader :optype_name
|
||||
attr_reader :parts
|
||||
def initialize(op_name, optype_name, parts)
|
||||
@op_name = op_name
|
||||
@optype_name = optype_name
|
||||
@parts = parts
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :name # required
|
||||
attr_reader :parameter_order # optional
|
||||
attr_reader :input
|
||||
attr_reader :output
|
||||
attr_reader :fault
|
||||
attr_reader :type # required
|
||||
|
||||
def initialize
|
||||
super
|
||||
@name = nil
|
||||
@type = nil
|
||||
@parameter_order = nil
|
||||
@input = nil
|
||||
@output = nil
|
||||
@fault = nil
|
||||
end
|
||||
|
||||
def targetnamespace
|
||||
parent.targetnamespace
|
||||
end
|
||||
|
||||
def input_info
|
||||
op_name = @name
|
||||
optype_name = XSD::QName.new(targetnamespace, input.name ? input.name.name : @name.name)
|
||||
NameInfo.new(op_name, optype_name, inputparts)
|
||||
end
|
||||
|
||||
def output_info
|
||||
op_name = @name
|
||||
optype_name = XSD::QName.new(targetnamespace, output.name ? output.name.name : @name.name)
|
||||
NameInfo.new(op_name, optype_name, outputparts)
|
||||
end
|
||||
|
||||
def inputparts
|
||||
sort_parts(input.find_message.parts)
|
||||
end
|
||||
|
||||
def outputparts
|
||||
sort_parts(output.find_message.parts)
|
||||
end
|
||||
|
||||
def faultparts
|
||||
sort_parts(fault.find_message.parts)
|
||||
end
|
||||
|
||||
def outputname
|
||||
XSD::QName.new(targetnamespace,
|
||||
output.name ? output.name.name : @name.name + 'Response')
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when InputName
|
||||
o = Param.new
|
||||
@input = o
|
||||
o
|
||||
when OutputName
|
||||
o = Param.new
|
||||
@output = o
|
||||
o
|
||||
when FaultName
|
||||
o = Param.new
|
||||
@fault = o
|
||||
o
|
||||
when DocumentationName
|
||||
o = Documentation.new
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when NameAttrName
|
||||
@name = XSD::QName.new(targetnamespace, value)
|
||||
when TypeAttrName
|
||||
@type = value
|
||||
when ParameterOrderAttrName
|
||||
@parameter_order = value.split(/\s+/)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def sort_parts(parts)
|
||||
return parts.dup unless parameter_order
|
||||
result = []
|
||||
parameter_order.each do |orderitem|
|
||||
if (ele = parts.find { |part| part.name == orderitem })
|
||||
result << ele
|
||||
end
|
||||
end
|
||||
if result.length == 0
|
||||
return parts.dup
|
||||
end
|
||||
if parts.length != result.length
|
||||
raise RuntimeError.new("Incomplete prarmeterOrder list.")
|
||||
end
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
91
lib/wsdl/operationBinding.rb
Normal file
91
lib/wsdl/operationBinding.rb
Normal file
|
@ -0,0 +1,91 @@
|
|||
=begin
|
||||
WSDL4R - WSDL bound operation definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class OperationBinding < Info
|
||||
attr_reader :name # required
|
||||
attr_reader :input
|
||||
attr_reader :output
|
||||
attr_reader :fault
|
||||
attr_reader :soapoperation
|
||||
|
||||
def initialize
|
||||
super
|
||||
@name = nil
|
||||
@input = nil
|
||||
@output = nil
|
||||
@fault = nil
|
||||
@soapoperation = nil
|
||||
end
|
||||
|
||||
def targetnamespace
|
||||
parent.targetnamespace
|
||||
end
|
||||
|
||||
def porttype
|
||||
root.porttype(parent.type)
|
||||
end
|
||||
|
||||
def find_operation
|
||||
porttype.operations[@name]
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when InputName
|
||||
o = Param.new
|
||||
@input = o
|
||||
o
|
||||
when OutputName
|
||||
o = Param.new
|
||||
@output = o
|
||||
o
|
||||
when FaultName
|
||||
o = Param.new
|
||||
@fault = o
|
||||
o
|
||||
when SOAPOperationName
|
||||
o = WSDL::SOAP::Operation.new
|
||||
@soapoperation = o
|
||||
o
|
||||
when DocumentationName
|
||||
o = Documentation.new
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when NameAttrName
|
||||
@name = XSD::QName.new(targetnamespace, value)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
85
lib/wsdl/param.rb
Normal file
85
lib/wsdl/param.rb
Normal file
|
@ -0,0 +1,85 @@
|
|||
=begin
|
||||
WSDL4R - WSDL param definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class Param < Info
|
||||
attr_reader :message # required
|
||||
attr_reader :name # optional but required for fault.
|
||||
attr_reader :soapbody
|
||||
attr_reader :soapheader
|
||||
attr_reader :soapfault
|
||||
|
||||
def initialize
|
||||
super
|
||||
@message = nil
|
||||
@name = nil
|
||||
@soapbody = nil
|
||||
@soapheader = []
|
||||
@soapfault = nil
|
||||
end
|
||||
|
||||
def targetnamespace
|
||||
parent.targetnamespace
|
||||
end
|
||||
|
||||
def find_message
|
||||
root.message(@message)
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when SOAPBodyName
|
||||
o = WSDL::SOAP::Body.new
|
||||
@soapbody = o
|
||||
o
|
||||
when SOAPHeaderName
|
||||
o = WSDL::SOAP::Header.new
|
||||
@soapheader << o
|
||||
o
|
||||
when SOAPFaultName
|
||||
o = WSDL::SOAP::Fault.new
|
||||
@soap_fault = o
|
||||
o
|
||||
when DocumentationName
|
||||
o = Documentation.new
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when MessageAttrName
|
||||
@message = value
|
||||
when NameAttrName
|
||||
@name = XSD::QName.new(targetnamespace, value)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
170
lib/wsdl/parser.rb
Normal file
170
lib/wsdl/parser.rb
Normal file
|
@ -0,0 +1,170 @@
|
|||
=begin
|
||||
WSDL4R - WSDL XML Instance parser library.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/qname'
|
||||
require 'xsd/ns'
|
||||
require 'xsd/charset'
|
||||
require 'xsd/datatypes'
|
||||
require 'xsd/xmlparser'
|
||||
require 'wsdl/wsdl'
|
||||
require 'wsdl/data'
|
||||
require 'wsdl/xmlSchema/data'
|
||||
require 'wsdl/soap/data'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class Parser
|
||||
include WSDL
|
||||
|
||||
class ParseError < Error; end
|
||||
class FormatDecodeError < ParseError; end
|
||||
class UnknownElementError < FormatDecodeError; end
|
||||
class UnknownAttributeError < FormatDecodeError; end
|
||||
class UnexpectedElementError < FormatDecodeError; end
|
||||
class ElementConstraintError < FormatDecodeError; end
|
||||
class AttributeConstraintError < FormatDecodeError; end
|
||||
|
||||
private
|
||||
|
||||
class ParseFrame
|
||||
attr_reader :ns
|
||||
attr_reader :name
|
||||
attr_accessor :node
|
||||
|
||||
private
|
||||
|
||||
def initialize(ns, name, node)
|
||||
@ns = ns
|
||||
@name = name
|
||||
@node = node
|
||||
end
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
def initialize(opt = {})
|
||||
@parser = XSD::XMLParser.create_parser(self, opt)
|
||||
@parsestack = nil
|
||||
@lastnode = nil
|
||||
end
|
||||
|
||||
def parse(string_or_readable)
|
||||
@parsestack = []
|
||||
@lastnode = nil
|
||||
@textbuf = ''
|
||||
@parser.do_parse(string_or_readable)
|
||||
@lastnode
|
||||
end
|
||||
|
||||
def charset
|
||||
@parser.charset
|
||||
end
|
||||
|
||||
def start_element(name, attrs)
|
||||
lastframe = @parsestack.last
|
||||
ns = parent = nil
|
||||
if lastframe
|
||||
ns = lastframe.ns.clone_ns
|
||||
parent = lastframe.node
|
||||
else
|
||||
ns = XSD::NS.new
|
||||
parent = nil
|
||||
end
|
||||
attrs = XSD::XMLParser.filter_ns(ns, attrs)
|
||||
node = decode_tag(ns, name, attrs, parent)
|
||||
@parsestack << ParseFrame.new(ns, name, node)
|
||||
end
|
||||
|
||||
def characters(text)
|
||||
lastframe = @parsestack.last
|
||||
if lastframe
|
||||
# Need not to be cloned because character does not have attr.
|
||||
ns = lastframe.ns
|
||||
decode_text(ns, text)
|
||||
else
|
||||
p text if $DEBUG
|
||||
end
|
||||
end
|
||||
|
||||
def end_element(name)
|
||||
lastframe = @parsestack.pop
|
||||
unless name == lastframe.name
|
||||
raise UnexpectedElementError.new("Closing element name '#{ name }' does not match with opening element '#{ lastframe.name }'.")
|
||||
end
|
||||
decode_tag_end(lastframe.ns, lastframe.node)
|
||||
@lastnode = lastframe.node
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def decode_tag(ns, name, attrs, parent)
|
||||
o = nil
|
||||
element = ns.parse(name)
|
||||
if !parent
|
||||
if element == DefinitionsName
|
||||
o = Definitions.parse_element(element)
|
||||
else
|
||||
raise UnknownElementError.new("Unknown element #{ element }.")
|
||||
end
|
||||
else
|
||||
o = parent.parse_element(element)
|
||||
unless o
|
||||
STDERR.puts("Unknown element #{ element }.")
|
||||
o = Documentation.new # which accepts any element.
|
||||
end
|
||||
o.parent = parent
|
||||
end
|
||||
attrs.each do |key, value|
|
||||
attr = unless /:/ =~ key
|
||||
XSD::QName.new(nil, key)
|
||||
else
|
||||
ns.parse(key)
|
||||
end
|
||||
value_ele = if /:/ !~ value
|
||||
value
|
||||
elsif /^http:\/\// =~ value # ToDo: ugly.
|
||||
value
|
||||
else
|
||||
begin
|
||||
ns.parse(value)
|
||||
rescue
|
||||
value
|
||||
end
|
||||
end
|
||||
unless o.parse_attr(attr, value_ele)
|
||||
STDERR.puts("Unknown attr #{ attr }.")
|
||||
# raise UnknownAttributeError.new("Unknown attr #{ attr }.")
|
||||
end
|
||||
end
|
||||
o
|
||||
end
|
||||
|
||||
def decode_tag_end(ns, node)
|
||||
node.parse_epilogue
|
||||
end
|
||||
|
||||
def decode_text(ns, text)
|
||||
@textbuf << text
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
63
lib/wsdl/part.rb
Normal file
63
lib/wsdl/part.rb
Normal file
|
@ -0,0 +1,63 @@
|
|||
=begin
|
||||
WSDL4R - WSDL part definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class Part < Info
|
||||
attr_reader :name # required
|
||||
attr_reader :element # optional
|
||||
attr_reader :type # optional
|
||||
|
||||
def initialize
|
||||
super
|
||||
@name = nil
|
||||
@element = nil
|
||||
@type = nil
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when DocumentationName
|
||||
o = Documentation.new
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when NameAttrName
|
||||
@name = value
|
||||
when ElementAttrName
|
||||
@element = value
|
||||
when TypeAttrName
|
||||
@type = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
95
lib/wsdl/port.rb
Normal file
95
lib/wsdl/port.rb
Normal file
|
@ -0,0 +1,95 @@
|
|||
=begin
|
||||
WSDL4R - WSDL port definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class Port < Info
|
||||
attr_reader :name # required
|
||||
attr_reader :binding # required
|
||||
attr_reader :soap_address
|
||||
|
||||
def initialize
|
||||
super
|
||||
@name = nil
|
||||
@binding = nil
|
||||
@soap_address = nil
|
||||
end
|
||||
|
||||
def targetnamespace
|
||||
parent.targetnamespace
|
||||
end
|
||||
|
||||
def porttype
|
||||
root.porttype(find_binding.type)
|
||||
end
|
||||
|
||||
def find_binding
|
||||
root.binding(@binding)
|
||||
end
|
||||
|
||||
def inputoperation_map
|
||||
result = {}
|
||||
find_binding.operations.each do |op_bind|
|
||||
op_info = op_bind.soapoperation.input_info
|
||||
result[op_info.op_name] = op_info
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def outputoperation_map
|
||||
result = {}
|
||||
find_binding.operations.each do |op_bind|
|
||||
op_info = op_bind.soapoperation.output_info
|
||||
result[op_info.op_name] = op_info
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when SOAPAddressName
|
||||
o = WSDL::SOAP::Address.new
|
||||
@soap_address = o
|
||||
o
|
||||
when DocumentationName
|
||||
o = Documentation.new
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when NameAttrName
|
||||
@name = XSD::QName.new(targetnamespace, value)
|
||||
when BindingAttrName
|
||||
@binding = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
83
lib/wsdl/portType.rb
Normal file
83
lib/wsdl/portType.rb
Normal file
|
@ -0,0 +1,83 @@
|
|||
=begin
|
||||
WSDL4R - WSDL portType definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
require 'xsd/namedelements'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class PortType < Info
|
||||
attr_reader :name # required
|
||||
attr_reader :operations
|
||||
|
||||
def targetnamespace
|
||||
parent.targetnamespace
|
||||
end
|
||||
|
||||
def initialize
|
||||
super
|
||||
@name = nil
|
||||
@operations = XSD::NamedElements.new
|
||||
end
|
||||
|
||||
def find_binding
|
||||
root.bindings.find { |item| item.type == @name }
|
||||
end
|
||||
|
||||
def locations
|
||||
bind_name = find_binding.name
|
||||
result = []
|
||||
root.services.each do |service|
|
||||
service.ports.each do |port|
|
||||
if port.binding == bind_name
|
||||
result << port.soap_address.location if port.soap_address
|
||||
end
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when OperationName
|
||||
o = Operation.new
|
||||
@operations << o
|
||||
o
|
||||
when DocumentationName
|
||||
o = Documentation.new
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when NameAttrName
|
||||
@name = XSD::QName.new(targetnamespace, value)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
72
lib/wsdl/service.rb
Normal file
72
lib/wsdl/service.rb
Normal file
|
@ -0,0 +1,72 @@
|
|||
=begin
|
||||
WSDL4R - WSDL service definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
require 'xsd/namedelements'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class Service < Info
|
||||
attr_reader :name # required
|
||||
attr_reader :ports
|
||||
attr_reader :soap_address
|
||||
|
||||
def initialize
|
||||
super
|
||||
@name = nil
|
||||
@ports = XSD::NamedElements.new
|
||||
@soap_address = nil
|
||||
end
|
||||
|
||||
def targetnamespace
|
||||
parent.targetnamespace
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when PortName
|
||||
o = Port.new
|
||||
@ports << o
|
||||
o
|
||||
when SOAPAddressName
|
||||
o = WSDL::SOAP::Address.new
|
||||
@soap_address = o
|
||||
o
|
||||
when DocumentationName
|
||||
o = Documentation.new
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when NameAttrName
|
||||
@name = XSD::QName.new(targetnamespace, value)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
51
lib/wsdl/soap/address.rb
Normal file
51
lib/wsdl/soap/address.rb
Normal file
|
@ -0,0 +1,51 @@
|
|||
=begin
|
||||
WSDL4R - WSDL SOAP address definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module SOAP
|
||||
|
||||
|
||||
class Address < Info
|
||||
attr_reader :location
|
||||
|
||||
def initialize
|
||||
super
|
||||
@location = nil
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
nil
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when LocationAttrName
|
||||
@location = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
59
lib/wsdl/soap/binding.rb
Normal file
59
lib/wsdl/soap/binding.rb
Normal file
|
@ -0,0 +1,59 @@
|
|||
=begin
|
||||
WSDL4R - WSDL SOAP binding definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module SOAP
|
||||
|
||||
|
||||
class Binding < Info
|
||||
attr_reader :style
|
||||
attr_reader :transport
|
||||
|
||||
def initialize
|
||||
super
|
||||
@style = nil
|
||||
@transport = nil
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
nil
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when StyleAttrName
|
||||
if ["document", "rpc"].include?(value)
|
||||
@style = value.intern
|
||||
else
|
||||
raise AttributeConstraintError.new("Unexpected value #{ value }.")
|
||||
end
|
||||
when TransportAttrName
|
||||
@transport = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
63
lib/wsdl/soap/body.rb
Normal file
63
lib/wsdl/soap/body.rb
Normal file
|
@ -0,0 +1,63 @@
|
|||
=begin
|
||||
WSDL4R - WSDL SOAP body definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module SOAP
|
||||
|
||||
|
||||
class Body < Info
|
||||
attr_reader :parts
|
||||
attr_reader :use # required
|
||||
attr_reader :encodingstyle
|
||||
attr_reader :namespace
|
||||
|
||||
def initialize
|
||||
super
|
||||
@parts = nil
|
||||
@use = nil
|
||||
@encodingstyle = nil
|
||||
@namespace = nil
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
nil
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when PartsAttrName
|
||||
@parts = value
|
||||
when UseAttrName
|
||||
@use = value
|
||||
when EncodingStyleAttrName
|
||||
@encodingstyle = value
|
||||
when NamespaceAttrName
|
||||
@namespace = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
96
lib/wsdl/soap/complexType.rb
Normal file
96
lib/wsdl/soap/complexType.rb
Normal file
|
@ -0,0 +1,96 @@
|
|||
=begin
|
||||
WSDL4R - SOAP complexType definition for WSDL.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/xmlSchema/complexType'
|
||||
|
||||
|
||||
module WSDL
|
||||
module XMLSchema
|
||||
|
||||
|
||||
class ComplexType < Info
|
||||
def compoundtype
|
||||
@compoundtype ||= check_type
|
||||
end
|
||||
|
||||
def check_type
|
||||
if content
|
||||
:TYPE_STRUCT
|
||||
elsif complexcontent and complexcontent.base == ::SOAP::ValueArrayName
|
||||
:TYPE_ARRAY
|
||||
else
|
||||
raise NotImplementedError.new("Unknown kind of complexType.")
|
||||
end
|
||||
end
|
||||
|
||||
def child_type(name = nil)
|
||||
case compoundtype
|
||||
when :TYPE_STRUCT
|
||||
if ele = find_element(name)
|
||||
ele.type
|
||||
elsif ele = find_element_by_name(name.name)
|
||||
ele.type
|
||||
else
|
||||
nil
|
||||
end
|
||||
when :TYPE_ARRAY
|
||||
@contenttype ||= content_arytype
|
||||
end
|
||||
end
|
||||
|
||||
def child_defined_complextype(name)
|
||||
unless compoundtype == :TYPE_STRUCT
|
||||
raise RuntimeError.new("Assert: not for struct")
|
||||
end
|
||||
unless ele = find_element(name)
|
||||
if name.namespace.nil?
|
||||
ele = find_element_by_name(name.name)
|
||||
end
|
||||
end
|
||||
unless ele
|
||||
raise RuntimeError.new("Cannot find #{name} as a children of #{@name}.")
|
||||
end
|
||||
ele.local_complextype
|
||||
end
|
||||
|
||||
def find_arytype
|
||||
complexcontent.attributes.each do |attribute|
|
||||
if attribute.ref == ::SOAP::AttrArrayTypeName
|
||||
return attribute.arytype
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def content_arytype
|
||||
unless compoundtype == :TYPE_ARRAY
|
||||
raise RuntimeError.new("Assert: not for array")
|
||||
end
|
||||
arytype = find_arytype
|
||||
ns = arytype.namespace
|
||||
name = arytype.name.sub(/\[(?:,)*\]$/, '')
|
||||
XSD::QName.new(ns, name)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
52
lib/wsdl/soap/data.rb
Normal file
52
lib/wsdl/soap/data.rb
Normal file
|
@ -0,0 +1,52 @@
|
|||
=begin
|
||||
WSDL4R - WSDL SOAP binding data definitions.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/qname'
|
||||
require 'wsdl/soap/definitions'
|
||||
require 'wsdl/soap/binding'
|
||||
require 'wsdl/soap/operation'
|
||||
require 'wsdl/soap/body'
|
||||
require 'wsdl/soap/header'
|
||||
require 'wsdl/soap/headerfault'
|
||||
require 'wsdl/soap/fault'
|
||||
require 'wsdl/soap/address'
|
||||
require 'wsdl/soap/complexType'
|
||||
|
||||
|
||||
module WSDL
|
||||
module SOAP
|
||||
|
||||
|
||||
HeaderFaultName = XSD::QName.new(SOAPBindingNamespace, 'headerfault')
|
||||
|
||||
LocationAttrName = XSD::QName.new(nil, 'location')
|
||||
StyleAttrName = XSD::QName.new(nil, 'style')
|
||||
TransportAttrName = XSD::QName.new(nil, 'transport')
|
||||
UseAttrName = XSD::QName.new(nil, 'use')
|
||||
PartsAttrName = XSD::QName.new(nil, 'parts')
|
||||
PartAttrName = XSD::QName.new(nil, 'part')
|
||||
NameAttrName = XSD::QName.new(nil, 'name')
|
||||
MessageAttrName = XSD::QName.new(nil, 'message')
|
||||
EncodingStyleAttrName = XSD::QName.new(nil, 'encodingStyle')
|
||||
NamespaceAttrName = XSD::QName.new(nil, 'namespace')
|
||||
SOAPActionAttrName = XSD::QName.new(nil, 'soapAction')
|
||||
|
||||
|
||||
end
|
||||
end
|
130
lib/wsdl/soap/definitions.rb
Normal file
130
lib/wsdl/soap/definitions.rb
Normal file
|
@ -0,0 +1,130 @@
|
|||
=begin
|
||||
WSDL4R - WSDL additional definitions for SOAP.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
require 'xsd/namedelements'
|
||||
require 'soap/mapping'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class Definitions < Info
|
||||
def soap_rpc_complextypes(binding)
|
||||
types = rpc_operation_complextypes(binding)
|
||||
types << array_complextype
|
||||
types << fault_complextype
|
||||
types << exception_complextype
|
||||
types
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def rpc_operation_complextypes(binding)
|
||||
types = XSD::NamedElements.new
|
||||
binding.operations.each do |op_bind|
|
||||
if op_bind_rpc?(op_bind)
|
||||
operation = op_bind.find_operation
|
||||
if op_bind.input
|
||||
type = XMLSchema::ComplexType.new(operation_input_name(operation))
|
||||
message = messages[operation.input.message]
|
||||
type.sequence_elements = elements_from_message(message)
|
||||
types << type
|
||||
end
|
||||
if op_bind.output
|
||||
type = XMLSchema::ComplexType.new(operation_output_name(operation))
|
||||
message = messages[operation.output.message]
|
||||
type.sequence_elements = elements_from_message(message)
|
||||
types << type
|
||||
end
|
||||
end
|
||||
end
|
||||
types
|
||||
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)
|
||||
op_bind.soapoperation and op_bind.soapoperation.operation_style == :rpc
|
||||
end
|
||||
|
||||
def elements_from_message(message)
|
||||
message.parts.collect { |part|
|
||||
qname = XSD::QName.new(nil, part.name)
|
||||
XMLSchema::Element.new(qname, part.type)
|
||||
}
|
||||
end
|
||||
|
||||
def array_complextype
|
||||
type = XMLSchema::ComplexType.new(::SOAP::ValueArrayName)
|
||||
type.complexcontent = XMLSchema::ComplexContent.new
|
||||
type.complexcontent.base = ::SOAP::ValueArrayName
|
||||
attr = XMLSchema::Attribute.new
|
||||
attr.ref = ::SOAP::AttrArrayTypeName
|
||||
anytype = XSD::AnyTypeName.dup
|
||||
anytype.name += '[]'
|
||||
attr.arytype = anytype
|
||||
type.complexcontent.attributes << attr
|
||||
type
|
||||
end
|
||||
|
||||
=begin
|
||||
<xs:complexType name="Fault" final="extension">
|
||||
<xs:sequence>
|
||||
<xs:element name="faultcode" type="xs:QName" />
|
||||
<xs:element name="faultstring" type="xs:string" />
|
||||
<xs:element name="faultactor" type="xs:anyURI" minOccurs="0" />
|
||||
<xs:element name="detail" type="tns:detail" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
=end
|
||||
def fault_complextype
|
||||
type = XMLSchema::ComplexType.new(::SOAP::EleFaultName)
|
||||
faultcode = XMLSchema::Element.new(::SOAP::EleFaultCodeName, XSD::XSDQName::Type)
|
||||
faultstring = XMLSchema::Element.new(::SOAP::EleFaultStringName, XSD::XSDString::Type)
|
||||
faultactor = XMLSchema::Element.new(::SOAP::EleFaultActorName, XSD::XSDAnyURI::Type)
|
||||
faultactor.minoccurs = 0
|
||||
detail = XMLSchema::Element.new(::SOAP::EleFaultDetailName, XSD::AnyTypeName)
|
||||
detail.minoccurs = 0
|
||||
type.all_elements = [faultcode, faultstring, faultactor, detail]
|
||||
type.final = 'extension'
|
||||
type
|
||||
end
|
||||
|
||||
def exception_complextype
|
||||
type = XMLSchema::ComplexType.new(XSD::QName.new(
|
||||
::SOAP::Mapping::RubyCustomTypeNamespace, 'SOAPException'))
|
||||
excn_name = XMLSchema::Element.new(XSD::QName.new(nil, 'exceptionTypeName'), XSD::XSDString::Type)
|
||||
cause = XMLSchema::Element.new(XSD::QName.new(nil, 'cause'), XSD::AnyTypeName)
|
||||
backtrace = XMLSchema::Element.new(XSD::QName.new(nil, 'backtrace'), ::SOAP::ValueArrayName)
|
||||
message = XMLSchema::Element.new(XSD::QName.new(nil, 'message'), XSD::XSDString::Type)
|
||||
type.all_elements = [excn_name, cause, backtrace, message]
|
||||
type
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
63
lib/wsdl/soap/fault.rb
Normal file
63
lib/wsdl/soap/fault.rb
Normal file
|
@ -0,0 +1,63 @@
|
|||
=begin
|
||||
WSDL4R - WSDL SOAP body definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module SOAP
|
||||
|
||||
|
||||
class Fault < Info
|
||||
attr_reader :name # required
|
||||
attr_reader :use # required
|
||||
attr_reader :encodingstyle
|
||||
attr_reader :namespace
|
||||
|
||||
def initialize
|
||||
super
|
||||
@name = nil
|
||||
@use = nil
|
||||
@encodingstyle = nil
|
||||
@namespace = nil
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
nil
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when NameAttrName
|
||||
@name = value
|
||||
when UseAttrName
|
||||
@use = value
|
||||
when EncodingStyleAttrName
|
||||
@encodingstyle = value
|
||||
when NamespaceAttrName
|
||||
@namespace = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
90
lib/wsdl/soap/header.rb
Normal file
90
lib/wsdl/soap/header.rb
Normal file
|
@ -0,0 +1,90 @@
|
|||
=begin
|
||||
WSDL4R - WSDL SOAP body definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module SOAP
|
||||
|
||||
|
||||
class Header < Info
|
||||
attr_reader :headerfault
|
||||
|
||||
attr_reader :message # required
|
||||
attr_reader :part # required
|
||||
attr_reader :use # required
|
||||
attr_reader :encodingstyle
|
||||
attr_reader :namespace
|
||||
|
||||
def initialize
|
||||
super
|
||||
@message = nil
|
||||
@part = nil
|
||||
@use = nil
|
||||
@encodingstyle = nil
|
||||
@namespace = nil
|
||||
@headerfault = nil
|
||||
end
|
||||
|
||||
def find_message
|
||||
root.message(@message)
|
||||
end
|
||||
|
||||
def find_part
|
||||
find_message.parts.each do |part|
|
||||
if part.name == @part
|
||||
return part
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when HeaderFaultName
|
||||
o = WSDL::SOAP::HeaderFault.new
|
||||
@headerfault = o
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when MessageAttrName
|
||||
@message = value
|
||||
when PartAttrName
|
||||
@part = value
|
||||
when UseAttrName
|
||||
@use = value
|
||||
when EncodingStyleAttrName
|
||||
@encodingstyle = value
|
||||
when NamespaceAttrName
|
||||
@namespace = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
67
lib/wsdl/soap/headerfault.rb
Normal file
67
lib/wsdl/soap/headerfault.rb
Normal file
|
@ -0,0 +1,67 @@
|
|||
=begin
|
||||
WSDL4R - WSDL SOAP body definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module SOAP
|
||||
|
||||
|
||||
class HeaderFault < Info
|
||||
attr_reader :message # required
|
||||
attr_reader :part # required
|
||||
attr_reader :use # required
|
||||
attr_reader :encodingstyle
|
||||
attr_reader :namespace
|
||||
|
||||
def initialize
|
||||
super
|
||||
@message = nil
|
||||
@part = nil
|
||||
@use = nil
|
||||
@encodingstyle = nil
|
||||
@namespace = nil
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
nil
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when MessageAttrName
|
||||
@message = value
|
||||
when PartAttrName
|
||||
@part = value
|
||||
when UseAttrName
|
||||
@use = value
|
||||
when EncodingStyleAttrName
|
||||
@encodingstyle = value
|
||||
when NamespaceAttrName
|
||||
@namespace = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
131
lib/wsdl/soap/operation.rb
Normal file
131
lib/wsdl/soap/operation.rb
Normal file
|
@ -0,0 +1,131 @@
|
|||
=begin
|
||||
WSDL4R - WSDL SOAP operation definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module SOAP
|
||||
|
||||
|
||||
class Operation < Info
|
||||
class OperationInfo
|
||||
attr_reader :style
|
||||
attr_reader :op_name
|
||||
attr_reader :optype_name
|
||||
attr_reader :headerparts
|
||||
attr_reader :bodyparts
|
||||
attr_reader :faultpart
|
||||
attr_reader :soapaction
|
||||
|
||||
def initialize(style, op_name, optype_name, headerparts, bodyparts, faultpart, soapaction)
|
||||
@style = style
|
||||
@op_name = op_name
|
||||
@optype_name = optype_name
|
||||
@headerparts = headerparts
|
||||
@bodyparts = bodyparts
|
||||
@faultpart = faultpart
|
||||
@soapaction = soapaction
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :soapaction
|
||||
attr_reader :style
|
||||
|
||||
def initialize
|
||||
super
|
||||
@soapaction = nil
|
||||
@style = nil
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
nil
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when StyleAttrName
|
||||
if ["document", "rpc"].include?(value)
|
||||
@style = value.intern
|
||||
else
|
||||
raise AttributeConstraintError.new("Unexpected value #{ value }.")
|
||||
end
|
||||
when SOAPActionAttrName
|
||||
@soapaction = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def input_info
|
||||
name_info = parent.find_operation.input_info
|
||||
param_info(name_info, parent.input)
|
||||
end
|
||||
|
||||
def output_info
|
||||
name_info = parent.find_operation.output_info
|
||||
param_info(name_info, parent.output)
|
||||
end
|
||||
|
||||
def operation_style
|
||||
return @style if @style
|
||||
if parent_binding.soapbinding
|
||||
return parent_binding.soapbinding.style
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def parent_binding
|
||||
parent.parent
|
||||
end
|
||||
|
||||
def param_info(name_info, param)
|
||||
op_name = name_info.op_name
|
||||
optype_name = name_info.optype_name
|
||||
|
||||
soapheader = param.soapheader
|
||||
headerparts = soapheader.collect { |item| item.find_part }
|
||||
|
||||
soapbody = param.soapbody
|
||||
if soapbody.encodingstyle and
|
||||
soapbody.encodingstyle != ::SOAP::EncodingNamespace
|
||||
raise NotImplementedError.new(
|
||||
"EncodingStyle '#{ soapbody.encodingstyle }' not supported.")
|
||||
end
|
||||
if soapbody.namespace
|
||||
op_name = op_name.dup
|
||||
op_name.namespace = soapbody.namespace
|
||||
end
|
||||
if soapbody.parts
|
||||
raise NotImplementedError.new("soap:body parts")
|
||||
else
|
||||
bodyparts = name_info.parts
|
||||
end
|
||||
|
||||
faultpart = nil
|
||||
soapaction = parent.soapoperation.soapaction
|
||||
OperationInfo.new(operation_style, op_name, optype_name, headerparts, bodyparts, faultpart, soapaction)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
54
lib/wsdl/types.rb
Normal file
54
lib/wsdl/types.rb
Normal file
|
@ -0,0 +1,54 @@
|
|||
=begin
|
||||
WSDL4R - WSDL types definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
class Types < Info
|
||||
attr_reader :schemas
|
||||
|
||||
def initialize
|
||||
super
|
||||
@schemas = []
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when SchemaName
|
||||
o = XMLSchema::Schema.new
|
||||
@schemas << o
|
||||
o
|
||||
when DocumentationName
|
||||
o = Documentation.new
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
34
lib/wsdl/wsdl.rb
Normal file
34
lib/wsdl/wsdl.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
=begin
|
||||
WSDL4R - Base definitions.
|
||||
Copyright (C) 2000, 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/qname'
|
||||
|
||||
|
||||
module WSDL
|
||||
|
||||
|
||||
Version = '0.0.2'
|
||||
|
||||
Namespace = 'http://schemas.xmlsoap.org/wsdl/'
|
||||
SOAPBindingNamespace ='http://schemas.xmlsoap.org/wsdl/soap/'
|
||||
|
||||
class Error < StandardError; end
|
||||
|
||||
|
||||
end
|
76
lib/wsdl/xmlSchema/all.rb
Normal file
76
lib/wsdl/xmlSchema/all.rb
Normal file
|
@ -0,0 +1,76 @@
|
|||
=begin
|
||||
WSDL4R - XMLSchema complexType definition for WSDL.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module XMLSchema
|
||||
|
||||
|
||||
class All < Info
|
||||
attr_reader :minoccurs
|
||||
attr_reader :maxoccurs
|
||||
attr_reader :elements
|
||||
|
||||
def initialize
|
||||
super()
|
||||
@minoccurs = 1
|
||||
@maxoccurs = 1
|
||||
@elements = []
|
||||
end
|
||||
|
||||
def targetnamespace
|
||||
parent.targetnamespace
|
||||
end
|
||||
|
||||
def <<(element)
|
||||
@elements << element
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when AnyName
|
||||
o = Any.new
|
||||
@elements << o
|
||||
o
|
||||
when ElementName
|
||||
o = Element.new
|
||||
@elements << o
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when MaxOccursAttrName
|
||||
@maxoccurs = value
|
||||
when MinOccursAttrName
|
||||
@minoccurs = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
67
lib/wsdl/xmlSchema/any.rb
Normal file
67
lib/wsdl/xmlSchema/any.rb
Normal file
|
@ -0,0 +1,67 @@
|
|||
=begin
|
||||
WSDL4R - XMLSchema any definition for WSDL.
|
||||
Copyright (C) 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module XMLSchema
|
||||
|
||||
|
||||
class Any < Info
|
||||
attr_accessor :maxoccurs
|
||||
attr_accessor :minoccurs
|
||||
attr_accessor :namespace
|
||||
attr_accessor :process_contents
|
||||
|
||||
def initialize
|
||||
super()
|
||||
@maxoccurs = 1
|
||||
@minoccurs = 1
|
||||
@namespace = '##any'
|
||||
@process_contents = 'strict'
|
||||
end
|
||||
|
||||
def targetnamespace
|
||||
parent.targetnamespace
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
nil
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when MaxOccursAttrName
|
||||
@maxoccurs = value
|
||||
when MinOccursAttrName
|
||||
@minoccurs = value
|
||||
when NamespaceAttrName
|
||||
@namespace = value
|
||||
when ProcessContentsAttrName
|
||||
@process_contents = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
85
lib/wsdl/xmlSchema/attribute.rb
Normal file
85
lib/wsdl/xmlSchema/attribute.rb
Normal file
|
@ -0,0 +1,85 @@
|
|||
=begin
|
||||
WSDL4R - XMLSchema attribute definition for WSDL.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module XMLSchema
|
||||
|
||||
|
||||
class Attribute < Info
|
||||
attr_accessor :ref
|
||||
attr_accessor :use
|
||||
attr_accessor :form
|
||||
attr_accessor :name
|
||||
attr_accessor :type
|
||||
attr_accessor :default
|
||||
attr_accessor :fixed
|
||||
|
||||
attr_accessor :arytype
|
||||
|
||||
def initialize
|
||||
super
|
||||
@ref = nil
|
||||
@use = nil
|
||||
@form = nil
|
||||
@name = nil
|
||||
@type = nil
|
||||
@default = nil
|
||||
@fixed = nil
|
||||
|
||||
@arytype = nil
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
nil
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when RefAttrName
|
||||
@ref = value
|
||||
when UseAttrName
|
||||
@use = value
|
||||
when FormAttrName
|
||||
@form = value
|
||||
when NameAttrName
|
||||
@name = value
|
||||
when TypeAttrName
|
||||
@type = value
|
||||
when DefaultAttrName
|
||||
@default = value
|
||||
when FixedAttrName
|
||||
@fixed = value
|
||||
when ArrayTypeAttrName
|
||||
@arytype = if value.is_a?(XSD::QName)
|
||||
value
|
||||
else
|
||||
XSD::QName.new(XSD::Namespace, value)
|
||||
end
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
76
lib/wsdl/xmlSchema/choice.rb
Normal file
76
lib/wsdl/xmlSchema/choice.rb
Normal file
|
@ -0,0 +1,76 @@
|
|||
=begin
|
||||
WSDL4R - XMLSchema complexType definition for WSDL.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module XMLSchema
|
||||
|
||||
|
||||
class Choice < Info
|
||||
attr_reader :minoccurs
|
||||
attr_reader :maxoccurs
|
||||
attr_reader :elements
|
||||
|
||||
def initialize
|
||||
super()
|
||||
@minoccurs = 1
|
||||
@maxoccurs = 1
|
||||
@elements = []
|
||||
end
|
||||
|
||||
def targetnamespace
|
||||
parent.targetnamespace
|
||||
end
|
||||
|
||||
def <<(element)
|
||||
@elements << element
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when AnyName
|
||||
o = Any.new
|
||||
@elements << o
|
||||
o
|
||||
when ElementName
|
||||
o = Element.new
|
||||
@elements << o
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when MaxOccursAttrName
|
||||
@maxoccurs = value
|
||||
when MinOccursAttrName
|
||||
@minoccurs = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
90
lib/wsdl/xmlSchema/complexContent.rb
Normal file
90
lib/wsdl/xmlSchema/complexContent.rb
Normal file
|
@ -0,0 +1,90 @@
|
|||
=begin
|
||||
WSDL4R - XMLSchema complexContent definition for WSDL.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
require 'xsd/namedelements'
|
||||
|
||||
|
||||
module WSDL
|
||||
module XMLSchema
|
||||
|
||||
|
||||
class ComplexContent < Info
|
||||
attr_accessor :base
|
||||
attr_reader :derivetype
|
||||
attr_reader :content
|
||||
attr_reader :attributes
|
||||
|
||||
def initialize
|
||||
super
|
||||
@base = nil
|
||||
@derivetype = nil
|
||||
@content = nil
|
||||
@attributes = XSD::NamedElements.new
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when RestrictionName, ExtensionName
|
||||
@derivetype = element.name
|
||||
self
|
||||
when AllName
|
||||
if @derivetype.nil?
|
||||
raise Parser::ElementConstraintError.new("base attr not found.")
|
||||
end
|
||||
@content = All.new
|
||||
@content
|
||||
when SequenceName
|
||||
if @derivetype.nil?
|
||||
raise Parser::ElementConstraintError.new("base attr not found.")
|
||||
end
|
||||
@content = Sequence.new
|
||||
@content
|
||||
when ChoiceName
|
||||
if @derivetype.nil?
|
||||
raise Parser::ElementConstraintError.new("base attr not found.")
|
||||
end
|
||||
@content = Choice.new
|
||||
@content
|
||||
when AttributeName
|
||||
if @derivetype.nil?
|
||||
raise Parser::ElementConstraintError.new("base attr not found.")
|
||||
end
|
||||
o = Attribute.new
|
||||
@attributes << o
|
||||
o
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
if @derivetype.nil?
|
||||
return nil
|
||||
end
|
||||
case attr
|
||||
when BaseAttrName
|
||||
@base = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
130
lib/wsdl/xmlSchema/complexType.rb
Normal file
130
lib/wsdl/xmlSchema/complexType.rb
Normal file
|
@ -0,0 +1,130 @@
|
|||
=begin
|
||||
WSDL4R - XMLSchema complexType definition for WSDL.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
require 'wsdl/xmlSchema/content'
|
||||
require 'xsd/namedelements'
|
||||
|
||||
|
||||
module WSDL
|
||||
module XMLSchema
|
||||
|
||||
|
||||
class ComplexType < Info
|
||||
attr_accessor :name
|
||||
attr_accessor :complexcontent
|
||||
attr_accessor :content
|
||||
attr_accessor :final
|
||||
attr_accessor :mixed
|
||||
attr_reader :attributes
|
||||
|
||||
def initialize(name = nil)
|
||||
super()
|
||||
@name = name
|
||||
@complexcontent = nil
|
||||
@content = nil
|
||||
@final = nil
|
||||
@mixed = false
|
||||
@attributes = XSD::NamedElements.new
|
||||
end
|
||||
|
||||
def targetnamespace
|
||||
parent.targetnamespace
|
||||
end
|
||||
|
||||
def each_element
|
||||
if @content
|
||||
@content.elements.each do |element|
|
||||
yield(element.name, element)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def find_element(name)
|
||||
if @content
|
||||
@content.elements.each do |element|
|
||||
return element if name == element.name
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def find_element_by_name(name)
|
||||
if @content
|
||||
@content.elements.each do |element|
|
||||
return element if name == element.name.name
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def sequence_elements=(elements)
|
||||
@content = Sequence.new
|
||||
elements.each do |element|
|
||||
@content << element
|
||||
end
|
||||
end
|
||||
|
||||
def all_elements=(elements)
|
||||
@content = All.new
|
||||
elements.each do |element|
|
||||
@content << element
|
||||
end
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when AllName
|
||||
@content = All.new
|
||||
@content
|
||||
when SequenceName
|
||||
@content = Sequence.new
|
||||
@content
|
||||
when ChoiceName
|
||||
@content = Choice.new
|
||||
@content
|
||||
when ComplexContentName
|
||||
@complexcontent = ComplexContent.new
|
||||
@complexcontent
|
||||
when AttributeName
|
||||
o = Attribute.new
|
||||
@attributes << o
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when FinalAttrName
|
||||
@final = value
|
||||
when MixedAttrName
|
||||
@mixed = (value == 'true')
|
||||
when NameAttrName
|
||||
@name = XSD::QName.new(targetnamespace, value)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
107
lib/wsdl/xmlSchema/content.rb
Normal file
107
lib/wsdl/xmlSchema/content.rb
Normal file
|
@ -0,0 +1,107 @@
|
|||
=begin
|
||||
WSDL4R - XMLSchema complexType definition for WSDL.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module XMLSchema
|
||||
|
||||
|
||||
class Content < Info
|
||||
attr_accessor :final
|
||||
attr_accessor :mixed
|
||||
attr_accessor :type
|
||||
attr_reader :contents
|
||||
attr_reader :elements
|
||||
|
||||
def initialize
|
||||
super()
|
||||
@final = nil
|
||||
@mixed = false
|
||||
@type = nil
|
||||
@contents = []
|
||||
@elements = []
|
||||
end
|
||||
|
||||
def targetnamespace
|
||||
parent.targetnamespace
|
||||
end
|
||||
|
||||
def <<(content)
|
||||
@contents << content
|
||||
update_elements
|
||||
end
|
||||
|
||||
def each
|
||||
@contents.each do |content|
|
||||
yield content
|
||||
end
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when AllName, SequenceName, ChoiceName
|
||||
o = Content.new
|
||||
o.type = element.name
|
||||
@contents << o
|
||||
o
|
||||
when AnyName
|
||||
o = Any.new
|
||||
@contents << o
|
||||
o
|
||||
when ElementName
|
||||
o = Element.new
|
||||
@contents << o
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when FinalAttrName
|
||||
@final = value
|
||||
when MixedAttrName
|
||||
@mixed = (value == 'true')
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_epilogue
|
||||
update_elements
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_elements
|
||||
@elements = []
|
||||
@contents.each do |content|
|
||||
if content.is_a?(Element)
|
||||
@elements << [content.name, content]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
75
lib/wsdl/xmlSchema/data.rb
Normal file
75
lib/wsdl/xmlSchema/data.rb
Normal file
|
@ -0,0 +1,75 @@
|
|||
=begin
|
||||
WSDL4R - XMLSchema data definitions.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/xmlSchema/schema'
|
||||
require 'wsdl/xmlSchema/import'
|
||||
require 'wsdl/xmlSchema/complexType'
|
||||
require 'wsdl/xmlSchema/complexContent'
|
||||
require 'wsdl/xmlSchema/any'
|
||||
require 'wsdl/xmlSchema/element'
|
||||
require 'wsdl/xmlSchema/all'
|
||||
require 'wsdl/xmlSchema/choice'
|
||||
require 'wsdl/xmlSchema/sequence'
|
||||
require 'wsdl/xmlSchema/attribute'
|
||||
require 'wsdl/xmlSchema/unique'
|
||||
|
||||
|
||||
module WSDL
|
||||
module XMLSchema
|
||||
|
||||
|
||||
AllName = XSD::QName.new(XSD::Namespace, 'all')
|
||||
AnyName = XSD::QName.new(XSD::Namespace, 'any')
|
||||
ArrayTypeAttrName = XSD::QName.new(Namespace, 'arrayType')
|
||||
AttributeName = XSD::QName.new(XSD::Namespace, 'attribute')
|
||||
ChoiceName = XSD::QName.new(XSD::Namespace, 'choice')
|
||||
ComplexContentName = XSD::QName.new(XSD::Namespace, 'complexContent')
|
||||
ComplexTypeName = XSD::QName.new(XSD::Namespace, 'complexType')
|
||||
ElementName = XSD::QName.new(XSD::Namespace, 'element')
|
||||
ExtensionName = XSD::QName.new(XSD::Namespace, 'extension')
|
||||
ImportName = XSD::QName.new(XSD::Namespace, 'import')
|
||||
RestrictionName = XSD::QName.new(XSD::Namespace, 'restriction')
|
||||
SequenceName = XSD::QName.new(XSD::Namespace, 'sequence')
|
||||
SchemaName = XSD::QName.new(XSD::Namespace, 'schema')
|
||||
SimpleTypeName = XSD::QName.new(XSD::Namespace, 'simpleType')
|
||||
UniqueName = XSD::QName.new(XSD::Namespace, 'unique')
|
||||
|
||||
AttributeFormDefaultAttrName = XSD::QName.new(nil, 'attributeFormDefault')
|
||||
BaseAttrName = XSD::QName.new(nil, 'base')
|
||||
DefaultAttrName = XSD::QName.new(nil, 'default')
|
||||
ElementFormDefaultAttrName = XSD::QName.new(nil, 'elementFormDefault')
|
||||
FinalAttrName = XSD::QName.new(nil, 'final')
|
||||
FixedAttrName = XSD::QName.new(nil, 'fixed')
|
||||
FormAttrName = XSD::QName.new(nil, 'form')
|
||||
IdAttrName = XSD::QName.new(nil, 'id')
|
||||
MaxOccursAttrName = XSD::QName.new(nil, 'maxOccurs')
|
||||
MinOccursAttrName = XSD::QName.new(nil, 'minOccurs')
|
||||
MixedAttrName = XSD::QName.new(nil, 'mixed')
|
||||
NameAttrName = XSD::QName.new(nil, 'name')
|
||||
NamespaceAttrName = XSD::QName.new(nil, 'namespace')
|
||||
NillableAttrName = XSD::QName.new(nil, 'nillable')
|
||||
RefAttrName = XSD::QName.new(nil, 'ref')
|
||||
SchemaLocationAttrName = XSD::QName.new(nil, 'schemaLocation')
|
||||
TargetNamespaceAttrName = XSD::QName.new(nil, 'targetNamespace')
|
||||
TypeAttrName = XSD::QName.new(nil, 'type')
|
||||
UseAttrName = XSD::QName.new(nil, 'use')
|
||||
|
||||
|
||||
end
|
||||
end
|
115
lib/wsdl/xmlSchema/element.rb
Normal file
115
lib/wsdl/xmlSchema/element.rb
Normal file
|
@ -0,0 +1,115 @@
|
|||
=begin
|
||||
WSDL4R - XMLSchema element definition for WSDL.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module XMLSchema
|
||||
|
||||
|
||||
class Element < Info
|
||||
attr_accessor :name # required
|
||||
attr_accessor :type
|
||||
attr_accessor :local_complextype
|
||||
attr_accessor :constraint
|
||||
attr_accessor :maxoccurs
|
||||
attr_accessor :minoccurs
|
||||
attr_accessor :nillable
|
||||
|
||||
def initialize(name = nil, type = XSD::AnyTypeName)
|
||||
super()
|
||||
@name = name
|
||||
@type = type
|
||||
@local_complextype = nil
|
||||
@constraint = nil
|
||||
@maxoccurs = 1
|
||||
@minoccurs = 1
|
||||
@nillable = nil
|
||||
end
|
||||
|
||||
def targetnamespace
|
||||
parent.targetnamespace
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when ComplexTypeName
|
||||
@type = nil
|
||||
@local_complextype = ComplexType.new
|
||||
@local_complextype
|
||||
when UniqueName
|
||||
@constraint = Unique.new
|
||||
@constraint
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when NameAttrName
|
||||
#@name = XSD::QName.new(nil, value)
|
||||
@name = XSD::QName.new(targetnamespace, value)
|
||||
when TypeAttrName
|
||||
@type = if value.is_a?(XSD::QName)
|
||||
value
|
||||
else
|
||||
XSD::QName.new(XSD::Namespace, value)
|
||||
end
|
||||
when MaxOccursAttrName
|
||||
case parent
|
||||
when All
|
||||
if value != '1'
|
||||
raise Parser::AttrConstraintError.new(
|
||||
"Cannot parse #{ value } for #{ attr }.")
|
||||
end
|
||||
@maxoccurs = value
|
||||
when Sequence
|
||||
@maxoccurs = value
|
||||
else
|
||||
raise NotImplementedError.new
|
||||
end
|
||||
@maxoccurs
|
||||
when MinOccursAttrName
|
||||
case parent
|
||||
when All
|
||||
if ['0', '1'].include?(value)
|
||||
@minoccurs = value
|
||||
else
|
||||
raise Parser::AttrConstraintError.new(
|
||||
"Cannot parse #{ value } for #{ attr }.")
|
||||
end
|
||||
when Sequence
|
||||
@minoccurs = value
|
||||
else
|
||||
raise NotImplementedError.new
|
||||
end
|
||||
@minoccurs
|
||||
when NillableAttrName
|
||||
@nillable = (value == 'true')
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
55
lib/wsdl/xmlSchema/import.rb
Normal file
55
lib/wsdl/xmlSchema/import.rb
Normal file
|
@ -0,0 +1,55 @@
|
|||
=begin
|
||||
WSDL4R - XMLSchema import definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module XMLSchema
|
||||
|
||||
|
||||
class Import < Info
|
||||
attr_reader :namespace
|
||||
attr_reader :schemalocation
|
||||
|
||||
def initialize
|
||||
super
|
||||
@namespace = nil
|
||||
@schemalocation = nil
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
nil
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when NamespaceAttrName
|
||||
@namespace = value
|
||||
when SchemaLocationAttrName
|
||||
@schemalocation = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
172
lib/wsdl/xmlSchema/parser.rb
Normal file
172
lib/wsdl/xmlSchema/parser.rb
Normal file
|
@ -0,0 +1,172 @@
|
|||
=begin
|
||||
WSDL4R - WSDL XML Instance parser library.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/qname'
|
||||
require 'xsd/ns'
|
||||
require 'xsd/charset'
|
||||
require 'xsd/datatypes'
|
||||
require 'xsd/xmlparser'
|
||||
require 'wsdl/xmlSchema/data'
|
||||
|
||||
|
||||
module WSDL
|
||||
module XMLSchema
|
||||
|
||||
|
||||
class Parser
|
||||
include XSD
|
||||
|
||||
class ParseError < Error; end
|
||||
class FormatDecodeError < Error; end
|
||||
class UnknownElementError < FormatDecodeError; end
|
||||
class UnknownAttributeError < FormatDecodeError; end
|
||||
class UnexpectedElementError < FormatDecodeError; end
|
||||
class ElementConstraintError < FormatDecodeError; end
|
||||
class AttributeConstraintError < FormatDecodeError; end
|
||||
|
||||
private
|
||||
|
||||
class ParseFrame
|
||||
attr_reader :ns
|
||||
attr_reader :name
|
||||
attr_accessor :node
|
||||
|
||||
private
|
||||
|
||||
def initialize(ns, name, node)
|
||||
@ns = ns
|
||||
@name = name
|
||||
@node = node
|
||||
end
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
def initialize(opt = {})
|
||||
@parser = XSD::XMLParser.create_parser(self, opt)
|
||||
@parsestack = nil
|
||||
@lastnode = nil
|
||||
end
|
||||
|
||||
def parse(string_or_readable)
|
||||
@parsestack = []
|
||||
@lastnode = nil
|
||||
@textbuf = ''
|
||||
@parser.do_parse(string_or_readable)
|
||||
@lastnode
|
||||
end
|
||||
|
||||
def charset
|
||||
@parser.charset
|
||||
end
|
||||
|
||||
def start_element(name, attrs)
|
||||
lastframe = @parsestack.last
|
||||
ns = parent = nil
|
||||
if lastframe
|
||||
ns = lastframe.ns.clone_ns
|
||||
parent = lastframe.node
|
||||
else
|
||||
ns = XSD::NS.new
|
||||
parent = nil
|
||||
end
|
||||
attrs = XSD::XMLParser.filter_ns(ns, attrs)
|
||||
node = decode_tag(ns, name, attrs, parent)
|
||||
@parsestack << ParseFrame.new(ns, name, node)
|
||||
end
|
||||
|
||||
def characters(text)
|
||||
lastframe = @parsestack.last
|
||||
if lastframe
|
||||
# Need not to be cloned because character does not have attr.
|
||||
ns = lastframe.ns
|
||||
decode_text(ns, text)
|
||||
else
|
||||
p text if $DEBUG
|
||||
end
|
||||
end
|
||||
|
||||
def end_element(name)
|
||||
lastframe = @parsestack.pop
|
||||
unless name == lastframe.name
|
||||
raise UnexpectedElementError.new("Closing element name '#{ name }' does not match with opening element '#{ lastframe.name }'.")
|
||||
end
|
||||
decode_tag_end(lastframe.ns, lastframe.node)
|
||||
@lastnode = lastframe.node
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def decode_tag(ns, name, attrs, parent)
|
||||
o = nil
|
||||
element = ns.parse(name)
|
||||
if !parent
|
||||
if element == SchemaName
|
||||
o = Schema.parse_element(element)
|
||||
else
|
||||
raise UnknownElementError.new("Unknown element #{ element }.")
|
||||
end
|
||||
else
|
||||
o = parent.parse_element(element)
|
||||
unless o
|
||||
raise UnknownElementError.new("Unknown element #{ element }.")
|
||||
end
|
||||
o.parent = parent
|
||||
end
|
||||
attrs.each do |key, value|
|
||||
attr = unless /:/ =~ key
|
||||
XSD::QName.new(nil, key)
|
||||
else
|
||||
ns.parse(key)
|
||||
end
|
||||
value_ele = if /:/ !~ value
|
||||
value
|
||||
elsif /^http:\/\// =~ value # ToDo: ugly.
|
||||
value
|
||||
else
|
||||
begin
|
||||
ns.parse(value)
|
||||
rescue
|
||||
value
|
||||
end
|
||||
end
|
||||
if attr == IdAttrName
|
||||
o.id = value_ele
|
||||
else
|
||||
unless o.parse_attr(attr, value_ele)
|
||||
STDERR.puts("Unknown attr #{ attr }.")
|
||||
# raise UnknownAttributeError.new("Unknown attr #{ attr }.")
|
||||
end
|
||||
end
|
||||
end
|
||||
o
|
||||
end
|
||||
|
||||
def decode_tag_end(ns, node)
|
||||
node.parse_epilogue
|
||||
end
|
||||
|
||||
def decode_text(ns, text)
|
||||
@textbuf << text
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
105
lib/wsdl/xmlSchema/schema.rb
Normal file
105
lib/wsdl/xmlSchema/schema.rb
Normal file
|
@ -0,0 +1,105 @@
|
|||
=begin
|
||||
WSDL4R - XMLSchema schema definition for WSDL.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
require 'xsd/namedelements'
|
||||
|
||||
|
||||
module WSDL
|
||||
module XMLSchema
|
||||
|
||||
|
||||
class Schema < Info
|
||||
attr_reader :targetnamespace # required
|
||||
attr_reader :complextypes
|
||||
attr_reader :elements
|
||||
attr_reader :attributes
|
||||
attr_reader :imports
|
||||
attr_accessor :attributeformdefault
|
||||
attr_accessor :elementformdefault
|
||||
|
||||
def initialize
|
||||
super
|
||||
@targetnamespace = nil
|
||||
@complextypes = XSD::NamedElements.new
|
||||
@elements = XSD::NamedElements.new
|
||||
@attributes = XSD::NamedElements.new
|
||||
@imports = []
|
||||
@elementformdefault = nil
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when ImportName
|
||||
o = Import.new
|
||||
@imports << o
|
||||
o
|
||||
when ComplexTypeName
|
||||
o = ComplexType.new
|
||||
@complextypes << o
|
||||
o
|
||||
when ElementName
|
||||
o = Element.new
|
||||
@elements << o
|
||||
o
|
||||
when AttributeName
|
||||
o = Attribute.new
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when TargetNamespaceAttrName
|
||||
@targetnamespace = value
|
||||
when AttributeFormDefaultAttrName
|
||||
@attributeformdefault = value
|
||||
when ElementFormDefaultAttrName
|
||||
@elementformdefault = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def collect_elements
|
||||
result = XSD::NamedElements.new
|
||||
result.concat(@elements)
|
||||
result
|
||||
end
|
||||
|
||||
def collect_complextypes
|
||||
result = XSD::NamedElements.new
|
||||
result.concat(@complextypes)
|
||||
result
|
||||
end
|
||||
|
||||
def self.parse_element(element)
|
||||
if element == SchemaName
|
||||
Schema.new
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
76
lib/wsdl/xmlSchema/sequence.rb
Normal file
76
lib/wsdl/xmlSchema/sequence.rb
Normal file
|
@ -0,0 +1,76 @@
|
|||
=begin
|
||||
WSDL4R - XMLSchema complexType definition for WSDL.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module XMLSchema
|
||||
|
||||
|
||||
class Sequence < Info
|
||||
attr_reader :minoccurs
|
||||
attr_reader :maxoccurs
|
||||
attr_reader :elements
|
||||
|
||||
def initialize
|
||||
super()
|
||||
@minoccurs = 1
|
||||
@maxoccurs = 1
|
||||
@elements = []
|
||||
end
|
||||
|
||||
def targetnamespace
|
||||
parent.targetnamespace
|
||||
end
|
||||
|
||||
def <<(element)
|
||||
@elements << element
|
||||
end
|
||||
|
||||
def parse_element(element)
|
||||
case element
|
||||
when AnyName
|
||||
o = Any.new
|
||||
@elements << o
|
||||
o
|
||||
when ElementName
|
||||
o = Element.new
|
||||
@elements << o
|
||||
o
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attr(attr, value)
|
||||
case attr
|
||||
when MaxOccursAttrName
|
||||
@maxoccurs = value
|
||||
when MinOccursAttrName
|
||||
@minoccurs = value
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
45
lib/wsdl/xmlSchema/unique.rb
Normal file
45
lib/wsdl/xmlSchema/unique.rb
Normal file
|
@ -0,0 +1,45 @@
|
|||
=begin
|
||||
WSDL4R - XMLSchema unique element.
|
||||
Copyright (C) 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'wsdl/info'
|
||||
|
||||
|
||||
module WSDL
|
||||
module XMLSchema
|
||||
|
||||
|
||||
class Unique < 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
|
175
lib/xsd/charset.rb
Normal file
175
lib/xsd/charset.rb
Normal file
|
@ -0,0 +1,175 @@
|
|||
=begin
|
||||
XSD4R - Charset handling library.
|
||||
Copyright (C) 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
module XSD
|
||||
|
||||
|
||||
module Charset
|
||||
@encoding = $KCODE
|
||||
|
||||
class XSDError < StandardError; end
|
||||
class CharsetError < XSDError; end
|
||||
class UnknownCharsetError < CharsetError; end
|
||||
class CharsetConversionError < CharsetError; end
|
||||
|
||||
public
|
||||
|
||||
###
|
||||
## Maps
|
||||
#
|
||||
EncodingConvertMap = {}
|
||||
def Charset.init
|
||||
begin
|
||||
require 'xsd/iconvcharset'
|
||||
@encoding = 'UTF8'
|
||||
EncodingConvertMap[['UTF8', 'EUC' ]] = Proc.new { |str| IconvCharset.safe_iconv("euc-jp", "utf-8", str) }
|
||||
EncodingConvertMap[['EUC' , 'UTF8']] = Proc.new { |str| IconvCharset.safe_iconv("utf-8", "euc-jp", str) }
|
||||
EncodingConvertMap[['EUC' , 'SJIS']] = Proc.new { |str| IconvCharset.safe_iconv("shift-jis", "euc-jp", str) }
|
||||
if /(mswin|bccwin|mingw|cygwin)/ =~ RUBY_PLATFORM
|
||||
EncodingConvertMap[['UTF8', 'SJIS']] = Proc.new { |str| IconvCharset.safe_iconv("cp932", "utf-8", str) }
|
||||
EncodingConvertMap[['SJIS', 'UTF8']] = Proc.new { |str| IconvCharset.safe_iconv("utf-8", "cp932", str) }
|
||||
EncodingConvertMap[['SJIS', 'EUC' ]] = Proc.new { |str| IconvCharset.safe_iconv("euc-jp", "cp932", str) }
|
||||
else
|
||||
EncodingConvertMap[['UTF8', 'SJIS']] = Proc.new { |str| IconvCharset.safe_iconv("shift-jis", "utf-8", str) }
|
||||
EncodingConvertMap[['SJIS', 'UTF8']] = Proc.new { |str| IconvCharset.safe_iconv("utf-8", "shift-jis", str) }
|
||||
EncodingConvertMap[['SJIS', 'EUC' ]] = Proc.new { |str| IconvCharset.safe_iconv("euc-jp", "shift-jis", str) }
|
||||
end
|
||||
rescue LoadError
|
||||
begin
|
||||
require 'nkf'
|
||||
EncodingConvertMap[['EUC' , 'SJIS']] = Proc.new { |str| NKF.nkf('-sXm0', str) }
|
||||
EncodingConvertMap[['SJIS', 'EUC' ]] = Proc.new { |str| NKF.nkf('-eXm0', str) }
|
||||
rescue LoadError
|
||||
end
|
||||
|
||||
begin
|
||||
require 'uconv'
|
||||
@encoding = 'UTF8'
|
||||
EncodingConvertMap[['UTF8', 'EUC' ]] = Uconv.method(:u8toeuc)
|
||||
EncodingConvertMap[['UTF8', 'SJIS']] = Uconv.method(:u8tosjis)
|
||||
EncodingConvertMap[['EUC' , 'UTF8']] = Uconv.method(:euctou8)
|
||||
EncodingConvertMap[['SJIS', 'UTF8']] = Uconv.method(:sjistou8)
|
||||
rescue LoadError
|
||||
end
|
||||
end
|
||||
end
|
||||
self.init
|
||||
|
||||
CharsetMap = {
|
||||
'NONE' => 'us-ascii',
|
||||
'EUC' => 'euc-jp',
|
||||
'SJIS' => 'shift_jis',
|
||||
'UTF8' => 'utf-8',
|
||||
}
|
||||
|
||||
|
||||
###
|
||||
## handlers
|
||||
#
|
||||
def Charset.encoding
|
||||
@encoding
|
||||
end
|
||||
|
||||
def Charset.encoding_label
|
||||
charset_label(@encoding)
|
||||
end
|
||||
|
||||
def Charset.encoding_to_xml(str, charset)
|
||||
encoding_conv(str, @encoding, charset_str(charset))
|
||||
end
|
||||
|
||||
def Charset.encoding_from_xml(str, charset)
|
||||
encoding_conv(str, charset_str(charset), @encoding)
|
||||
end
|
||||
|
||||
def Charset.encoding_conv(str, enc_from, enc_to)
|
||||
if enc_from == enc_to or enc_from == 'NONE' or enc_to == 'NONE'
|
||||
str
|
||||
elsif converter = EncodingConvertMap[[enc_from, enc_to]]
|
||||
converter.call(str)
|
||||
else
|
||||
raise CharsetConversionError.new(
|
||||
"Converter not found: #{ enc_from } -> #{ enc_to }")
|
||||
end
|
||||
end
|
||||
|
||||
def Charset.charset_label(encoding)
|
||||
CharsetMap[encoding.upcase]
|
||||
end
|
||||
|
||||
def Charset.charset_str(label)
|
||||
CharsetMap.index(label.downcase)
|
||||
end
|
||||
|
||||
# Original regexps: http://www.din.or.jp/~ohzaki/perl.htm
|
||||
# ascii_euc = '[\x00-\x7F]'
|
||||
ascii_euc = '[\x9\xa\xd\x20-\x7F]' # XML 1.0 restricted.
|
||||
twobytes_euc = '(?:[\x8E\xA1-\xFE][\xA1-\xFE])'
|
||||
threebytes_euc = '(?:\x8F[\xA1-\xFE][\xA1-\xFE])'
|
||||
character_euc = "(?:#{ ascii_euc }|#{ twobytes_euc }|#{ threebytes_euc })"
|
||||
EUCRegexp = Regexp.new("\\A#{ character_euc }*\\z", nil, "NONE")
|
||||
|
||||
# onebyte_sjis = '[\x00-\x7F\xA1-\xDF]'
|
||||
onebyte_sjis = '[\x9\xa\xd\x20-\x7F\xA1-\xDF]' # XML 1.0 restricted.
|
||||
twobytes_sjis = '(?:[\x81-\x9F\xE0-\xFC][\x40-\x7E\x80-\xFC])'
|
||||
character_sjis = "(?:#{ onebyte_sjis }|#{ twobytes_sjis })"
|
||||
SJISRegexp = Regexp.new("\\A#{ character_sjis }*\\z", nil, "NONE")
|
||||
|
||||
# 0xxxxxxx
|
||||
#ascii_utf8 = '[\0-\x7F]'
|
||||
ascii_utf8 = '[\x9\xA\xD\x20-\x7F]' # XML 1.0 restricted.
|
||||
# 110yyyyy 10xxxxxx
|
||||
twobytes_utf8 = '(?:[\xC0-\xDF][\x80-\xBF])'
|
||||
# 1110zzzz 10yyyyyy 10xxxxxx
|
||||
threebytes_utf8 = '(?:[\xE0-\xEF][\x80-\xBF][\x80-\xBF])'
|
||||
# 11110uuu 10uuuzzz 10yyyyyy 10xxxxxx
|
||||
fourbytes_utf8 = '(?:[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF])'
|
||||
character_utf8 = "(?:#{ ascii_utf8 }|#{ twobytes_utf8 }|#{ threebytes_utf8 }|#{ fourbytes_utf8 })"
|
||||
UTF8Regexp = Regexp.new("\\A#{ character_utf8 }*\\z", nil, "NONE")
|
||||
|
||||
def Charset.is_utf8(str)
|
||||
UTF8Regexp =~ str
|
||||
end
|
||||
|
||||
def Charset.is_euc(str)
|
||||
EUCRegexp =~ str
|
||||
end
|
||||
|
||||
def Charset.is_sjis(str)
|
||||
SJISRegexp =~ str
|
||||
end
|
||||
|
||||
def Charset.is_ces(str, code = $KCODE)
|
||||
case code
|
||||
when 'NONE'
|
||||
true
|
||||
when 'UTF8'
|
||||
is_utf8(str)
|
||||
when 'EUC'
|
||||
is_euc(str)
|
||||
when 'SJIS'
|
||||
is_sjis(str)
|
||||
else
|
||||
raise UnknownCharsetError.new("Unknown charset: #{ code }")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
1094
lib/xsd/datatypes.rb
Normal file
1094
lib/xsd/datatypes.rb
Normal file
File diff suppressed because it is too large
Load diff
31
lib/xsd/datatypes1999.rb
Normal file
31
lib/xsd/datatypes1999.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
=begin
|
||||
XSD4R - XML Schema Datatype 1999 support
|
||||
Copyright (C) 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/datatypes'
|
||||
|
||||
|
||||
module XSD
|
||||
Namespace.replace('http://www.w3.org/1999/XMLSchema')
|
||||
InstanceNamespace.replace('http://www.w3.org/1999/XMLSchema-instance')
|
||||
AnyTypeLiteral.replace('ur-type')
|
||||
AnySimpleTypeLiteral.replace('ur-type')
|
||||
NilLiteral.replace('null')
|
||||
NilValue.replace('1')
|
||||
DateTimeLiteral.replace('timeInstant')
|
||||
end
|
44
lib/xsd/iconvcharset.rb
Normal file
44
lib/xsd/iconvcharset.rb
Normal file
|
@ -0,0 +1,44 @@
|
|||
=begin
|
||||
XSD4R - Charset handling with iconv.
|
||||
Copyright (C) 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'iconv'
|
||||
|
||||
|
||||
module XSD
|
||||
|
||||
|
||||
class IconvCharset
|
||||
def self.safe_iconv(to, from, str)
|
||||
iconv = Iconv.new(to, from)
|
||||
out = ""
|
||||
begin
|
||||
out << iconv.iconv(str)
|
||||
rescue Iconv::IllegalSequence => e
|
||||
out << e.success
|
||||
ch, str = e.failed.split(//, 2)
|
||||
out << '?'
|
||||
STDERR.puts("Failed to convert #{ch}")
|
||||
retry
|
||||
end
|
||||
return out
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
86
lib/xsd/namedelements.rb
Normal file
86
lib/xsd/namedelements.rb
Normal file
|
@ -0,0 +1,86 @@
|
|||
=begin
|
||||
XSD4R - WSDL named element collection.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
module XSD
|
||||
|
||||
|
||||
class NamedElements
|
||||
include Enumerable
|
||||
|
||||
def initialize
|
||||
@elements = []
|
||||
@cache = {}
|
||||
end
|
||||
|
||||
def dup
|
||||
o = NamedElements.new
|
||||
o.elements = @elements.dup
|
||||
o
|
||||
end
|
||||
|
||||
def size
|
||||
@elements.size
|
||||
end
|
||||
|
||||
def [](idx)
|
||||
if idx.is_a?(Numeric)
|
||||
@elements[idx]
|
||||
else
|
||||
@cache[idx] ||= @elements.find { |item| item.name == idx }
|
||||
end
|
||||
end
|
||||
|
||||
def find_name(name)
|
||||
@elements.find { |item| item.name.name == name }
|
||||
end
|
||||
|
||||
def each
|
||||
@elements.each do |element|
|
||||
yield(element)
|
||||
end
|
||||
end
|
||||
|
||||
def <<(rhs)
|
||||
@elements << rhs
|
||||
self
|
||||
end
|
||||
|
||||
def +(rhs)
|
||||
o = NamedElements.new
|
||||
o.elements = @elements + rhs.elements
|
||||
o
|
||||
end
|
||||
|
||||
def concat(rhs)
|
||||
@elements.concat(rhs.elements)
|
||||
self
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def elements=(rhs)
|
||||
@elements = rhs
|
||||
end
|
||||
|
||||
def elements
|
||||
@elements
|
||||
end
|
||||
end
|
||||
|
||||
end
|
141
lib/xsd/ns.rb
Normal file
141
lib/xsd/ns.rb
Normal file
|
@ -0,0 +1,141 @@
|
|||
=begin
|
||||
XSD4R - XML Schema Namespace library
|
||||
Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/datatypes'
|
||||
|
||||
|
||||
module XSD
|
||||
|
||||
|
||||
class NS
|
||||
class Assigner
|
||||
def initialize
|
||||
@count = 0
|
||||
end
|
||||
|
||||
def assign(ns)
|
||||
@count += 1
|
||||
"n#{ @count }"
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :default_namespace
|
||||
|
||||
class FormatError < Error; end
|
||||
|
||||
public
|
||||
|
||||
def initialize(tag2ns = {})
|
||||
@tag2ns = tag2ns
|
||||
@assigner = nil
|
||||
@ns2tag = {}
|
||||
@tag2ns.each do |tag, ns|
|
||||
@ns2tag[ns] = tag
|
||||
end
|
||||
@default_namespace = nil
|
||||
end
|
||||
|
||||
def assign(ns, tag = nil)
|
||||
if (tag == '')
|
||||
@default_namespace = ns
|
||||
tag
|
||||
else
|
||||
@assigner ||= Assigner.new
|
||||
tag ||= @assigner.assign(ns)
|
||||
@ns2tag[ns] = tag
|
||||
@tag2ns[tag] = ns
|
||||
tag
|
||||
end
|
||||
end
|
||||
|
||||
def assigned?(ns)
|
||||
@ns2tag.key?(ns)
|
||||
end
|
||||
|
||||
def assigned_tag?(tag)
|
||||
@tag2ns.key?(tag)
|
||||
end
|
||||
|
||||
def clone_ns
|
||||
cloned = NS.new(@tag2ns.dup)
|
||||
cloned.assigner = @assigner
|
||||
cloned.assign(@default_namespace, '') if @default_namespace
|
||||
cloned
|
||||
end
|
||||
|
||||
def name(name)
|
||||
if (name.namespace == @default_namespace)
|
||||
name.name
|
||||
elsif @ns2tag.key?(name.namespace)
|
||||
@ns2tag[name.namespace] + ':' << name.name
|
||||
else
|
||||
raise FormatError.new('Namespace: ' << name.namespace << ' not defined yet.')
|
||||
end
|
||||
end
|
||||
|
||||
def compare(ns, name, rhs)
|
||||
if (ns == @default_namespace)
|
||||
return true if (name == rhs)
|
||||
end
|
||||
@tag2ns.each do |assigned_tag, assigned_ns|
|
||||
if assigned_ns == ns && "#{ assigned_tag }:#{ name }" == rhs
|
||||
return true
|
||||
end
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
# $1 and $2 are necessary.
|
||||
ParseRegexp = Regexp.new('^([^:]+)(?::(.+))?$')
|
||||
|
||||
def parse(elem)
|
||||
ns = nil
|
||||
name = nil
|
||||
ParseRegexp =~ elem
|
||||
if $2
|
||||
ns = @tag2ns[$1]
|
||||
name = $2
|
||||
if !ns
|
||||
raise FormatError.new('Unknown namespace qualifier: ' << $1)
|
||||
end
|
||||
elsif $1
|
||||
ns = @default_namespace
|
||||
name = $1
|
||||
end
|
||||
if !name
|
||||
raise FormatError.new("Illegal element format: #{ elem }")
|
||||
end
|
||||
XSD::QName.new(ns, name)
|
||||
end
|
||||
|
||||
def each_ns
|
||||
@ns2tag.each do |ns, tag|
|
||||
yield(ns, tag)
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def assigner=(assigner)
|
||||
@assigner = assigner
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
77
lib/xsd/qname.rb
Normal file
77
lib/xsd/qname.rb
Normal file
|
@ -0,0 +1,77 @@
|
|||
=begin
|
||||
XSD4R - XML QName definition.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
module XSD
|
||||
|
||||
|
||||
class QName
|
||||
attr_accessor :namespace
|
||||
attr_accessor :name
|
||||
|
||||
def initialize(namespace = nil, name = nil)
|
||||
@namespace = namespace
|
||||
@name = name
|
||||
end
|
||||
|
||||
def dup_name(name)
|
||||
self.class.new(@namespace, name)
|
||||
end
|
||||
|
||||
def match(rhs)
|
||||
unless self.class === rhs
|
||||
return false
|
||||
end
|
||||
if rhs.namespace and (rhs.namespace != @namespace)
|
||||
return false
|
||||
end
|
||||
if rhs.name and (rhs.name != @name)
|
||||
return false
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def ==(rhs)
|
||||
(self.class === rhs && @namespace == rhs.namespace && @name == rhs.name)
|
||||
end
|
||||
|
||||
def ===(rhs)
|
||||
(self == rhs)
|
||||
end
|
||||
|
||||
def eql?(rhs)
|
||||
(self == rhs)
|
||||
end
|
||||
|
||||
def hash
|
||||
@namespace.hash ^ @name.hash
|
||||
end
|
||||
|
||||
def to_s
|
||||
"{#{ namespace }}#{ name }"
|
||||
end
|
||||
|
||||
NormalizedNameRegexp = /^\{([^}]*)\}(.*)$/
|
||||
def parse(str)
|
||||
NormalizedNameRegexp =~ str
|
||||
self.new($1, $2)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
72
lib/xsd/xmlparser.rb
Normal file
72
lib/xsd/xmlparser.rb
Normal file
|
@ -0,0 +1,72 @@
|
|||
=begin
|
||||
XSD4R - XML Instance parser library.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/xmlparser/parser'
|
||||
|
||||
|
||||
module XSD
|
||||
|
||||
|
||||
module XMLParser
|
||||
def create_parser(host, opt)
|
||||
XSD::XMLParser::Parser.create_parser(host, opt)
|
||||
end
|
||||
module_function :create_parser
|
||||
|
||||
# $1 is necessary.
|
||||
NSParseRegexp = Regexp.new('^xmlns:?(.*)$')
|
||||
|
||||
def filter_ns(ns, attrs)
|
||||
return attrs if attrs.nil? or attrs.empty?
|
||||
newattrs = {}
|
||||
attrs.each do |key, value|
|
||||
if (NSParseRegexp =~ key)
|
||||
# '' means 'default namespace'.
|
||||
tag = $1 || ''
|
||||
ns.assign(value, tag)
|
||||
else
|
||||
newattrs[key] = value
|
||||
end
|
||||
end
|
||||
newattrs
|
||||
end
|
||||
module_function :filter_ns
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
# Try to load XML processor.
|
||||
loaded = false
|
||||
[
|
||||
'xsd/xmlparser/xmlscanner',
|
||||
'xsd/xmlparser/xmlparser',
|
||||
'xsd/xmlparser/rexmlparser',
|
||||
].each do |lib|
|
||||
begin
|
||||
require lib
|
||||
loaded = true
|
||||
break
|
||||
rescue LoadError
|
||||
end
|
||||
end
|
||||
unless loaded
|
||||
raise RuntimeError.new("XML processor module not found.")
|
||||
end
|
107
lib/xsd/xmlparser/parser.rb
Normal file
107
lib/xsd/xmlparser/parser.rb
Normal file
|
@ -0,0 +1,107 @@
|
|||
=begin
|
||||
XSD4R - XML Instance parser library.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/qname'
|
||||
require 'xsd/ns'
|
||||
require 'xsd/charset'
|
||||
|
||||
|
||||
module XSD
|
||||
module XMLParser
|
||||
|
||||
|
||||
class Parser
|
||||
class ParseError < Error; end
|
||||
class FormatDecodeError < ParseError; end
|
||||
class UnknownElementError < FormatDecodeError; end
|
||||
class UnknownAttributeError < FormatDecodeError; end
|
||||
class UnexpectedElementError < FormatDecodeError; end
|
||||
class ElementConstraintError < FormatDecodeError; end
|
||||
|
||||
@@parser_factory = nil
|
||||
|
||||
def self.factory
|
||||
@@parser_factory
|
||||
end
|
||||
|
||||
def self.create_parser(host, opt = {})
|
||||
@@parser_factory.new(host, opt)
|
||||
end
|
||||
|
||||
def self.add_factory(factory)
|
||||
if $DEBUG
|
||||
puts "Set #{ factory } as XML processor."
|
||||
end
|
||||
@@parser_factory = factory
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
attr_accessor :charset
|
||||
|
||||
def initialize(host, opt = {})
|
||||
@host = host
|
||||
@charset = opt[:charset] || 'us-ascii'
|
||||
end
|
||||
|
||||
def parse(string_or_readable)
|
||||
@textbuf = ''
|
||||
prologue
|
||||
do_parse(string_or_readable)
|
||||
epilogue
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def do_parse(string_or_readable)
|
||||
raise NotImplementError.new(
|
||||
'Method do_parse must be defined in derived class.')
|
||||
end
|
||||
|
||||
def start_element(name, attrs)
|
||||
@host.start_element(name, attrs)
|
||||
end
|
||||
|
||||
def characters(text)
|
||||
@host.characters(text)
|
||||
end
|
||||
|
||||
def end_element(name)
|
||||
@host.end_element(name)
|
||||
end
|
||||
|
||||
def prologue
|
||||
end
|
||||
|
||||
def epilogue
|
||||
end
|
||||
|
||||
def xmldecl_encoding=(charset)
|
||||
if @charset.nil?
|
||||
@charset = charset
|
||||
else
|
||||
# Definition in a stream (like HTTP) has a priority.
|
||||
p "encoding definition: #{ charset } is ignored." if $DEBUG
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
65
lib/xsd/xmlparser/rexmlparser.rb
Normal file
65
lib/xsd/xmlparser/rexmlparser.rb
Normal file
|
@ -0,0 +1,65 @@
|
|||
=begin
|
||||
XSD4R - REXMLParser XML parser library.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/xmlparser'
|
||||
require 'rexml/streamlistener'
|
||||
require 'rexml/document'
|
||||
|
||||
|
||||
module XSD
|
||||
module XMLParser
|
||||
|
||||
|
||||
class REXMLParser < XSD::XMLParser::Parser
|
||||
include REXML::StreamListener
|
||||
|
||||
def do_parse(string_or_readable)
|
||||
source = nil
|
||||
source = REXML::SourceFactory.create_from(string_or_readable)
|
||||
source.encoding = charset if charset
|
||||
# Listener passes a String in utf-8.
|
||||
@charset = 'utf-8'
|
||||
REXML::Document.parse_stream(source, self)
|
||||
end
|
||||
|
||||
def epilogue
|
||||
end
|
||||
|
||||
def tag_start(name, attrs)
|
||||
start_element(name, attrs)
|
||||
end
|
||||
|
||||
def tag_end(name)
|
||||
end_element(name)
|
||||
end
|
||||
|
||||
def text(text)
|
||||
characters(text)
|
||||
end
|
||||
|
||||
def xmldecl(version, encoding, standalone)
|
||||
# Version should be checked.
|
||||
end
|
||||
|
||||
add_factory(self)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
61
lib/xsd/xmlparser/xmlparser.rb
Normal file
61
lib/xsd/xmlparser/xmlparser.rb
Normal file
|
@ -0,0 +1,61 @@
|
|||
=begin
|
||||
XSD4R - XMLParser XML parser library.
|
||||
Copyright (C) 2001, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/xmlparser'
|
||||
require 'xml/parser'
|
||||
|
||||
|
||||
module XSD
|
||||
module XMLParser
|
||||
|
||||
|
||||
class XMLParser < XSD::XMLParser::Parser
|
||||
class Listener < XML::Parser
|
||||
begin
|
||||
require 'xml/encoding-ja'
|
||||
include XML::Encoding_ja
|
||||
rescue LoadError
|
||||
# uconv may not be installed.
|
||||
end
|
||||
end
|
||||
|
||||
def do_parse(string_or_readable)
|
||||
# XMLParser passes a String in utf-8.
|
||||
@charset = 'utf-8'
|
||||
@parser = Listener.new
|
||||
@parser.parse(string_or_readable) do |type, name, data|
|
||||
case type
|
||||
when XML::Parser::START_ELEM
|
||||
start_element(name, data)
|
||||
when XML::Parser::END_ELEM
|
||||
end_element(name)
|
||||
when XML::Parser::CDATA
|
||||
characters(data)
|
||||
else
|
||||
raise FormatDecodeError.new("Unexpected XML: #{ type }/#{ name }/#{ data }.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
add_factory(self)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
158
lib/xsd/xmlparser/xmlscanner.rb
Normal file
158
lib/xsd/xmlparser/xmlscanner.rb
Normal file
|
@ -0,0 +1,158 @@
|
|||
=begin
|
||||
XSD4R - XMLScan XML parser library.
|
||||
Copyright (C) 2002, 2003 NAKAMURA, Hiroshi.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PRATICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 675 Mass
|
||||
Ave, Cambridge, MA 02139, USA.
|
||||
=end
|
||||
|
||||
|
||||
require 'xsd/xmlparser'
|
||||
require 'xmlscan/scanner'
|
||||
|
||||
|
||||
module XSD
|
||||
module XMLParser
|
||||
|
||||
|
||||
class XMLScanner < XSD::XMLParser::Parser
|
||||
include XMLScan::Visitor
|
||||
|
||||
def do_parse(string_or_readable)
|
||||
@attrs = {}
|
||||
@curattr = nil
|
||||
@scanner = XMLScan::XMLScanner.new(self)
|
||||
@scanner.kcode = ::XSD::Charset.charset_str(charset) if charset
|
||||
@scanner.parse(string_or_readable)
|
||||
end
|
||||
|
||||
def scanner_kcode=(charset)
|
||||
@scanner.kcode = ::XSD::Charset.charset_str(charset) if charset
|
||||
self.xmldecl_encoding = charset
|
||||
end
|
||||
|
||||
ENTITY_REF_MAP = {
|
||||
'lt' => '<',
|
||||
'gt' => '>',
|
||||
'amp' => '&',
|
||||
'quot' => '"',
|
||||
'apos' => '\''
|
||||
}
|
||||
|
||||
def parse_error(msg)
|
||||
raise ParseError.new(msg)
|
||||
end
|
||||
|
||||
def wellformed_error(msg)
|
||||
raise NotWellFormedError.new(msg)
|
||||
end
|
||||
|
||||
def valid_error(msg)
|
||||
raise NotValidError.new(msg)
|
||||
end
|
||||
|
||||
def warning(msg)
|
||||
p msg if $DEBUG
|
||||
end
|
||||
|
||||
# def on_xmldecl; end
|
||||
|
||||
def on_xmldecl_version(str)
|
||||
# 1.0 expected.
|
||||
end
|
||||
|
||||
def on_xmldecl_encoding(str)
|
||||
self.scanner_kcode = str
|
||||
end
|
||||
|
||||
# def on_xmldecl_standalone(str); end
|
||||
|
||||
# def on_xmldecl_other(name, value); end
|
||||
|
||||
# def on_xmldecl_end; end
|
||||
|
||||
# def on_doctype(root, pubid, sysid); end
|
||||
|
||||
# def on_prolog_space(str); end
|
||||
|
||||
# def on_comment(str); end
|
||||
|
||||
# def on_pi(target, pi); end
|
||||
|
||||
def on_chardata(str)
|
||||
characters(str)
|
||||
end
|
||||
|
||||
# def on_cdata(str); end
|
||||
|
||||
def on_etag(name)
|
||||
end_element(name)
|
||||
end
|
||||
|
||||
def on_entityref(ref)
|
||||
characters(ENTITY_REF_MAP[ref])
|
||||
end
|
||||
|
||||
def on_charref(code)
|
||||
characters([code].pack('U'))
|
||||
end
|
||||
|
||||
def on_charref_hex(code)
|
||||
on_charref(code)
|
||||
end
|
||||
|
||||
# def on_start_document; end
|
||||
|
||||
# def on_end_document; end
|
||||
|
||||
def on_stag(name)
|
||||
@attrs = {}
|
||||
end
|
||||
|
||||
def on_attribute(name)
|
||||
@attrs[name] = @curattr = ''
|
||||
end
|
||||
|
||||
def on_attr_value(str)
|
||||
@curattr << str
|
||||
end
|
||||
|
||||
def on_attr_entityref(ref)
|
||||
@curattr << ENTITY_REF_MAP[ref]
|
||||
end
|
||||
|
||||
def on_attr_charref(code)
|
||||
@curattr << [code].pack('U')
|
||||
end
|
||||
|
||||
def on_attr_charref_hex(code)
|
||||
on_attr_charref(code)
|
||||
end
|
||||
|
||||
# def on_attribute_end(name); end
|
||||
|
||||
def on_stag_end_empty(name)
|
||||
on_stag_end(name)
|
||||
on_etag(name)
|
||||
end
|
||||
|
||||
def on_stag_end(name)
|
||||
start_element(name, @attrs)
|
||||
end
|
||||
|
||||
add_factory(self)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
16
sample/soap/babelfish.rb
Normal file
16
sample/soap/babelfish.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
#!/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)
|
17
sample/soap/calc/calc.rb
Normal file
17
sample/soap/calc/calc.rb
Normal file
|
@ -0,0 +1,17 @@
|
|||
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
|
29
sample/soap/calc/calc2.rb
Normal file
29
sample/soap/calc/calc2.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
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
|
26
sample/soap/calc/client.rb
Normal file
26
sample/soap/calc/client.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
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)
|
29
sample/soap/calc/client2.rb
Normal file
29
sample/soap/calc/client2.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
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
|
15
sample/soap/calc/httpd.rb
Normal file
15
sample/soap/calc/httpd.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'webrick'
|
||||
require 'getopts'
|
||||
|
||||
getopts "", 'r:', 'p:8808'
|
||||
|
||||
s = WEBrick::HTTPServer.new(
|
||||
:BindAddress => "0.0.0.0",
|
||||
:Port => $OPT_p.to_i,
|
||||
:DocumentRoot => $OPT_r || ".",
|
||||
:CGIPathEnv => ENV['PATH']
|
||||
)
|
||||
trap(:INT){ s.shutdown }
|
||||
s.start
|
15
sample/soap/calc/server.cgi
Normal file
15
sample/soap/calc/server.cgi
Normal file
|
@ -0,0 +1,15 @@
|
|||
#!/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
|
17
sample/soap/calc/server.rb
Normal file
17
sample/soap/calc/server.rb
Normal file
|
@ -0,0 +1,17 @@
|
|||
#!/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__
|
||||
status = CalcServer.new('CalcServer', nil, '0.0.0.0', 7000).start
|
||||
end
|
20
sample/soap/calc/server2.rb
Normal file
20
sample/soap/calc/server2.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
#!/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__
|
||||
status = CalcServer2.new('CalcServer', 'http://tempuri.org/calcService', '0.0.0.0', 7000).start
|
||||
end
|
43
sample/soap/digraph.rb
Normal file
43
sample/soap/digraph.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
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").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")
|
19
sample/soap/exchange/client.rb
Normal file
19
sample/soap/exchange/client.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require "soap/rpc/driver"
|
||||
|
||||
ExchangeServiceNamespace = 'http://tempuri.org/exchangeService'
|
||||
|
||||
server = ARGV.shift || "http://localhost:7000/"
|
||||
# server = "http://localhost:8808/server.cgi"
|
||||
|
||||
logger = nil
|
||||
wiredump_dev = nil
|
||||
# logger = Logger.new(STDERR)
|
||||
# wiredump_dev = STDERR
|
||||
|
||||
drv = SOAP::RPC::Driver.new(server, ExchangeServiceNamespace)
|
||||
drv.wiredump_dev = wiredump_dev
|
||||
drv.add_method("rate", "country1", "country2")
|
||||
|
||||
p drv.rate("USA", "Japan")
|
17
sample/soap/exchange/exchange.rb
Normal file
17
sample/soap/exchange/exchange.rb
Normal file
|
@ -0,0 +1,17 @@
|
|||
require 'soap/rpc/driver'
|
||||
|
||||
ExchangeServiceNamespace = 'http://tempuri.org/exchangeService'
|
||||
|
||||
class Exchange
|
||||
ForeignServer = "http://services.xmethods.net/soap"
|
||||
Namespace = "urn:xmethods-CurrencyExchange"
|
||||
|
||||
def initialize
|
||||
@drv = SOAP::RPC::Driver.new(ForeignServer, Namespace)
|
||||
@drv.add_method("getRate", "country1", "country2")
|
||||
end
|
||||
|
||||
def rate(country1, country2)
|
||||
return @drv.getRate(country1, country2)
|
||||
end
|
||||
end
|
15
sample/soap/exchange/httpd.rb
Normal file
15
sample/soap/exchange/httpd.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'webrick'
|
||||
require 'getopts'
|
||||
|
||||
getopts "", 'r:', 'p:8808'
|
||||
|
||||
s = WEBrick::HTTPServer.new(
|
||||
:BindAddress => "0.0.0.0",
|
||||
:Port => $OPT_p.to_i,
|
||||
:DocumentRoot => $OPT_r || ".",
|
||||
:CGIPathEnv => ENV['PATH']
|
||||
)
|
||||
trap(:INT){ s.shutdown }
|
||||
s.start
|
14
sample/soap/exchange/server.cgi
Normal file
14
sample/soap/exchange/server.cgi
Normal file
|
@ -0,0 +1,14 @@
|
|||
#!/usr/local/bin/ruby
|
||||
|
||||
require 'soap/rpc/cgistub'
|
||||
require 'exchange'
|
||||
|
||||
class ExchangeServer < SOAP::RPC::CGIStub
|
||||
def initialize(*arg)
|
||||
super
|
||||
servant = Exchange.new
|
||||
add_servant(servant)
|
||||
end
|
||||
end
|
||||
|
||||
status = ExchangeServer.new('SampleStructServer', ExchangeServiceNamespace).start
|
16
sample/soap/exchange/server.rb
Normal file
16
sample/soap/exchange/server.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'soap/rpc/standaloneServer'
|
||||
require 'exchange'
|
||||
|
||||
class ExchangeServer < SOAP::RPC::StandaloneServer
|
||||
def initialize(*arg)
|
||||
super
|
||||
servant = Exchange.new
|
||||
add_servant(servant)
|
||||
end
|
||||
end
|
||||
|
||||
if $0 == __FILE__
|
||||
status = ExchangeServer.new('SampleStructServer', ExchangeServiceNamespace, '0.0.0.0', 7000).start
|
||||
end
|
6
sample/soap/helloworld/hw_c.rb
Normal file
6
sample/soap/helloworld/hw_c.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
require 'soap/rpc/driver'
|
||||
|
||||
s = SOAP::RPC::Driver.new('http://localhost:2000/', 'urn:hws')
|
||||
s.add_method("hello_world", "from")
|
||||
|
||||
p s.hello_world(self.to_s)
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue