diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/net/https.rb | 171 | ||||
-rw-r--r-- | lib/soap/mapping/wsdlencodedregistry.rb | 173 | ||||
-rw-r--r-- | lib/soap/mapping/wsdlliteralregistry.rb | 281 | ||||
-rw-r--r-- | lib/wsdl/soap/element.rb | 34 | ||||
-rw-r--r-- | lib/wsdl/xmlSchema/simpleContent.rb | 65 |
5 files changed, 724 insertions, 0 deletions
diff --git a/lib/net/https.rb b/lib/net/https.rb new file mode 100644 index 0000000000..fb329df43d --- /dev/null +++ b/lib/net/https.rb @@ -0,0 +1,171 @@ +=begin + += $RCSfile$ -- SSL/TLS enhancement for Net::HTTP. + +== Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2001 GOTOU Yuuzou <gotoyuzo@notwork.org> + All rights reserved. + +== Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + +== Requirements + This program requires Net 1.2.0 or higher version. + You can get it from RAA or Ruby's CVS repository. + +== Version + $Id$ + + 2001-11-06: Contiributed to Ruby/OpenSSL project. + 2004-03-06: Some code is merged in to net/http. + +== Example + +Here is a simple HTTP client: + + require 'net/http' + require 'uri' + + uri = URI.parse(ARGV[0] || 'http://localhost/') + http = Net::HTTP.new(uri.host, uri.port) + http.start { + http.request_get(uri.path) {|res| + print res.body + } + } + +It can be replaced by the following code: + + require 'net/https' + require 'uri' + + uri = URI.parse(ARGV[0] || 'https://localhost/') + http = Net::HTTP.new(uri.host, uri.port) + http.use_ssl = true if uri.scheme == "https" # enable SSL/TLS + http.start { + http.request_get(uri.path) {|res| + print res.body + } + } + +== class Net::HTTP + +=== Instance Methods + +: use_ssl? + returns true if use SSL/TLS with HTTP. + +: use_ssl=((|true_or_false|)) + sets use_ssl. + +: peer_cert + return the X.509 certificates the server presented. + +: key, key=((|key|)) + Sets an OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object. + (This method is appeared in Michal Rokos's OpenSSL extention.) + +: cert, cert=((|cert|)) + Sets an OpenSSL::X509::Certificate object as client certificate + (This method is appeared in Michal Rokos's OpenSSL extention). + +: ca_file, ca_file=((|path|)) + Sets path of a CA certification file in PEM format. + The file can contrain several CA certificats. + +: ca_path, ca_path=((|path|)) + Sets path of a CA certification directory containing certifications + in PEM format. + +: verify_mode, verify_mode=((|mode|)) + Sets the flags for server the certification verification at + begining of SSL/TLS session. + OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER is acceptable. + +: verify_callback, verify_callback=((|proc|)) + Sets the verify callback for the server certification verification. + +: verify_depth, verify_depth=((|num|)) + Sets the maximum depth for the certificate chain verification. + +: cert_store, cert_store=((|store|)) + Sets the X509::Store to verify peer certificate. + +: ssl_timeout, ssl_timeout=((|sec|)) + Sets the SSL timeout seconds. + +=end + +require 'net/http' +require 'openssl' + +module Net + + class HTTP + remove_method :use_ssl? + def use_ssl? + @use_ssl + end + + alias use_ssl use_ssl? # for backward compatibility + + # Turn on/off SSL. + # This flag must be set before starting session. + # If you change use_ssl value after session started, + # a Net::HTTP object raises IOError. + def use_ssl=(flag) + flag = (flag ? true : false) + raise IOError, "use_ssl value changed, but session already started" \ + if started? and @use_ssl != flag + if flag and not @ssl_context + @ssl_context = OpenSSL::SSL::SSLContext.new + end + @use_ssl = flag + end + + def self.ssl_context_accessor(name) + module_eval(<<-End, __FILE__, __LINE__ + 1) + def #{name} + return nil unless @ssl_context + @ssl_context.#{name} + end + + def #{name}=(val) + @ssl_context ||= OpenSSL::SSL::SSLContext.new + @ssl_context.#{name} = val + end + End + end + + ssl_context_accessor :key + ssl_context_accessor :cert + ssl_context_accessor :ca_file + ssl_context_accessor :ca_path + ssl_context_accessor :verify_mode + ssl_context_accessor :verify_callback + ssl_context_accessor :verify_depth + ssl_context_accessor :cert_store + + def ssl_timeout + return nil unless @ssl_context + @ssl_context.timeout + end + + def ssl_timeout=(sec) + raise ArgumentError, 'Net::HTTP#ssl_timeout= called but use_ssl=false' \ + unless use_ssl? + @ssl_context ||= OpenSSL::SSL::SSLContext.new + @ssl_context.timeout = sec + end + + alias timeout= ssl_timeout= # for backward compatibility + + def peer_cert + return nil if not use_ssl? or not @socket + @socket.io.peer_cert + end + end + +end diff --git a/lib/soap/mapping/wsdlencodedregistry.rb b/lib/soap/mapping/wsdlencodedregistry.rb new file mode 100644 index 0000000000..4433c73cf0 --- /dev/null +++ b/lib/soap/mapping/wsdlencodedregistry.rb @@ -0,0 +1,173 @@ +# SOAP4R - WSDL encoded mapping registry. +# Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'soap/baseData' +require 'soap/mapping/mapping' +require 'soap/mapping/typeMap' + + +module SOAP +module Mapping + + +class WSDLEncodedRegistry + include TraverseSupport + + attr_reader :definedtypes + attr_accessor :excn_handler_obj2soap + + def initialize(definedtypes, config = {}) + @definedtypes = definedtypes + @config = config + @excn_handler_obj2soap = nil + # For mapping AnyType element. + @rubytype_factory = RubytypeFactory.new( + :allow_untyped_struct => true, + :allow_original_mapping => true + ) + end + + def obj2soap(obj, type_qname = nil) + soap_obj = nil + if obj.nil? + soap_obj = SOAPNil.new + elsif type_qname.nil? or type_qname == XSD::AnyTypeName + soap_obj = @rubytype_factory.obj2soap(nil, obj, nil, self) + elsif obj.is_a?(XSD::NSDBase) + soap_obj = soap2soap(obj, type_qname) + elsif type = @definedtypes[type_qname] + soap_obj = obj2type(obj, type) + elsif (type = TypeMap[type_qname]) + soap_obj = base2soap(obj, type) + end + return soap_obj if soap_obj + if @excn_handler_obj2soap + soap_obj = @excn_handler_obj2soap.call(obj) { |yield_obj| + Mapping._obj2soap(yield_obj, self) + } + return soap_obj if soap_obj + end + raise MappingError.new("Cannot map #{ obj.class.name } to SOAP/OM.") + end + + def soap2obj(node) + raise RuntimeError.new("#{ self } is for obj2soap only.") + end + +private + + def soap2soap(obj, type_qname) + if obj.is_a?(SOAPBasetype) + obj + elsif obj.is_a?(SOAPStruct) && (type = @definedtypes[type_qname]) + soap_obj = obj + mark_marshalled_obj(obj, soap_obj) + elements2soap(obj, soap_obj, type.content.elements) + soap_obj + elsif obj.is_a?(SOAPArray) && (type = @definedtypes[type_qname]) + soap_obj = obj + contenttype = type.child_type + mark_marshalled_obj(obj, soap_obj) + obj.replace do |ele| + Mapping._obj2soap(ele, self, contenttype) + end + soap_obj + else + nil + end + end + + def obj2type(obj, type) + if type.is_a?(::WSDL::XMLSchema::SimpleType) + simple2soap(obj, type) + else + complex2soap(obj, type) + end + end + + def simple2soap(obj, type) + o = base2soap(obj, TypeMap[type.base]) + if type.restriction.enumeration.empty? + STDERR.puts("#{type.name}: simpleType which is not enum type not supported.") + return o + end + type.check_lexical_format(obj) + o + end + + def complex2soap(obj, type) + case type.compoundtype + when :TYPE_STRUCT + struct2soap(obj, type.name, type) + when :TYPE_ARRAY + array2soap(obj, type.name, type) + when :TYPE_MAP + map2soap(obj, type.name, type) + else + raise MappingError.new("Unknown compound type: #{ type.compoundtype }") + 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) + arytype = type.child_type + soap_obj = SOAPArray.new(ValueArrayName, 1, arytype) + mark_marshalled_obj(obj, soap_obj) + obj.each do |item| + soap_obj.add(Mapping._obj2soap(item, self, arytype)) + end + soap_obj + end + + MapKeyName = XSD::QName.new(nil, "key") + MapValueName = XSD::QName.new(nil, "value") + def map2soap(obj, type_qname, type) + keytype = type.child_type(MapKeyName) || XSD::AnyTypeName + valuetype = type.child_type(MapValueName) || XSD::AnyTypeName + soap_obj = SOAPStruct.new(MapQName) + mark_marshalled_obj(obj, soap_obj) + obj.each do |key, value| + elem = SOAPStruct.new + elem.add("key", Mapping._obj2soap(key, self, keytype)) + elem.add("value", Mapping._obj2soap(value, self, valuetype)) + # ApacheAxis allows only 'item' here. + soap_obj.add("item", elem) + 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 diff --git a/lib/soap/mapping/wsdlliteralregistry.rb b/lib/soap/mapping/wsdlliteralregistry.rb new file mode 100644 index 0000000000..c190c9d904 --- /dev/null +++ b/lib/soap/mapping/wsdlliteralregistry.rb @@ -0,0 +1,281 @@ +# SOAP4R - WSDL literal mapping registry. +# Copyright (C) 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'soap/baseData' +require 'soap/mapping/mapping' +require 'soap/mapping/typeMap' +require 'xsd/codegen/gensupport' + + +module SOAP +module Mapping + + +class WSDLLiteralRegistry + attr_reader :definedelements + attr_reader :definedtypes + attr_accessor :excn_handler_obj2soap + attr_accessor :excn_handler_soap2obj + + def initialize(definedelements = nil, definedtypes = nil) + @definedelements = definedelements + @definedtypes = definedtypes + @rubytype_factory = RubytypeFactory.new(:allow_original_mapping => false) + @schema_element_cache = {} + end + + def obj2soap(obj, qname) + ret = nil + if !@definedelements.nil? && ele = @definedelements[qname] + ret = _obj2soap(obj, ele) + elsif !@definedtypes.nil? && type = @definedtypes[qname] + ret = obj2type(obj, type) + else + ret = unknownobj2soap(obj, qname) + end + return ret if ret + if @excn_handler_obj2soap + ret = @excn_handler_obj2soap.call(obj) { |yield_obj| + Mapping._obj2soap(yield_obj, self) + } + return ret if ret + end + raise MappingError.new("Cannot map #{ obj.class.name } to SOAP/OM.") + end + + # node should be a SOAPElement + def soap2obj(node) + begin + return soapele2obj(node) + rescue MappingError + end + if @excn_handler_soap2obj + begin + return @excn_handler_soap2obj.call(node) { |yield_node| + Mapping._soap2obj(yield_node, self) + } + rescue Exception + end + end + raise MappingError.new("Cannot map #{ node.type.name } to Ruby object.") + end + +private + + def _obj2soap(obj, ele) + o = nil + if ele.type + if type = @definedtypes[ele.type] + o = obj2type(obj, type) + elsif type = TypeMap[ele.type] + o = base2soap(obj, type) + else + raise MappingError.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_ele| + o.add(_obj2soap(Mapping.find_attribute(obj, child_ele.name.name), + child_ele)) + end + else + raise MappingError.new('Illegal schema?') + end + o + end + + def obj2type(obj, type) + if type.is_a?(::WSDL::XMLSchema::SimpleType) + simple2soap(obj, type) + else + complex2soap(obj, type) + end + end + + def simple2soap(obj, type) + o = base2soap(obj, TypeMap[type.base]) + if type.restriction.enumeration.empty? + STDERR.puts( + "#{type.name}: simpleType which is not enum type not supported.") + return o + end + type.check_lexical_format(obj) + o + end + + def complex2soap(obj, type) + o = SOAPElement.new(type.name) + type.each_element do |child_ele| + o.add(_obj2soap(Mapping.find_attribute(obj, child_ele.name.name), + child_ele)) + end + o + end + + def unknownobj2soap(obj, name) + if obj.class.class_variables.include?('@@schema_element') + ele = SOAPElement.new(name) + add_elements2soap(obj, ele) + add_attributes2soap(obj, ele) + ele + elsif obj.is_a?(Hash) + ele = SOAPElement.from_obj(obj) + ele.elename = name + ele + else # expected to be a basetype or an anyType. + o = Mapping.obj2soap(obj) + o.elename = name + o + end + end + + def add_elements2soap(obj, ele) + elements, as_array = schema_element_definition(obj.class) + elements.each do |elename, type| + child = Mapping.find_attribute(obj, elename) + name = ::XSD::QName.new(nil, elename) + if as_array.include?(type) + child.each do |item| + ele.add(obj2soap(item, name)) + end + else + ele.add(obj2soap(child, name)) + end + end + end + + def add_attributes2soap(obj, ele) + attributes = schema_attribute_definition(obj.class) + attributes.each do |attrname, param| + attr = Mapping.find_attribute(obj, 'attr_' + attrname) + ele.extraattr[attrname] = attr + 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) + else + soap_obj = type.new(obj) + end + soap_obj + end + + def anytype2obj(node) + if node.is_a?(::SOAP::SOAPBasetype) + return node.data + end + klass = ::SOAP::Mapping::Object + obj = klass.new + node.each do |name, value| + obj.__soap_set_property(name, Mapping.soap2obj(value)) + end + obj + end + + def soapele2obj(node, obj_class = nil) + unless obj_class + typestr = ::XSD::CodeGen::GenSupport.safeconstname(node.elename.name) + obj_class = Mapping.class_from_name(typestr) + end + if obj_class and obj_class.class_variables.include?('@@schema_element') + soapele2definedobj(node, obj_class) + elsif node.is_a?(SOAPElement) + node.to_obj + else + result, obj = @rubytype_factory.soap2obj(nil, node, nil, self) + obj + end + end + + def soapele2definedobj(node, obj_class) + obj = Mapping.create_empty_object(obj_class) + add_elements2obj(node, obj) + add_attributes2obj(node, obj) + obj + end + + def add_elements2obj(node, obj) + elements, as_array = schema_element_definition(obj.class) + vars = {} + node.each do |name, value| + if class_name = elements[name] + if klass = Mapping.class_from_name(class_name) + if klass.ancestors.include?(::SOAP::SOAPBasetype) + if value.respond_to?(:data) + child = klass.new(value.data).data + else + child = klass.new(nil).data + end + else + child = soapele2obj(value, klass) + end + else + raise MappingError.new("Unknown class: #{class_name}") + end + else # untyped element is treated as anyType. + child = anytype2obj(value) + end + if as_array.include?(class_name) + (vars[name] ||= []) << child + else + vars[name] = child + end + end + Mapping.set_instance_vars(obj, vars) + end + + def add_attributes2obj(node, obj) + Mapping.set_instance_vars(obj, {'__soap_attribute' => {}}) + vars = {} + attributes = schema_attribute_definition(obj.class) + attributes.each do |attrname, class_name| + attr = node.extraattr[::XSD::QName.new(nil, attrname)] + next if attr.nil? or attr.empty? + klass = Mapping.class_from_name(class_name) + if klass.ancestors.include?(::SOAP::SOAPBasetype) + child = klass.new(attr).data + else + child = attr + end + vars['attr_' + attrname] = child + end + Mapping.set_instance_vars(obj, vars) + end + + # it caches @@schema_element. this means that @@schema_element must not be + # changed while a lifetime of a WSDLLiteralRegistry. + def schema_element_definition(klass) + if @schema_element_cache.key?(klass) + return @schema_element_cache[klass] + end + elements = {} + as_array = [] + klass.class_eval('@@schema_element').each do |name, class_name| + if /\[\]$/ =~ class_name + class_name = class_name.sub(/\[\]$/, '') + as_array << class_name + end + elements[name] = class_name + end + @schema_element_cache[klass] = [elements, as_array] + return @schema_element_cache[klass] + end + + def schema_attribute_definition(klass) + attributes = klass.class_eval('@@schema_attribute') + end +end + + +end +end diff --git a/lib/wsdl/soap/element.rb b/lib/wsdl/soap/element.rb new file mode 100644 index 0000000000..c39a00d25a --- /dev/null +++ b/lib/wsdl/soap/element.rb @@ -0,0 +1,34 @@ +# WSDL4R - XMLSchema element definition for WSDL. +# Copyright (C) 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'wsdl/xmlSchema/element' + + +module WSDL +module XMLSchema + + +class Element < Info + def map_as_array? + maxoccurs != '1' + end + + def attributes + @local_complextype.attributes + end + + def each_element + @local_complextype.each_element do |element| + yield(element) + end + end +end + + +end +end diff --git a/lib/wsdl/xmlSchema/simpleContent.rb b/lib/wsdl/xmlSchema/simpleContent.rb new file mode 100644 index 0000000000..0d83678a01 --- /dev/null +++ b/lib/wsdl/xmlSchema/simpleContent.rb @@ -0,0 +1,65 @@ +# WSDL4R - XMLSchema simpleContent definition for WSDL. +# Copyright (C) 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>. + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'wsdl/info' +require 'xsd/namedelements' + + +module WSDL +module XMLSchema + + +class SimpleContent < 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 targetnamespace + parent.targetnamespace + end + + def parse_element(element) + case element + when RestrictionName, ExtensionName + @derivetype = element.name + self + 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 |