Changeset 1720
- Timestamp:
- 09/10/06 20:46:24 (2 years ago)
- Files:
-
- trunk/lib/soap/mapping/encodedregistry.rb (copied) (copied from trunk/lib/soap/mapping/registry.rb) (4 diffs)
- trunk/lib/soap/mapping/factory.rb (modified) (3 diffs)
- trunk/lib/soap/mapping/literalregistry.rb (copied) (copied from trunk/lib/soap/mapping/wsdlliteralregistry.rb) (9 diffs)
- trunk/lib/soap/mapping/mapping.rb (modified) (10 diffs)
- trunk/lib/soap/mapping/registry.rb (modified) (4 diffs)
- trunk/lib/soap/mapping/wsdlencodedregistry.rb (modified) (6 diffs)
- trunk/lib/soap/mapping/wsdlliteralregistry.rb (modified) (4 diffs)
- trunk/lib/soap/marshal.rb (modified) (2 diffs)
- trunk/lib/soap/rpc/driver.rb (modified) (2 diffs)
- trunk/lib/soap/rpc/proxy.rb (modified) (3 diffs)
- trunk/lib/soap/rpc/router.rb (modified) (3 diffs)
- trunk/lib/wsdl/soap/cgiStubCreator.rb (modified) (1 diff)
- trunk/lib/wsdl/soap/driverCreator.rb (modified) (1 diff)
- trunk/lib/wsdl/soap/mappingRegistryCreator.rb (modified) (3 diffs)
- trunk/lib/wsdl/soap/standaloneServerStubCreator.rb (modified) (1 diff)
- trunk/lib/xsd/mapping.rb (modified) (2 diffs)
- trunk/test/wsdl/any/expectedDriver.rb (modified) (1 diff)
- trunk/test/wsdl/any/expectedService.rb (modified) (1 diff)
- trunk/test/wsdl/simpletype/rpc/expectedDriver.rb (modified) (1 diff)
- trunk/test/wsdl/simpletype/rpc/expectedService.rb (modified) (1 diff)
- trunk/test/wsdl/soap/wsdl2ruby/expectedDriver.rb (modified) (1 diff)
- trunk/test/wsdl/soap/wsdl2ruby/expectedService.cgi (modified) (1 diff)
- trunk/test/wsdl/soap/wsdl2ruby/expectedService.rb (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/lib/soap/mapping/encodedregistry.rb
r1706 r1720 1 # SOAP4R - Mapping registry.2 # Copyright (C) 2000 , 2001, 2002, 2003NAKAMURA, Hiroshi <nahi@ruby-lang.org>.1 # SOAP4R - encoded mapping registry. 2 # Copyright (C) 2000-2003, 2006 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. 3 3 4 4 # This program is copyrighted free software by NAKAMURA, Hiroshi. You can … … 15 15 16 16 module SOAP 17 18 19 module Marshallable20 # @@type_ns = Mapping::RubyCustomTypeNamespace21 end22 23 24 17 module Mapping 25 18 26 27 module MappedException; end28 29 30 RubyTypeName = XSD::QName.new(RubyTypeInstanceNamespace, 'rubyType')31 RubyExtendName = XSD::QName.new(RubyTypeInstanceNamespace, 'extends')32 RubyIVarName = XSD::QName.new(RubyTypeInstanceNamespace, 'ivars')33 34 19 35 20 # Inner class to pass an exception. 36 class SOAPException ; include Marshallable21 class SOAPException 37 22 attr_reader :excn_type_name, :cause 23 38 24 def initialize(e) 39 25 @excn_type_name = Mapping.name2elename(e.class.to_s) … … 61 47 62 48 63 # For anyType object: SOAP::Mapping::Object not ::Object 64 class Object; include Marshallable 65 def initialize 66 @__xmlele_type = {} 67 @__xmlele = [] 68 @__xmlattr = {} 69 end 70 71 def inspect 72 sprintf("#<%s:0x%x%s>", self.class.name, __id__, 73 @__xmlele.collect { |name, value| " #{name}=#{value.inspect}" }.join) 74 end 75 76 def __xmlattr 77 @__xmlattr 78 end 79 80 def __xmlele 81 @__xmlele 82 end 83 84 def [](qname) 85 unless qname.is_a?(XSD::QName) 86 qname = XSD::QName.new(nil, qname) 87 end 88 @__xmlele.each do |k, v| 89 return v if k == qname 90 end 91 # fallback 92 @__xmlele.each do |k, v| 93 return v if k.name == qname.name 94 end 95 nil 96 end 97 98 def []=(qname, value) 99 unless qname.is_a?(XSD::QName) 100 qname = XSD::QName.new(nil, qname) 101 end 102 found = false 103 @__xmlele.each do |pair| 104 if pair[0] == qname 105 found = true 106 pair[1] = value 107 end 108 end 109 unless found 110 __define_attr_accessor(qname) 111 @__xmlele << [qname, value] 112 end 113 @__xmlele_type[qname] = :single 114 end 115 116 def __add_xmlele_value(qname, value) 117 found = false 118 @__xmlele.map! do |k, v| 119 if k == qname 120 found = true 121 [k, __set_xmlele_value(k, v, value)] 122 else 123 [k, v] 124 end 125 end 126 unless found 127 __define_attr_accessor(qname) 128 @__xmlele << [qname, value] 129 @__xmlele_type[qname] = :single 130 end 131 value 132 end 133 134 private 135 136 # Mapping.define_attr_accessor calls define_method with proc and it exhausts 137 # much memory for each singleton Object. just instance_eval instead of it. 138 def __define_attr_accessor(qname) 139 # untaint depends GenSupport.safemethodname 140 name = XSD::CodeGen::GenSupport.safemethodname(qname.name).untaint 141 # untaint depends QName#dump 142 qnamedump = qname.dump.untaint 143 unless self.respond_to?(name) 144 instance_eval <<-EOS 145 def #{name} 146 self[#{qnamedump}] 147 end 148 EOS 149 end 150 unless self.respond_to?(name + "=") 151 instance_eval <<-EOS 152 def #{name}=(value) 153 self[#{qnamedump}] = value 154 end 155 EOS 156 end 157 end 158 159 def __set_xmlele_value(key, org, value) 160 case @__xmlele_type[key] 161 when :multi 162 org << value 163 org 164 when :single 165 @__xmlele_type[key] = :multi 166 [org, value] 167 else 168 raise RuntimeError.new("unknown type") 169 end 170 end 171 end 172 173 174 class MappingError < Error; end 175 176 177 class Registry 49 class EncodedRegistry 178 50 class Map 179 51 def initialize(registry) … … 532 404 end 533 405 end 534 535 406 end 536 537 538 DefaultRegistry = Registry.new539 RubyOriginalRegistry = Registry.new(:allow_original_mapping => true)540 407 541 408 trunk/lib/soap/mapping/factory.rb
r1706 r1720 55 55 def setdefinediv2soap(ele, obj, map) 56 56 # cache needed? 57 definition = Mapping.schema_ element_definition(obj.class)57 definition = Mapping.schema_definition_classdef(obj.class) 58 58 definition.elements.each do |eledef| 59 59 child = Mapping.get_attribute(obj, eledef.varname) … … 107 107 end 108 108 begin 109 unless XSD::Charset.is_ces(obj, Thread.current[:SOAPExternalCES]) 109 externalces = Thread.current[:SOAPMapping][:ExternalCES] 110 unless XSD::Charset.is_ces(obj, externalces) 110 111 return nil 111 112 end 112 encoded = XSD::Charset.encoding_conv(obj, 113 Thread.current[:SOAPExternalCES],XSD::Charset.encoding)113 encoded = XSD::Charset.encoding_conv(obj, externalces, 114 XSD::Charset.encoding) 114 115 soap_obj = soap_class.new(encoded) 115 116 rescue XSD::ValueSpaceError … … 123 124 obj = Mapping.create_empty_object(obj_class) 124 125 decoded = XSD::Charset.encoding_conv(node.data, XSD::Charset.encoding, 125 Thread.current[:SOAP ExternalCES])126 Thread.current[:SOAPMapping][:ExternalCES]) 126 127 obj.replace(decoded) 127 128 mark_unmarshalled_obj(node, obj) trunk/lib/soap/mapping/literalregistry.rb
r1719 r1720 1 # SOAP4R - WSDLliteral mapping registry.1 # SOAP4R - literal mapping registry. 2 2 # Copyright (C) 2004-2006 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. 3 3 … … 18 18 19 19 20 class WSDLLiteralRegistry <Registry21 attr_reader :definedelements22 attr_reader :definedtypes 20 class LiteralRegistry 21 include RegistrySupport 22 23 23 attr_accessor :excn_handler_obj2soap 24 24 attr_accessor :excn_handler_soap2obj 25 25 26 def initialize(definedtypes = XSD::NamedElements::Empty, 27 definedelements = XSD::NamedElements::Empty) 28 @definedtypes = definedtypes 29 @definedelements = definedelements 26 def initialize 27 super() 30 28 @excn_handler_obj2soap = nil 31 29 @excn_handler_soap2obj = nil 32 @schema_element_cache = {}33 @schema_attribute_cache = {}34 30 end 35 31 … … 38 34 if obj.is_a?(SOAPElement) 39 35 soap_obj = obj 40 elsif eledef = @definedelements[qname]41 soap_obj = obj2elesoap(obj, eledef)42 elsif type = @definedtypes[qname]43 soap_obj = obj2typesoap(obj, type, true)44 36 else 45 37 soap_obj = any2soap(obj, qname) … … 80 72 81 73 MAPPING_OPT = { :no_reference => true } 82 83 def obj2elesoap(obj, eledef)84 ele = nil85 qualified = (eledef.elementform == 'qualified')86 if eledef.type87 if type = @definedtypes[eledef.type]88 ele = obj2typesoap(obj, type, qualified)89 elsif type = TypeMap[eledef.type]90 ele = base2soap(obj, type)91 else92 raise MappingError.new("cannot find type #{eledef.type}")93 end94 elsif eledef.local_complextype95 ele = obj2typesoap(obj, eledef.local_complextype, qualified)96 elsif eledef.local_simpletype97 ele = obj2typesoap(obj, eledef.local_simpletype, qualified)98 else99 raise MappingError.new('illegal schema?')100 end101 ele.elename = eledef.name102 ele103 end104 105 def obj2typesoap(obj, type, qualified)106 ele = nil107 if type.is_a?(::WSDL::XMLSchema::SimpleType)108 ele = simpleobj2soap(obj, type)109 elsif type.simplecontent110 ele = simpleobj2soap(obj, type.simplecontent)111 else112 ele = complexobj2soap(obj, type, qualified)113 end114 add_attributes2soap(obj, ele)115 ele116 end117 118 def simpleobj2soap(obj, type)119 type.check_lexical_format(obj)120 return SOAPNil.new if obj.nil? # TODO: check nillable.121 if type.base122 ele = base2soap(obj, TypeMap[type.base])123 elsif type.list124 value = obj.is_a?(Array) ? obj.join(" ") : obj.to_s125 ele = base2soap(value, SOAP::SOAPString)126 else127 raise MappingError.new("unsupported simpleType: #{type}")128 end129 ele130 end131 132 def complexobj2soap(obj, type, qualified)133 ele = SOAPElement.new(type.name)134 ele.qualified = qualified135 if type.choice?136 complexobj2choicesoap(obj, ele, type)137 else138 complexobj2sequencesoap(obj, ele, type)139 end140 end141 142 def complexobj2sequencesoap(obj, ele, type)143 elements = type.elements144 any = nil145 if type.have_any?146 any = Mapping.get_attributes_for_any(obj, elements)147 end148 elements.each do |child_ele|149 case child_ele150 when WSDL::XMLSchema::Any151 if any152 SOAPElement.from_objs(any).each do |child|153 ele.add(child)154 end155 end156 when WSDL::XMLSchema::Element157 complexobj2soapchildren(obj, ele, child_ele)158 when WSDL::XMLSchema::Sequence159 complexobj2sequencesoap(obj, child_ele, type)160 when WSDL::XMLSchema::Choice161 complexobj2choicesoap(obj, child_ele, type)162 else163 raise MappingError.new("unknown type: #{child_ele}")164 end165 end166 ele167 end168 169 def complexobj2choicesoap(obj, ele, type)170 elements = type.elements171 any = nil172 if type.have_any?173 raise MappingError.new(174 "<any/> in <choice/> is not supported: #{ele.name.name}")175 end176 elements.each do |child_ele|177 break if complexobj2soapchildren(obj, ele, child_ele, true)178 end179 ele180 end181 182 def complexobj2soapchildren(obj, ele, child_ele, allow_nil_value = false)183 if child_ele.map_as_array?184 complexobj2soapchildren_array(obj, ele, child_ele, allow_nil_value)185 else186 complexobj2soapchildren_single(obj, ele, child_ele, allow_nil_value)187 end188 end189 190 def complexobj2soapchildren_array(obj, ele, child_ele, allow_nil_value)191 child = Mapping.get_attribute(obj, child_ele.name.name)192 if child.nil? and obj.respond_to?(:each)193 child = obj194 end195 if child.nil?196 return false if allow_nil_value197 if child_soap = nil2soap(child_ele)198 ele.add(child_soap)199 return true200 else201 return false202 end203 end204 unless child.respond_to?(:each)205 return false206 end207 child.each do |item|208 if item.is_a?(SOAPElement)209 ele.add(item)210 else211 child_soap = obj2elesoap(item, child_ele)212 ele.add(child_soap)213 end214 end215 true216 end217 218 def complexobj2soapchildren_single(obj, ele, child_ele, allow_nil_value)219 child = Mapping.get_attribute(obj, child_ele.name.name)220 case child221 when NilClass222 return false if allow_nil_value223 if child_soap = nil2soap(child_ele)224 ele.add(child_soap)225 true226 else227 false228 end229 when SOAPElement230 ele.add(child)231 true232 else233 child_soap = obj2elesoap(child, child_ele)234 ele.add(child_soap)235 true236 end237 end238 239 def nil2soap(ele)240 if ele.nillable241 obj2elesoap(nil, ele) # add an empty element242 elsif Integer(ele.minoccurs) == 0243 nil # intends no element244 else245 raise MappingError.new("nil not allowed: #{ele.name.name}")246 end247 end248 74 249 75 def any2soap(obj, qname) … … 281 107 (obj.class.class_variables.include?('@@schema_qualified') and 282 108 obj.class.class_eval('@@schema_qualified')) 283 definition = schema_element_definition(obj.class)109 definition = Mapping.schema_definition_classdef(obj.class) 284 110 ele.extraattr[XSD::AttrTypeName] = 285 111 XSD::QName.new(definition.ns, definition.type) … … 325 151 ele 326 152 end 327 328 def add_attributes2soap(obj, ele)329 attributes = schema_attribute_definition(obj.class)330 if attributes331 attributes.each do |qname, param|332 at = obj.__send__(333 XSD::CodeGen::GenSupport.safemethodname('xmlattr_' + qname.name))334 ele.extraattr[qname] = at335 end336 elsif obj.respond_to?(:__xmlattr)337 obj.__xmlattr.each do |key, value|338 ele.extraattr[key] = value339 end340 end341 end342 343 def base2soap(obj, type)344 soap_obj = nil345 if type <= XSD::XSDString346 str = XSD::Charset.encoding_conv(obj.to_s,347 Thread.current[:SOAPExternalCES], XSD::Charset.encoding)348 soap_obj = type.new(str)349 else350 soap_obj = type.new(obj)351 end352 soap_obj353 end354 153 355 154 def any2obj(node, obj_class = nil) … … 396 195 397 196 def add_elesoap2stubobj(node, obj) 398 definition = schema_element_definition(obj.class)197 definition = Mapping.schema_definition_classdef(obj.class) 399 198 vars = {} 400 199 node.each do |name, value| … … 439 238 440 239 def add_attributes2stubobj(node, obj) 441 if attributes = schema_attribute_definition(obj.class) 240 schema_definition = Mapping.schema_definition_classdef(obj.class) 241 if schema_definition && attributes = schema_definition.attributes 442 242 define_xmlattr(obj) 443 243 attributes.each do |qname, class_name| … … 501 301 end 502 302 end 503 504 # it caches @@schema_element. this means that @@schema_element must not be505 # changed while a lifetime of a WSDLLiteralRegistry.506 def schema_element_definition(klass)507 @schema_element_cache[klass] ||= Mapping.schema_element_definition(klass)508 end509 510 def schema_attribute_definition(klass)511 @schema_attribute_cache[klass] ||=512 Mapping.schema_attribute_definition(klass)513 end514 303 end 515 304 trunk/lib/soap/mapping/mapping.rb
r1719 r1720 21 21 22 22 23 # TraverseSupport breaks following thread variables.24 # Thread.current[:SOAPMarshalDataKey]25 23 module TraverseSupport 26 24 def mark_marshalled_obj(obj, soap_obj) 27 25 raise if obj.nil? 28 Thread.current[:SOAPMa rshalDataKey][obj.__id__] = soap_obj26 Thread.current[:SOAPMapping][:MarshalKey][obj.__id__] = soap_obj 29 27 end 30 28 … … 32 30 return if obj.nil? 33 31 # node.id is not Object#id but SOAPReference#id 34 Thread.current[:SOAPMa rshalDataKey][node.id] = obj35 end 36 end 37 38 39 EMPTY_OPT = {} 32 Thread.current[:SOAPMapping][:MarshalKey][node.id] = obj 33 end 34 end 35 36 37 EMPTY_OPT = {}.freeze 40 38 def self.obj2soap(obj, registry = nil, type = nil, opt = EMPTY_OPT) 41 39 registry ||= Mapping::DefaultRegistry 42 40 soap_obj = nil 43 protect_threadvars(:SOAPMarshalDataKey, :SOAPExternalCES, :SOAPMarshalNoReference) do 44 Thread.current[:SOAPMarshalDataKey] = {} 45 Thread.current[:SOAPExternalCES] = 46 opt[:external_ces] || XSD::Charset.encoding 47 Thread.current[:SOAPMarshalNoReference] = opt[:no_reference] 41 protect_mapping(opt) do 48 42 soap_obj = _obj2soap(obj, registry, type) 49 43 end … … 54 48 registry ||= Mapping::DefaultRegistry 55 49 obj = nil 56 protect_threadvars(:SOAPMarshalDataKey, :SOAPExternalCES, :SOAPMarshalNoReference) do 57 Thread.current[:SOAPMarshalDataKey] = {} 58 Thread.current[:SOAPExternalCES] = 59 opt[:external_ces] || XSD::Charset.encoding 60 Thread.current[:SOAPMarshalNoReference] = opt[:no_reference] 50 protect_mapping(opt) do 61 51 obj = _soap2obj(node, registry, klass) 62 52 end … … 68 58 type = XSD::QName.new(type_ns, typename) 69 59 soap_ary = SOAPArray.new(ValueArrayName, 1, type) 70 protect_threadvars(:SOAPMarshalDataKey, :SOAPExternalCES, :SOAPMarshalNoReference) do 71 Thread.current[:SOAPMarshalDataKey] = {} 72 Thread.current[:SOAPExternalCES] = 73 opt[:external_ces] || XSD::Charset.encoding 74 Thread.current[:SOAPMarshalNoReference] = opt[:no_reference] 60 protect_mapping(opt) do 75 61 ary.each do |ele| 76 62 soap_ary.add(_obj2soap(ele, registry, type)) … … 84 70 type = XSD::QName.new(type_ns, typename) 85 71 md_ary = SOAPArray.new(ValueArrayName, rank, type) 86 protect_threadvars(:SOAPMarshalDataKey, :SOAPExternalCES, :SOAPMarshalNoReference) do 87 Thread.current[:SOAPMarshalDataKey] = {} 88 Thread.current[:SOAPExternalCES] = 89 opt[:external_ces] || XSD::Charset.encoding 90 Thread.current[:SOAPMarshalNoReference] = opt[:no_reference] 72 protect_mapping(opt) do 91 73 add_md_ary(md_ary, ary, [], registry) 92 74 end … … 125 107 126 108 def self._obj2soap(obj, registry, type = nil) 127 if referent = Thread.current[:SOAPMa rshalDataKey][obj.__id__] and128 !Thread.current[:SOAPMa rshalNoReference]109 if referent = Thread.current[:SOAPMapping][:MarshalKey][obj.__id__] and 110 !Thread.current[:SOAPMapping][:NoReference] 129 111 SOAPReference.new(referent) 130 112 elsif registry … … 141 123 target = node.__getobj__ 142 124 # target.id is not Object#id but SOAPReference#id 143 if referent = Thread.current[:SOAPMa rshalDataKey][target.id] and144 !Thread.current[:SOAPMa rshalNoReference]125 if referent = Thread.current[:SOAPMapping][:MarshalKey][target.id] and 126 !Thread.current[:SOAPMapping][:NoReference] 145 127 return referent 146 128 else … … 377 359 378 360 def self.schema_element_definition(klass) 379 schema_element = class_schema_variable(:schema_element, klass) 380 return nil unless schema_element 381 parse_schema_element_definition(klass, schema_element) 382 end 383 384 class SchemaElementDefinition 385 attr_reader :varname, :elename, :type 386 387 def initialize(varname, elename, type, as_array) 388 @varname = varname 389 @elename = elename 390 @type = type 391 @as_array = as_array 392 end 393 394 def as_array? 395 @as_array 396 end 397 end 398 399 class SchemaDefinition 400 attr_reader :ns, :type, :elements 401 402 def initialize(ns, type) 403 @ns = ns 404 @type = type 405 @elements = [] 406 @choice = false 407 @any = false 408 end 409 410 def choice? 411 @choice 412 end 413 414 def have_any? 415 @any 416 end 417 418 def set_choice 419 @choice = true 420 end 421 422 def set_any 423 @any = true 424 end 361 class_schema_variable(:schema_element, klass) 425 362 end 426 363 … … 429 366 end 430 367 431 class << Mapping 432 private 433 434 def parse_schema_element_definition(klass, schema_element) 435 schema_ns = schema_ns_definition(klass) 436 schema_type = schema_type_definition(klass) 437 definition = SchemaDefinition.new(schema_ns, schema_type) 368 def self.schema_definition_classdef(klass) 369 if definition = Thread.current[:SOAPMapping][:SchemaDefinition][klass] 370 return definition 371 end 372 ns = schema_ns_definition(klass) 373 type = schema_type_definition(klass) 374 elements = schema_element_definition(klass) 375 attributes = schema_attribute_definition(klass) 376 return nil if ns.nil? and type.nil? and elements.nil? and attributes.nil? 377 definition = create_schema_definition(klass, ns, type, elements, attributes) 378 Thread.current[:SOAPMapping][:SchemaDefinition][klass] = definition 379 definition 380 end 381 382 def self.create_schema_definition(klass, schema_ns, schema_type, 383 schema_element, schema_attributes) 384 definition = SchemaDefinition.new(schema_ns, schema_type) 385 definition.attributes = schema_attributes 386 if schema_element 438 387 if schema_element[0] == :choice 439 388 schema_element.shift … … 462 411 ) 463 412 end 464 definition 465 end 413 end 414 definition 415 end 416 417 class SchemaElementDefinition 418 attr_reader :varname, :elename, :type 419 420 def initialize(varname, elename, type, as_array) 421 @varname = varname 422 @elename = elename 423 @type = type 424 @as_array = as_array 425 end 426 427 def as_array? 428 @as_array 429 end 430 end 431 432 class SchemaDefinition 433 attr_reader :ns, :type, :elements 434 attr_accessor :attributes 435 436 def initialize(ns, type) 437 @ns = ns 438 @type = type 439 @elements = [] 440 @attributes = nil 441 @choice = false 442 @any = false 443 end 444 445 def choice? 446 @choice 447 end 448 449 def have_any? 450 @any 451 end 452 453 def set_choice 454 @choice = true 455 end 456 457 def set_any 458 @any = true 459 end 460 end 461 462 class << Mapping 463 private 466 464 467 465 def class_schema_variable(sym, klass) 468 466 var = "@@#{sym}" 469 467 klass.class_variables.include?(var) ? klass.class_eval(var) : nil 468 end 469 470 def protect_mapping(opt) 471 protect_threadvars(:SOAPMapping) do 472 data = Thread.current[:SOAPMapping] = {} 473 data[:MarshalKey] = {} 474 data[:ExternalCES] = opt[:external_ces] || XSD::Charset.encoding 475 data[:NoReference] = opt[:no_reference] 476 data[:SchemaDefinition] = {} 477 yield 478 end 470 479 end 471 480 trunk/lib/soap/mapping/registry.rb
r1706 r1720 1 1 # SOAP4R - Mapping registry. 2 # Copyright (C) 2000 , 2001, 2002, 2003NAKAMURA, Hiroshi <nahi@ruby-lang.org>.2 # Copyright (C) 2000-2003, 2006 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. 3 3 4 4 # This program is copyrighted free software by NAKAMURA, Hiroshi. You can … … 9 9 require 'soap/baseData' 10 10 require 'soap/mapping/mapping' 11 require 'soap/mapping/typeMap' 12 require 'soap/mapping/factory' 13 require 'soap/mapping/rubytypeFactory' 11 require 'soap/mapping/encodedregistry.rb' 14 12 15 13 … … 31 29 RubyExtendName = XSD::QName.new(RubyTypeInstanceNamespace, 'extends') 32 30 RubyIVarName = XSD::QName.new(RubyTypeInstanceNamespace, 'ivars') 33 34 35 # Inner class to pass an exception.36 class SOAPException; include Marshallable37 attr_reader :excn_type_name, :cause38 def initialize(e)39 @excn_type_name = Mapping.name2elename(e.class.to_s)40 @cause = e41 end42 43 def to_e44 if @cause.is_a?(::Exception)45 @cause.extend(::SOAP::Mapping::MappedException)46 return @cause47 elsif @cause.respond_to?(:message) and @cause.respond_to?(:backtrace)48 e = RuntimeError.new(@cause.message)49 e.set_backtrace(@cause.backtrace)50 return e51 end52 klass = Mapping.class_from_name(Mapping.elename2name(@excn_type_name.to_s))53 if klass.nil? or not klass <= ::Exception54 return RuntimeError.new(@cause.inspect)55 end56 obj = klass.new(@cause.message)57 obj.extend(::SOAP::Mapping::MappedException)58 obj59 end60 end61 31 62 32 … … 175 145 176 146 177 class Registry 178 class Map 179 def initialize(registry) 180 @obj2soap = {} 181 @soap2obj = {} 182 @registry = registry 183 end 184 185 def obj2soap(obj) 186 klass = obj.class 187 if map = @obj2soap[klass] 188 map.each do |soap_class, factory, info| 189 ret = factory.obj2soap(soap_class, obj, info, @registry) 190 return ret if ret 191 end 147 module RegistrySupport 148 def initialize 149 super() 150 end 151 152 def add_attributes2soap(obj, ele) 153 schema_definition = Mapping.schema_definition_classdef(obj.class) 154 if schema_definition && attributes = schema_definition.attributes 155 attributes.each do |qname, param| 156 at = obj.__send__( 157 XSD::CodeGen::GenSupport.safemethodname('xmlattr_' + qname.name)) 158 ele.extraattr[qname] = at 192 159 end 193 ancestors = klass.ancestors 194 ancestors.delete(klass) 195 ancestors.delete(::Object) 196 ancestors.delete(::Kernel) 197 ancestors.each do |klass| 198 if map = @obj2soap[klass] 199 map.each do |soap_class, factory, info| 200 if info[:derived_class] 201 ret = factory.obj2soap(soap_class, obj, info, @registry) 202 return ret if ret 203 end 204 end 205 end 206 end 207 nil 208 end 209 210 def soap2obj(node, klass = nil) 211 if map = @soap2obj[node.class] 212 map.each do |obj_class, factory, info| 213 next if klass and obj_class != klass 214 conv, obj = factory.soap2obj(obj_class, node, info, @registry) 215 return true, obj if conv 216 end 217 end 218 return false, nil 219 end 220 221 # Give priority to former entry. 222 def init(init_map = []) 223 clear 224 init_map.reverse_each do |obj_class, soap_class, factory, info| 225 add(obj_class, soap_class, factory, info) 226 end 227 end 228 229 # Give priority to latter entry. 230 def add(obj_class, soap_class, factory, info) 231 info ||= {} 232 (@obj2soap[obj_class] ||= []).unshift([soap_class, factory, info]) 233 (@soap2obj[soap_class] ||= []).unshift([obj_class, factory, info]) 234 end 235 236 def clear 237 @obj2soap.clear 238 @soap2obj.clear 239 end 240 241 def find_mapped_soap_class(target_obj_class) 242 map = @obj2soap[target_obj_class] 243 map.empty? ? nil : map[0][1] 244 end 245 246 def find_mapped_obj_class(target_soap_class) 247 map = @soap2obj[target_soap_class] 248 map.empty? ? nil : map[0][0] 249 end 250 end 251 252 StringFactory = StringFactory_.new 253 BasetypeFactory = BasetypeFactory_.new 254 DateTimeFactory = DateTimeFactory_.new 255 ArrayFactory = ArrayFactory_.new 256 Base64Factory = Base64Factory_.new 257 URIFactory = URIFactory_.new 258 TypedArrayFactory = TypedArrayFactory_.new 259 TypedStructFactory = TypedStructFactory_.new 260 261 HashFactory = HashFactory_.new 262 263 SOAPBaseMap = [ 264 [::NilClass, ::SOAP::SOAPNil, BasetypeFactory], 265 [::TrueClass, ::SOAP::SOAPBoolean, BasetypeFactory], 266 [::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory], 267 [::String, ::SOAP::SOAPString, StringFactory], 268 [::DateTime, ::SOAP::SOAPDateTime, DateTimeFactory], 269 [::Date, ::SOAP::SOAPDate, DateTimeFactory], 270 [::Time, ::SOAP::SOAPDateTime, DateTimeFactory], 271 [::Time, ::SOAP::SOAPTime, DateTimeFactory], 272 [::Float, ::SOAP::SOAPDouble, BasetypeFactory, 273 {:derived_class => true}], 274 [::Float, ::SOAP::SOAPFloat, BasetypeFactory, 275 {:derived_class => true}], 276 [::Integer, ::SOAP::SOAPInt, BasetypeFactory, 277 {:derived_class => true}], 278 [::Integer, ::SOAP::SOAPLong, BasetypeFactory, 279 {:derived_class => true}], 280 [::Integer, ::SOAP::SOAPInteger, BasetypeFactory, 281 {:derived_class => true}], 282 [::Integer, ::SOAP::SOAPShort, BasetypeFactory, 283 {:derived_class => true}], 284 [::Integer, ::SOAP::SOAPByte, BasetypeFactory, 285 {:derived_class => true}], 286 [::Integer, ::SOAP::SOAPNonPositiveInteger, BasetypeFactory, 287 {:derived_class => true}], 288 [::Integer, ::SOAP::SOAPNegativeInteger, BasetypeFactory, 289 {:derived_class => true}], 290 [::Integer, ::SOAP::SOAPNonNegativeInteger, BasetypeFactory, 291 {:derived_class => true}], 292 [::Integer, ::SOAP::SOAPPositiveInteger, BasetypeFactory, 293 {:derived_class => true}], 294 [::Integer, ::SOAP::SOAPUnsignedLong, BasetypeFactory, 295 {:derived_class => true}], 296 [::Integer, ::SOAP::SOAPUnsignedInt, BasetypeFactory, 297 {:derived_class => true}], 298 [::Integer, ::SOAP::SOAPUnsignedShort, BasetypeFactory, 299 {:derived_class => true}], 300 [::Integer, ::SOAP::SOAPUnsignedByte, BasetypeFactory, 301 {:derived_class => true}], 302 [::URI::Generic, ::SOAP::SOAPAnyURI, URIFactory, 303 {:derived_class => true}], 304 [::String, ::SOAP::SOAPBase64, Base64Factory], 305 [::String, ::SOAP::SOAPHexBinary, Base64Factory], 306 [::String, ::SOAP::SOAPDecimal, BasetypeFactory], 307 [::String, ::SOAP::SOAPDuration, BasetypeFactory], 308 [::String, ::SOAP::SOAPGYearMonth, BasetypeFactory], 309 [::String, ::SOAP::SOAPGYear, BasetypeFactory], 310 [::String, ::SOAP::SOAPGMonthDay, BasetypeFactory], 311 [::String, ::SOAP::SOAPGDay, BasetypeFactory], 312 [::String, ::SOAP::SOAPGMonth, BasetypeFactory], 313 [::String, ::SOAP::SOAPQName, BasetypeFactory], 314 315 [::Hash, ::SOAP::SOAPArray, HashFactory], 316 [::Hash, ::SOAP::SOAPStruct, HashFactory], 317 318 [::Array, ::SOAP::SOAPArray, ArrayFactory, 319 {:derived_class => true}], 320 321 [::SOAP::Mapping::SOAPException, 322 ::SOAP::SOAPStruct, TypedStructFactory, 323 {:type => XSD::QName.new(RubyCustomTypeNamespace, "SOAPException")}], 324 ] 325 326 RubyOriginalMap = [ 327 [::NilClass, ::SOAP::SOAPNil, BasetypeFactory], 328 [::TrueClass, ::SOAP::SOAPBoolean, BasetypeFactory], 329 [::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory], 330 [::String, ::SOAP::SOAPString, StringFactory], 331 [::DateTime, ::SOAP::SOAPDateTime, DateTimeFactory], 332 [::Date, ::SOAP::SOAPDate, DateTimeFactory], 333 [::Time, ::SOAP::SOAPDateTime, DateTimeFactory], 334 [::Time, ::SOAP::SOAPTime, DateTimeFactory], 335 [::Float, ::SOAP::SOAPDouble, BasetypeFactory, 336 {:derived_class => true}], 337 [::Float, ::SOAP::SOAPFloat, BasetypeFactory, 338 {:derived_class => true}], 339 [::Integer, ::SOAP::SOAPInt, BasetypeFactory, 340 {:derived_class => true}], 341 [::Integer, ::SOAP::SOAPLong, BasetypeFactory, 342 {:derived_class => true}], 343 [::Integer, ::SOAP::SOAPInteger, BasetypeFactory, 344 {:derived_class => true}], 345 [::Integer, ::SOAP::SOAPShort, BasetypeFactory, 346 {:derived_class => true}], 347 [::Integer, ::SOAP::SOAPByte, BasetypeFactory, 348 {:derived_class => true}], 349 [::Integer, ::SOAP::SOAPNonPositiveInteger, BasetypeFactory, 350 {:derived_class => true}], 351 [::Integer, ::SOAP::SOAPNegativeInteger, BasetypeFactory, 352 {:derived_class => true}], 353 [::Integer, ::SOAP::SOAPNonNegativeInteger, BasetypeFactory, 354 {:derived_class => true}], 355 [::Integer, ::SOAP::SOAPPositiveInteger, BasetypeFactory, 356 {:derived_class => true}], 357 [::Integer, ::SOAP::SOAPUnsignedLong, BasetypeFactory, 358 {:derived_class => true}], 359 [::Integer, ::SOAP::SOAPUnsignedInt, BasetypeFactory, 360 {:derived_class => true}], 361 [::Integer, ::SOAP::SOAPUnsignedShort, BasetypeFactory, 362 {:derived_class => true}], 363 [::Integer, ::SOAP::SOAPUnsignedByte, BasetypeFactory, 364 {:derived_class => true}], 365 [::URI::Generic, ::SOAP::SOAPAnyURI, URIFactory, 366 {:derived_class => true}], 367 [::String, ::SOAP::SOAPBase64, Base64Factory], 368 [::String, ::SOAP::SOAPHexBinary, Base64Factory], 369 [::String, ::SOAP::SOAPDecimal, BasetypeFactory], 370 [::String, ::SOAP::SOAPDuration, BasetypeFactory], 371 [::String, ::SOAP::SOAPGYearMonth, BasetypeFactory], 372 [::String, ::SOAP::SOAPGYear, BasetypeFactory], 373 [::String, ::SOAP::SOAPGMonthDay, BasetypeFactory], 374 [::String, ::SOAP::SOAPGDay, BasetypeFactory], 375 [::String, ::SOAP::SOAPGMonth, BasetypeFactory], 376 [::String, ::SOAP::SOAPQName, BasetypeFactory], 377 378 [::Hash, ::SOAP::SOAPArray, HashFactory], 379 [::Hash, ::SOAP::SOAPStruct, HashFactory], 380 381 # Does not allow Array's subclass here. 382 [::Array, ::SOAP::SOAPArray, ArrayFactory], 383 384 [::SOAP::Mapping::SOAPException, 385 ::SOAP::SOAPStruct, TypedStructFactory, 386 {:type => XSD::QName.new(RubyCustomTypeNamespace, "SOAPException")}], 387 ] 388 389 attr_accessor :default_factory 390 attr_accessor :excn_handler_obj2soap 391 attr_accessor :excn_handler_soap2obj 392 393 def initialize(config = {}) 394 @config = config 395 @map = Map.new(self) 396 if @config[:allow_original_mapping] 397 @allow_original_mapping = true 398 @map.init(RubyOriginalMap) 399 else 400 @allow_original_mapping = false 401 @map.init(SOAPBaseMap) 402 end 403 @allow_untyped_struct = @config.key?(:allow_untyped_struct) ? 404 @config[:allow_untyped_struct] : true 405 @rubytype_factory = RubytypeFactory.new( 406 :allow_untyped_struct => @allow_untyped_struct, 407 :allow_original_mapping => @allow_original_mapping 408 ) 409 @default_factory = @rubytype_factory 410 @excn_handler_obj2soap = nil 411 @excn_handler_soap2obj = nil 412 end 413 414 def add(obj_class, soap_class, factory, info = nil) 415 @map.add(obj_class, soap_class, factory, info) 416 end 417 alias set add 418 419 <