Welcome to the "trac"-ing site of soap4r!
[soap4r] [httpclient] [openpgp4u] [pkcs1] [logger] [csv] [vtr]

Changeset 24

Show
Ignore:
Timestamp:
03/20/01 23:17:56 (8 years ago)
Author:
nakahiro
Message:

Moved SOAP*.rb -> soap/*.rb

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/lib/SOAP.rb

    r2 r24  
    1 =begin 
    2 SOAP4R 
    3 Copyright (C) 2000 NAKAMURA Hiroshi. 
    4  
    5 This program is free software; you can redistribute it and/or modify it under 
    6 the terms of the GNU General Public License as published by the Free Software 
    7 Foundation; either version 2 of the License, or (at your option) any later 
    8 version. 
    9  
    10 This program is distributed in the hope that it will be useful, but WITHOUT ANY 
    11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
    12 PRATICULAR PURPOSE. See the GNU General Public License for more details. 
    13  
    14 You should have received a copy of the GNU General Public License along with 
    15 this program; if not, write to the Free Software Foundation, Inc., 675 Mass 
    16 Ave, Cambridge, MA 02139, USA. 
    17 =end 
    18  
    19 module SOAP 
    20   public 
    21  
    22   EnvelopeNamespace = 'http://schemas.xmlsoap.org/soap/envelope/' 
    23   EncodingNamespace = 'http://schemas.xmlsoap.org/soap/encoding/' 
    24  
    25   NextActor = 'http://schemas.xmlsoap.org/soap/actor/next' 
    26  
    27   AttrMustUnderstand = 'mustUnderstand' 
    28   AttrEncodingStyle = 'encodingStyle' 
    29   AttrActor = 'actor' 
    30  
    31   class Error < StandardError; end 
    32  
    33   class MethodDefinitionError < Error; end 
    34   class HTTPStreamError < Error; end 
    35   class PostUnavailableError < HTTPStreamError; end 
    36   class MPostUnavailableError < HTTPStreamError; end 
    37  
    38   class ArrayIndexOutOfBoundsError < Error; end 
    39   class ArrayStoreError < Error; end 
    40  
    41   class FaultError < Error 
    42     public 
    43  
    44     attr_reader :faultCode 
    45     attr_reader :faultString 
    46     attr_reader :faultActor 
    47     attr_reader :detail 
    48  
    49     def initialize( fault ) 
    50       @faultCode = fault.faultCode 
    51       @faultString = fault.faultString 
    52       @faultActor = fault.faultActor 
    53       @detail = fault.detail 
    54     end 
    55   end 
    56  
    57   class FormatDecodeError < Error; end 
    58  
    59 end 
     1require 'soap/soap' 
  • trunk/lib/SOAPData.rb

    r16 r24  
    1 =begin 
    2 SOAP4R 
    3 Copyright (C) 2000 NAKAMURA Hiroshi. 
    4  
    5 This program is free software; you can redistribute it and/or modify it under 
    6 the terms of the GNU General Public License as published by the Free Software 
    7 Foundation; either version 2 of the License, or (at your option) any later 
    8 version. 
    9  
    10 This program is distributed in the hope that it will be useful, but WITHOUT ANY 
    11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
    12 PRATICULAR PURPOSE. See the GNU General Public License for more details. 
    13  
    14 You should have received a copy of the GNU General Public License along with 
    15 this program; if not, write to the Free Software Foundation, Inc., 675 Mass 
    16 Ave, Cambridge, MA 02139, USA. 
    17 =end 
    18  
    19 require 'SOAP' 
    20 require 'XMLSchemaDatatypes' 
    21 require 'xmltreebuilder' 
    22  
    23  
    24 ### 
    25 ## SOAP utility module for classes( not instances! ) 
    26 
    27 class SOAPNS 
    28   public 
    29  
    30   attr_reader :defaultNamespace 
    31   attr_reader :namespaceTag 
    32  
    33   def initialize( initNamespace = {} ) 
    34     @namespaceTag = initNamespace 
    35     @defaultNamespace = nil 
    36   end 
    37  
    38   def assign( namespace, name = nil ) 
    39     if ( @namespaceTag.has_key?( namespace )) 
    40       false 
    41     elsif ( name == '' ) 
    42       @defaultNamespace = namespace 
    43       name 
    44     elsif ( @namespaceTag.has_value?( name )) 
    45       # Already assigned.  Should raise Error? 
    46       name = SOAPNS.assign( namespace ) 
    47       @namespaceTag[ namespace ] = name 
    48       name 
    49     else 
    50       name ||= SOAPNS.assign( namespace ) 
    51       @namespaceTag[ namespace ] = name 
    52       name 
    53     end 
    54   end 
    55  
    56   def []( namespace ) 
    57     if ( @namespaceTag.has_key?( namespace )) 
    58       @namespaceTag[ namespace ] 
    59     else 
    60       nil 
    61     end 
    62   end 
    63  
    64   def clone() 
    65     SOAPNS.new( @namespaceTag.dup ) 
    66   end 
    67  
    68   def name( namespace, name ) 
    69     if ( namespace == @defaultNamespace ) 
    70       name 
    71     elsif @namespaceTag.has_key?( namespace ) 
    72       @namespaceTag[ namespace ] + ':' << name 
    73     else 
    74       raise FormatDecodeError.new( 'Namespace: ' << namespace << ' not defined yet.' ) 
    75     end 
    76   end 
    77  
    78   def compare( namespace, name, rhs ) 
    79     if ( namespace == @defaultNamespace ) 
    80       return true if ( name == rhs ) 
    81     end 
    82  
    83     if @namespaceTag.has_key?( namespace ) 
    84       return (( @namespaceTag[ namespace ] + ':' << name ) == rhs ) 
    85     end 
    86  
    87     return false 
    88   end 
    89  
    90   # $1 and $2 are necessary. 
    91   ParseRegexp = Regexp.new( '^([^:]+)(?::(.+))?$' ) 
    92  
    93   def parse( elem ) 
    94     namespace = nil 
    95     name = nil 
    96     ParseRegexp =~ elem 
    97     if $2 
    98       namespace = @namespaceTag.index( $1 ) 
    99       name = $2 
    100       if !namespace 
    101         raise FormatDecodeError.new( 'Unknown namespace qualifier: ' << $1 ) 
    102       end 
    103     elsif $1 
    104       namespace = @defaultNamespace 
    105       name = $1 
    106     end 
    107     if !name 
    108       raise FormatDecodeError.new( 'Illegal element format: ' << elem ) 
    109     end 
    110     return namespace, name 
    111   end 
    112  
    113   private 
    114  
    115   AssigningName = [ 0 ] 
    116  
    117   def self.assign( namespace ) 
    118     AssigningName[ 0 ] += 1 
    119     'n' << AssigningName[ 0 ].to_s 
    120   end 
    121  
    122   def self.reset() 
    123     AssigningName[ 0 ] = 0 
    124   end 
    125 end 
    126  
    127  
    128 ### 
    129 ## SOAP related datatypes. 
    130 
    131 module SOAPModuleUtils 
    132   include SOAP 
    133   include XML::SimpleTree 
    134  
    135   public 
    136  
    137   def decode( ns, elem ) 
    138     elem.normalize 
    139     value = if elem.childNodes[0] 
    140         elem.childNodes[0].nodeValue 
    141       else 
    142         '' 
    143       end 
    144     d = self.new( value ) 
    145     d.namespace, = ns.parse( elem.nodeName ) 
    146     d 
    147   end 
    148  
    149   private 
    150  
    151   def decodeChild( ns, elem ) 
    152     if isNull( ns, elem ) 
    153       return SOAPNull.decode( ns, elem ) 
    154     end 
    155  
    156     case getType( ns, elem ) 
    157     when 'int' 
    158       SOAPInt.decode( ns, elem ) 
    159     when 'integer' 
    160       SOAPInteger.decode( ns, elem ) 
    161     when 'boolean' 
    162       SOAPBoolean.decode( ns, elem ) 
    163     when 'string' 
    164       SOAPString.decode( ns, elem ) 
    165     when 'timeInstant' 
    166       SOAPTimeInstant.decode( ns, elem ) 
    167     when /\[\d*\]$/ 
    168       SOAPArray.decode( ns, elem ) 
    169     else 
    170       bOnlyText = true 
    171       elem.childNodes.each do | child | 
    172         next if ( isEmptyText( child )) 
    173         bOnlyText = false 
    174         break 
    175       end 
    176       if bOnlyText 
    177         # No type is set. Decode as SOAPString by default. 
    178         SOAPString.decode( ns, elem ) 
    179       else 
    180         SOAPStruct.decode( ns, elem ) 
    181       end 
    182     end 
    183   end 
    184  
    185   EmptyTextRegexp = Regexp.new( '\s*(?:\n\s*)*' ) 
    186  
    187   def isEmptyText( node ) 
    188     (( node.nodeName == '#text' ) and ( EmptyTextRegexp =~ node.nodeValue )) 
    189   end 
    190  
    191   def isNull( ns, elem ) 
    192     elem.attributes.each do | attr | 
    193       if ( ns.compare( XSD::InstanceNamespace, 'null', '1' )) 
    194         return true 
    195       end 
    196     end 
    197     false 
    198   end 
    199  
    200   def getType( ns, elem ) 
    201     elem.attributes.each do | attr | 
    202       if ( ns.compare( XSD::InstanceNamespace, 'type', attr.nodeName )) 
    203         return attr.nodeValue 
    204       end 
    205     end 
    206     nil 
    207   end 
    208  
    209   # $1 is necessary. 
    210   NSParseRegexp = Regexp.new( '^xmlns:?(.*)$' ) 
    211  
    212   def parseNS( ns, elem ) 
    213     return unless elem.attributes 
    214     elem.attributes.each do | attr | 
    215       next unless ( NSParseRegexp =~ attr.nodeName ) 
    216       # '' means 'default namespace'. 
    217       tag = $1 || '' 
    218       ns.assign( attr.nodeValue, tag ) 
    219     end 
    220   end 
    221 end 
    222  
    223 module SOAPBasetypeUtils 
    224   include SOAP 
    225   include XML::SimpleTree 
    226  
    227   public 
    228  
    229   def initialize( *vars ) 
    230     super( *vars ) 
    231  
    232 # SOAP Basetype is a XSD type.  No need to reset @namespace. 
    233 #    @namespace = EnvelopeNamespace 
    234  
    235   end 
    236  
    237   def encode( ns, name ) 
    238     attrs = [] 
    239     createNS( attrs, ns ) 
    240     attrs.push( datatypeAttr( ns )) 
    241  
    242     if ( self.to_s.empty? ) 
    243       Element.new( name, attrs ) 
    244     else 
    245       Element.new( name, attrs, Text.new( self.to_s )) 
    246     end 
    247   end 
    248  
    249   def ==( rhs ) 
    250     self.data == rhs 
    251   end 
    252  
    253   private 
    254  
    255   def datatypeAttr( ns ) 
    256     Attr.new( ns.name( XSD::InstanceNamespace, 'type' ), ns.name( @namespace, @typeName )) 
    257   end 
    258  
    259   def createNS( attrs, ns ) 
    260     unless ns[ XSD::Namespace ] 
    261       tag = ns.assign( XSD::Namespace ) 
    262       attrs.push( Attr.new( 'xmlns:' << tag, XSD::Namespace )) 
    263     end 
    264   end 
    265 end 
    266  
    267  
    268 ### 
    269 ## Basic datatypes. 
    270 
    271 class SOAPNull < XSDNull 
    272   extend SOAPModuleUtils 
    273   include SOAPBasetypeUtils 
    274  
    275   private 
    276  
    277   # Override the definition in SOAPBasetypeUtils. 
    278   def datatypeAttr( ns ) 
    279     Attr.new( ns.name( XSD::Namespace, 'null' ), '1' ) 
    280   end 
    281  
    282   # Override the definition in SOAPModuleUtils 
    283   def decode( ns, elem ) 
    284     d = self.new() 
    285     d.namespace, = ns.parse( elem.nodeName ) 
    286     d 
    287   end 
    288 end 
    289  
    290 class SOAPBoolean < XSDBoolean 
    291   extend SOAPModuleUtils 
    292   include SOAPBasetypeUtils 
    293 end 
    294  
    295 class SOAPString < XSDString 
    296   extend SOAPModuleUtils 
    297   include SOAPBasetypeUtils 
    298 end 
    299  
    300 class SOAPInteger < XSDInteger 
    301   extend SOAPModuleUtils 
    302   include SOAPBasetypeUtils 
    303 end 
    304  
    305 class SOAPInt < XSDInt 
    306   extend SOAPModuleUtils 
    307   include SOAPBasetypeUtils 
    308 end 
    309  
    310 class SOAPTimeInstant < XSDTimeInstant 
    311   extend SOAPModuleUtils 
    312   include SOAPBasetypeUtils 
    313 end 
    314  
    315  
    316 ### 
    317 ## Compound datatypes. 
    318 
    319 class SOAPCompoundBase < NSDBase 
    320   extend SOAPModuleUtils 
    321  
    322   public 
    323  
    324   def initialize( typeName ) 
    325     super( typeName, EnvelopeNamespace ) 
    326   end 
    327 end 
    328  
    329  
    330 class SOAPStruct < SOAPCompoundBase 
    331   include Enumerable 
    332  
    333   public 
    334  
    335   attr_reader :array 
    336   attr_reader :data 
    337  
    338   def initialize( typeName ) 
    339     super( typeName ) 
    340     @array = [] 
    341     @data = {} 
    342   end 
    343  
    344   def to_s() 
    345     str = '' 
    346     self.each do | key, data | 
    347       str << "#{ key }: #{ data }\n" 
    348     end 
    349     str 
    350   end 
    351  
    352   def add( name, newMember ) 
    353     addMember( name, newMember ) 
    354   end 
    355  
    356   def []( idx ) 
    357     if ( idx > array.size ) 
    358       raise ArrayIndexOutOfBoundsError.new( 'In ' << @typeName ) 
    359     end 
    360     @array[ idx ] 
    361   end 
    362  
    363   def has_key?( name ) 
    364     @data.has_key?( name ) 
    365   end 
    366  
    367   def each 
    368     @array.each do | key | 
    369       yield( key, @data[ key ] ) 
    370     end 
    371   end 
    372  
    373   def encode( ns, name ) 
    374     attrs = [] 
    375     createNS( attrs, ns ) 
    376     attrs.push( datatypeAttr( ns )) 
    377  
    378     children = @array.collect { | child | 
    379       @data[ child ].encode( ns.clone, child ) 
    380     } 
    381  
    382     Element.new( name, attrs, children ) 
    383   end 
    384  
    385   def self.decode( ns, elem ) 
    386     namespace, name = ns.parse( elem.nodeName ) 
    387     s = SOAPStruct.new( name ) 
    388     s.namespace = namespace 
    389  
    390     elem.childNodes.each do | child | 
    391       childNS = ns.clone 
    392       parseNS( childNS, child ) 
    393       next if ( isEmptyText( child )) 
    394       childName = ns.parse( child.nodeName )[1] 
    395       s.add( childName, decodeChild( childNS, child )) 
    396     end 
    397     s 
    398   end 
    399  
    400   private 
    401  
    402   def datatypeAttr( ns ) 
    403     Attr.new( ns.name( XSD::InstanceNamespace, 'type' ), ns.name( @namespace, @typeName )) 
    404   end 
    405  
    406   def createNS( attrs, ns ) 
    407     unless ns[ @namespace ] 
    408       tag = ns.assign( @namespace ) 
    409       attrs.push( Attr.new( 'xmlns:' << tag, @namespace )) 
    410     end 
    411   end 
    412  
    413   def addMember( name, initMember = nil ) 
    414     initMember = SOAPNull.new() unless initMember 
    415  
    416     instance_eval <<-EOS 
    417       def #{ name }() 
    418         @data[ '#{ name }' ] 
    419       end 
    420  
    421       def #{ name }=( newMember ) 
    422         @data[ '#{ name }' ] = newMember 
    423       end 
    424     EOS 
    425  
    426     @array.push( name ) 
    427     @data[ name ] = initMember 
    428   end 
    429 end 
    430  
    431 class SOAPArray < SOAPCompoundBase 
    432   include Enumerable 
    433  
    434   public 
    435  
    436   attr_reader :data 
    437  
    438   def initialize( typeName = nil ) 
    439     super( typeName ) 
    440     @data = [ [] ] 
    441     @variant = false 
    442     @rank = 1 
    443   end 
    444  
    445   def set( newArray ) 
    446     raise NotImplementError.new( 'Partially transmittion does not supported' ) 
    447   end 
    448  
    449   def add( newMember ) 
    450     if ( @rank != 1 ) 
    451       raise NotImplementError.new( 'Rank must be 1' ) 
    452     end 
    453     if ( @data[ 0 ].empty? and !@typeName ) 
    454       @typeName = SOAPArray.getAtype( newMember.typeName, @rank ) 
    455       @namespace = newMember.namespace # ?? 
    456     end 
    457     if ( @typeName != newMember.typeName ) 
    458       @variant = true 
    459     end 
    460     @data[ 0 ] << newMember 
    461   end 
    462  
    463   def []( idx ) 
    464     if ( @rank != 1 ) 
    465       raise NotImplementError.new( 'Rank must be 1' ) 
    466     end 
    467     if ( idx > @data[ 0 ].size ) 
    468       raise ArrayIndexOutOfBoundsError.new( 'In ' << @typeName ) 
    469     end 
    470     @data[ 0 ][ idx ] 
    471   end 
    472  
    473   def each 
    474     if ( @rank != 1 ) 
    475       raise NotImplementError.new( 'Rank must be 1' ) 
    476     end 
    477     @data[ 0 ].each do | datum | 
    478       yield( datum ) 
    479     end 
    480   end 
    481  
    482   def encode( ns, name ) 
    483     attrs = [] 
    484     createNS( attrs, ns ) 
    485     attrs.push( datatypeAttr( ns )) 
    486  
    487     children = @data[ 0 ].collect { | child | 
    488       childTypeName = contentsTypeName().gsub( /\[,*\]/, 'Array' ) 
    489       child.encode( ns.clone, childTypeName ) 
    490     } 
    491     Element.new( name, attrs, children ) 
    492   end 
    493  
    494   def isVariant? 
    495     @variant 
    496   end 
    497  
    498   private 
    499  
    500   def datatypeAttr( ns ) 
    501     Attr.new( ns.name( EncodingNamespace, 'arrayType' ), ns.name( @namespace, arrayTypeValue() )) 
    502   end 
    503  
    504   def createNS( attrs, ns ) 
    505     unless ns[ @namespace ] 
    506       tag = ns.assign( @namespace ) 
    507       attrs.push( Attr.new( 'xmlns:' << tag, @namespace )) 
    508     end 
    509     unless ns[ EncodingNamespace ] 
    510       tag = ns.assign( EncodingNamespace ) 
    511       attrs.push( Attr.new( 'xmlns:' << tag, EncodingNamespace )) 
    512     end 
    513   end 
    514  
    515   def contentsTypeName() 
    516     @typeName.dup.sub( /\[,*\]$/, '' ) 
    517   end 
    518  
    519   def arrayTypeValue() 
    520     contentsTypeName << '[' << @data.collect { |i| i.size }.join( ',' ) << ']' 
    521   end 
    522  
    523   # Module function 
    524  
    525   public 
    526  
    527   def self.decode( ns, elem ) 
    528     typeNamespace, typeNameString = ns.parse( getType( ns, elem )) 
    529     typeName, nofArray = parseType( typeNameString ) 
    530     s = SOAPArray.new( typeName ) 
    531     s.namespace, = ns.parse( elem.nodeName ) 
    532  
    533     i = 0 
    534     elem.childNodes.each do | child | 
    535       childNS = ns.clone 
    536       parseNS( childNS, child ) 
    537       next if ( isEmptyText( child )) 
    538       s.add( decodeChild( childNS, child )) 
    539       i += 1 
    540       if ( nofArray and ( i > nofArray.to_i )) 
    541         raise ArrayIndexOutOfBoundsError.new( 'In ' << elem.nodeName ) 
    542       end 
    543     end 
    544     s 
    545   end 
    546  
    547   private 
    548  
    549   def self.getAtype( typeName, rank ) 
    550     "#{ typeName }[" << ',' * ( rank - 1 ) << ']' 
    551   end 
    552  
    553   TypeParseRegexp = Regexp.new( '^(.+)\[(\d*)\]$' ) 
    554  
    555   def self.parseType( string ) 
    556     TypeParseRegexp =~ string 
    557     return $1, $2 
    558   end 
    559 end 
     1require 'soap/baseData' 
  • trunk/lib/SOAPElement.rb

    r17 r24  
    1 =begin 
    2 SOAP4R 
    3 Copyright (C) 2000 NAKAMURA Hiroshi. 
    4  
    5 This program is free software; you can redistribute it and/or modify it under 
    6 the terms of the GNU General Public License as published by the Free Software 
    7 Foundation; either version 2 of the License, or (at your option) any later 
    8 version. 
    9  
    10 This program is distributed in the hope that it will be useful, but WITHOUT ANY 
    11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
    12 PRATICULAR PURPOSE. See the GNU General Public License for more details. 
    13  
    14 You should have received a copy of the GNU General Public License along with 
    15 this program; if not, write to the Free Software Foundation, Inc., 675 Mass 
    16 Ave, Cambridge, MA 02139, USA. 
    17 =end 
    18  
    19 require 'SOAPData' 
    20 require 'xmltreebuilder' 
    21  
    22  
    23 ### 
    24 ## SOAP elements 
    25 
    26 class SOAPMethod < SOAPCompoundBase 
    27   public 
    28  
    29   attr_reader :namespace 
    30   attr_reader :name 
    31   attr_reader :paramDef 
    32  
    33   attr_accessor :paramNames 
    34   attr_reader :paramTypes 
    35   attr_reader :params 
    36  
    37   attr_reader :retName 
    38   attr_accessor :retVal 
    39  
    40   def initialize( namespace, name, paramDef = nil ) 
    41     super( self.type.to_s ) 
    42  
    43     @namespace = namespace 
    44     @name = name 
    45     @paramDef = paramDef 
    46  
    47     @paramNames = [] 
    48     @paramTypes = {} 
    49     @params = {} 
    50     @retName = nil 
    51     @retVal = nil 
    52  
    53     setParamDef() if @paramDef 
    54   end 
    55  
    56   def setParams( params ) 
    57     params.each do | param, data | 
    58       @params[ param ] = data 
    59     end 
    60   end 
    61  
    62   def encode( ns, forResponse = false ) 
    63     if !forResponse 
    64       paramElem = @paramNames.collect { | param | 
    65         @params[ param ].encode( ns.clone, param ) 
    66       } 
    67       Element.new( ns.name( @namespace, @name ), nil, paramElem ) 
    68     else 
    69       retElem = nil 
    70       if retVal.is_a?( SOAPStruct ) 
    71         children = retVal.collect { | param, data | 
    72           data.encode( ns.clone, param ) 
    73         } 
    74         retElem = Element.new( 'return', nil, children ) 
    75       else 
    76         retElem = retVal.encode( ns.clone, 'return' ) 
    77       end 
    78       Element.new( ns.name( @namespace, @name ), nil, retElem ) 
    79     end 
    80   end 
    81  
    82   private 
    83  
    84   def setParamDef() 
    85     @paramDef.each do | pair | 
    86       type, name = pair 
    87       type.scan( /[^,\s]+/ ).each do | typeToken | 
    88         case typeToken 
    89         when 'in' 
    90           @paramNames.push( name ) 
    91           @paramTypes[ name ] = 1 
    92         when 'out' 
    93           @paramNames.push( name ) 
    94           @paramTypes[ name ] = 2 
    95         when 'retval' 
    96           if ( @retName ) 
    97             raise MethodDefinitionError.new( 'Duplicated retval' ) 
    98           end 
    99           @retName = name 
    100         else 
    101           raise MethodDefinitionError.new( 'Unknown type: ' << typeToken ) 
    102         end 
    103       end 
    104     end 
    105   end 
    106  
    107   # Module function 
    108  
    109   public 
    110  
    111   def self.decode( ns, elem ) 
    112     retVal = nil 
    113     outParams = {} 
    114     elem.childNodes.each do | child | 
    115       next if ( isEmptyText( child )) 
    116       childNS = ns.clone 
    117       parseNS( childNS, child ) 
    118       if ( !retVal ) 
    119         retVal = decodeChild( childNS, child ) 
    120       else 
    121         # ToDo: [in/out] or [out] parameters here... 
    122         raise NotImplementError.new( '"out" parameters not supported.' ) 
    123       end 
    124     end 
    125  
    126     elemNamespace, elemName = ns.parse( elem.nodeName ) 
    127     m = SOAPMethod.new( elemNamespace, elemName ) 
    128  
    129     m.retVal = retVal 
    130     #m.setParams( outParams ) 
    131     m 
    132   end 
    133 end 
    134  
    135  
    136 class SOAPFault < SOAPCompoundBase 
    137   public 
    138  
    139   attr_reader :faultCode 
    140   attr_reader :faultString 
    141   attr_reader :faultActor 
    142   attr_reader :detail 
    143   attr_reader :options 
    144  
    145   def initialize( faultCode, faultString, faultActor, detail = nil, options = [] ) 
    146     super( self.type.to_s ) 
    147     @faultCode = faultCode 
    148     @faultString = faultString 
    149     @faultActor = faultActor 
    150     @detail = detail 
    151     @options = options 
    152   end 
    153  
    154   def encode( ns ) 
    155     # Caution: never been executed!! 
    156     faultElems = [ @faultCode.encode( ns, 'faultcode' ), 
    157       @faultString.encode( ns, 'faultstring' ), 
    158       @faultActor.encode( ns, 'faultactor' ) ] 
    159     faultElems.push( @detail.encode( ns, 'detail' )) if @detail 
    160     @options.each do | opt | 
    161       paramElem.push( opt.encode( ns )) 
    162     end 
    163     Element.new( ns.name( EnvelopeNamespace, 'Fault' ), nil, faultElems ) 
    164   end 
    165  
    166   # Module function 
    167  
    168   public 
    169  
    170   def self.decode( ns, elem ) 
    171     faultCode = nil 
    172     faultString = nil 
    173     faultActor = nil 
    174     detail = nil 
    175     options = [] 
    176     elem.childNodes.each do | child | 
    177       next if ( isEmptyText( child )) 
    178       childNS = ns.clone 
    179       parseNS( childNS, child ) 
    180  
    181       if ( childNS.compare( EnvelopeNamespace, 'faultcode', child.nodeName )) 
    182         raise FormatDecodeError.new( 'Duplicated faultcode in Fault' ) if faultCode 
    183         faultCode = SOAPInteger.decode( childNS, child ) 
    184  
    185       elsif ( childNS.compare( EnvelopeNamespace, 'faultstring', child.nodeName )) 
    186         raise FormatDecodeError.new( 'Duplicated faultstring in Fault' ) if faultString 
    187         faultString = SOAPString.decode( childNS, child ) 
    188  
    189       elsif ( childNS.compare( EnvelopeNamespace, 'faultactor', child.nodeName )) 
    190         raise FormatDecodeError.new( 'Duplicated faultactor in Fault' ) if faultActor 
    191         faultActor = SOAPString.decode( childNS, child ) 
    192  
    193       elsif ( childNS.compare( EnvelopeNamespace, 'detail', child.nodeName )) 
    194         raise FormatDecodeError.new( 'Duplicated detail in Fault' ) if detail 
    195         detail = decodeChild( childNS, child ) 
    196  
    197       else 
    198         options.push( decodeChild( childNS, child )) 
    199       end 
    200     end 
    201  
    202     SOAPFault.new( faultCode, faultString, faultActor, detail, options ) 
    203   end 
    204 end 
    205  
    206  
    207 class SOAPBody < SOAPCompoundBase 
    208   public 
    209  
    210   attr_reader :data 
    211   attr_reader :isFault 
    212  
    213   def initialize( data, isFault = false ) 
    214     super( self.type.to_s ) 
    215     @data = data 
    216     @isFault = isFault 
    217   end 
    218  
    219   def encode( ns, forResponse = false ) 
    220     attrs = [] 
    221     contents = nil 
    222     if @isFault 
    223       contents = @data.encode( ns ) 
    224     else 
    225       attrs.push( Attr.new( ns.name( EnvelopeNamespace, AttrEncodingStyle ), EncodingNamespace )) 
    226       contents = @data.encode( ns, forResponse ) 
    227     end 
    228  
    229     Element.new( ns.name( EnvelopeNamespace, 'Body' ), attrs, contents ) 
    230   end 
    231  
    232   # Module function 
    233  
    234   public 
    235  
    236   def self.decode( ns, elem ) 
    237     data = nil 
    238     isFault = false 
    239     result = [] 
    240  
    241     elem.childNodes.each do | child | 
    242       childNS = ns.clone 
    243       parseNS( childNS, child ) 
    244       if ( isEmptyText( child )) 
    245         # Nothing to do. 
    246       elsif ( childNS.compare( EnvelopeNamespace, 'Fault', child.nodeName )) 
    247         data = SOAPFault.decode( childNS, child ) 
    248         isFault = true 
    249       elsif !data 
    250         data = SOAPMethod.decode( childNS, child ) 
    251       else 
    252         # ToDo: May be a pointer... 
    253         result.push( child ) 
    254         raise FormatDecodeError.new( 'Unknown node name: ' << child.nodeName ) 
    255       end 
    256     end 
    257  
    258     # ToDo: Must resolve pointers in result... 
    259  
    260     SOAPBody.new( data, isFault ) 
    261   end 
    262 end 
    263  
    264  
    265 class SOAPHeaderItem < SOAPCompoundBase 
    266   public 
    267  
    268   attr_reader :namespace 
    269   attr_reader :name 
    270   attr_accessor :content 
    271   attr_accessor :mustUnderstand 
    272   attr_accessor :encodingStyle 
    273  
    274   def initialize( namespace, name, content, mustUnderstand = false, encodingStyle = nil ) 
    275     super( self.type.to_s ) 
    276     @namespace = namespace 
    277     @name = name 
    278     @content = content 
    279     @mustUnderstand = mustUnderstand 
    280     @encodingStyle = encodingStyle 
    281   end 
    282  
    283   def encode( ns ) 
    284     return nil if @name.empty? 
    285     attrs = [] 
    286     attrs.push( Attr.new( ns.name( EnvelopeNamespace, AttrMustUnderstand ), ( @mustUnderstand ? '1' : '0' ))) 
    287     attrs.push( Attr.new( ns.name( EnvelopeNamespace, AttrEncodingStyle ), @encodingStyle )) if @encodingStyle 
    288     Element.new( ns.name( @namespace, @name ), attrs, @content ) 
    289   end 
    290  
    291   # Module function 
    292  
    293   public 
    294  
    295   def self.decode( ns, elem ) 
    296     mustUnderstand = nil 
    297     encodingStyle = nil 
    298     elem.attributes.each do | attr | 
    299       name = attr.nodeName 
    300       if ( ns.compare( EnvelopeNamespace, AttrMustUnderstand, name )) 
    301         raise FormatDecodeError.new( 'Duplicated mustUnderstand in HeaderItem' ) if mustUnderstand 
    302         mustUnderstand = attr.nodeValue 
    303       elsif ( ns.compare( EnvelopeNamespace, AttrEncodingStyle, name )) 
    304         raise FormatDecodeError.new( 'Duplicated encodingStyle in HeaderItem' ) if encodingStyle 
    305         encodingStyle = attr.nodeValue 
    306       else 
    307         raise FormatDecodeError.new( 'Unknown attribute: ' << name ) 
    308       end 
    309     end 
    310     elemNamespace, elemName = ns.parse( elem.nodeName ) 
    311  
    312     # Convert NodeList to simple Array. 
    313     childArray = [] 
    314     elem.childNodes.each do | child | 
    315       childArray.push( child ) 
    316     end 
    317  
    318     SOAPHeaderItem.new( elemNamespace, elemName, childArray, mustUnderstand, encodingStyle ) 
    319   end 
    320 end 
    321  
    322  
    323 class SOAPHeader < SOAPArray 
    324   public 
    325  
    326   def initialize() 
    327     super( self.type.to_s ) 
    328   end 
    329  
    330   def encode( ns ) 
    331     children = @data.collect { | child | 
    332       child.encode( ns.clone ) 
    333     } 
    334     Element.new( ns.name( EnvelopeNamespace, 'Header' ), nil, children ) 
    335   end 
    336  
    337   def length 
    338     @data[ 0 ].length 
    339   end 
    340  
    341   # Module function 
    342  
    343   public 
    344  
    345   def self.decode( ns, elem ) 
    346     s = SOAPHeader.new() 
    347     elem.childNodes.each do | child | 
    348       childNS = ns.clone 
    349       parseNS( childNS, child ) 
    350       next if ( isEmptyText( child )) 
    351       s.add( SOAPHeaderItem.decode( childNS, child )) 
    352     end 
    353     s 
    354   end 
    355 end 
    356  
    357  
    358 class SOAPEnvelope < SOAPCompoundBase 
    359   public 
    360  
    361   attr_reader :header 
    362   attr_reader :body 
    363  
    364   def initialize( initHeader, initBody ) 
    365     super( self.type.to_s ) 
    366     @header = initHeader 
    367     @body = initBody 
    368   end 
    369  
    370   def encode( ns ) 
    371     # Namespace preloading. 
    372     attrs = ns.namespaceTag.collect { | namespace, tag | 
    373       if ( tag == '' ) 
    374         Attr.new( 'xmlns' , namespace ) 
    375       else 
    376         Attr.new( 'xmlns:' << tag, namespace ) 
    377       end 
    378     } 
    379  
    380     contents = [] 
    381     contents.push( @header.encode( ns )) if @header and @header.length > 0 
    382     contents.push( @body.encode( ns )) 
    383  
    384     Element.new( ns.name( EnvelopeNamespace, 'Envelope' ), attrs, contents ) 
    385   end 
    386  
    387   # Module function 
    388  
    389   public 
    390  
    391   def self.decode( ns, doc ) 
    392     if ( doc.childNodes.size != 1 ) 
    393       raise FormatDecodeError.new( 'Envelope must be a child.' ) 
    394     end 
    395  
    396     elem = doc.childNodes[ 0 ] 
    397     parseNS( ns, elem ) 
    398  
    399     if ( !ns.compare( EnvelopeNamespace, 'Envelope', elem.nodeName )) 
    400       raise FormatDecodeError.new( 'Envelope not found.' ) 
    401     end 
    402  
    403     header = nil 
    404     body = nil 
    405     elem.childNodes.each do | child | 
    406       childNS = ns.clone 
    407       parseNS( childNS, child ) 
    408       name = child.nodeName 
    409       if ( isEmptyText( child )) 
    410         # Nothing to do. 
    411       elsif ( childNS.compare( EnvelopeNamespace, 'Header', name )) 
    412         raise FormatDecodeError.new( 'Duplicated Header in Envelope' ) if header 
    413         header = SOAPHeader.decode( childNS, child ) 
    414       elsif ( childNS.compare( EnvelopeNamespace, 'Body', name )) 
    415         raise FormatDecodeError.new( 'Duplicated Body in Envelope' ) if body 
    416         body = SOAPBody.decode( childNS, child ) 
    417       else 
    418         raise FormatDecodeError.new( 'Unknown scoping element: ' << name ) 
    419       end 
    420     end 
    421  
    422     SOAPEnvelope.new( header, body ) 
    423   end 
    424 end 
     1requre 'soap/element' 
  • trunk/lib/SOAPProcessor.rb

    r21 r24  
    1 =begin 
    2 SOAP4R 
    3 Copyright (C) 2000 NAKAMURA Hiroshi. 
    4  
    5 This program is free software; you can redistribute it and/or modify it under 
    6 the terms of the GNU General Public License as published by the Free Software 
    7 Foundation; either version 2 of the License, or (at your option) any later 
    8 version. 
    9  
    10 This program is distributed in the hope that it will be useful, but WITHOUT ANY 
    11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
    12 PRATICULAR PURPOSE. See the GNU General Public License for more details. 
    13  
    14 You should have received a copy of the GNU General Public License along with 
    15 this program; if not, write to the Free Software Foundation, Inc., 675 Mass 
    16 Ave, Cambridge, MA 02139, USA. 
    17 =end 
    18  
    19 require 'SOAP' 
    20 require 'SOAPElement' 
    21 require 'XMLSchemaDatatypes' 
    22  
    23 module SOAPProcessor 
    24   public 
    25  
    26   ### 
    27   ## SOAP marshaling 
    28   # 
    29   def marshal( ns, header, body ) 
    30  
    31     # Namespace preparing. 
    32     ns.assign( SOAP::EnvelopeNamespace, SOAPNamespaceTag ) 
    33     ns.assign( XSD::Namespace, XSDNamespaceTag ) 
    34     ns.assign( XSD::InstanceNamespace, XSINamespaceTag ) 
    35  
    36     # Create SOAP envelope. 
    37     env = SOAPEnvelope.new( header, body ) 
    38  
    39     # XML tree construction. 
    40     XML::SimpleTree::Document.new( env.encode( ns )) 
    41   end 
    42  
    43   ### 
    44   ## SOAP unmarshaling 
    45   # 
    46   def unmarshal( stream ) 
    47  
    48     # Namespace preparing. 
    49     ns = SOAPNS.new() 
    50  
    51     # XML tree parsing. 
    52     builder = XML::SimpleTreeBuilder.new() 
    53     tree = builder.parse( stream ) 
    54     tree.documentElement.normalize 
    55  
    56     # Parse SOAP envelope. 
    57     env = SOAPEnvelope.decode( ns, tree ) 
    58  
    59     return ns, env.header, env.body 
    60   end 
    61  
    62   private 
    63  
    64   SOAPNamespaceTag = 'SOAP-ENV' 
    65   XSDNamespaceTag = 'xsd' 
    66   XSINamespaceTag = 'xsi' 
    67 end 
     1require 'soap/processor' 
  • trunk/lib/SOAPProxy.rb

    r20 r24  
    1 =begin 
    2 SOAP4R 
    3 Copyright (C) 2000 NAKAMURA Hiroshi. 
    4  
    5 This program is free software; you can redistribute it and/or modify it under 
    6 the terms of the GNU General Public License as published by the Free Software 
    7 Foundation; either version 2 of the License, or (at your option) any later 
    8 version. 
    9  
    10 This program is distributed in the hope that it will be useful, but WITHOUT ANY 
    11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
    12 PRATICULAR PURPOSE. See the GNU General Public License for more details. 
    13  
    14 You should have received a copy of the GNU General Public License along with 
    15 this program; if not, write to the Free Software Foundation, Inc., 675 Mass 
    16 Ave, Cambridge, MA 02139, USA. 
    17 =end 
    18  
    19 require 'SOAP' 
    20 require 'SOAPProcessor' 
    21 require 'SOAPStreamHandler' 
    22  
    23  
    24 class SOAPProxy 
    25   include SOAPProcessor 
    26  
    27   public 
    28  
    29   attr_reader :namespace 
    30  
    31   def initialize( namespace, streamHandler ) 
    32     @namespace = namespace 
    33     @handler = streamHandler 
    34     @method = {} 
    35   end 
    36  
    37   class Request 
    38     public 
    39  
    40     attr_reader :method 
    41     attr_reader :namespace 
    42     attr_reader :name 
    43  
    44     def initialize( modelMethod, values ) 
    45       @method = SOAPMethod.new( modelMethod.namespace, modelMethod.name, 
    46         modelMethod.paramDef ) 
    47       @namespace = @method.namespace 
    48       @name = @method.name 
    49  
    50       params = {} 
    51      
    52       if (( values.size == 1 ) and ( values[0].is_a?( Hash ))) 
    53         params = values[ 0 ] 
    54       else 
    55         0.upto( values.size - 1 ) do | i | 
    56           params[ @method.paramNames[ i ]] = values[ i ] || SOAPNull.new() 
    57         end 
    58       end 
    59       @method.setParams( params ) 
    60     end 
    61   end 
    62  
    63   # Method definition. 
    64   def addMethod( methodName, paramDef ) 
    65     @method[ methodName ] = SOAPMethod.new( @namespace, methodName, paramDef ) 
    66   end 
    67  
    68   # Create new request. 
    69   def createRequest( methodName, *values ) 
    70     if ( @method.has_key?( methodName )) 
    71       method = @method[ methodName ] 
    72     else 
    73       raise MethodDefinitionError.new( 'Method: ' << methodName << ' not defined.' ) 
    74     end 
    75  
    76     Request.new( method, values ) 
    77   end 
    78  
    79   # Method calling. 
    80   def call( ns, headers, methodName, *values ) 
    81  
    82     # Create new request 
    83     req = createRequest( methodName, *values ) 
    84  
    85     # SOAP tree construction. 
    86     tree = createTree( ns, headers, req ) 
    87  
    88     # Send request. 
    89     receiveString = sendRequest( req, tree ) 
    90  
    91     # SOAP tree parsing. 
    92     ns, header, body = unmarshal( receiveString ) 
    93  
    94     # Check Fault. 
    95     checkFault( ns, body ) 
    96  
    97     # Used namespaces, header element, and body element. 
    98     return ns, header, body 
    99   end 
    100  
    101   # SOAP tree construction. 
    102   def createTree( ns, headers, request ) 
    103     # Preparing headers. 
    104     header = SOAPHeader.new() 
    105     if headers 
    106       headers.each do | namespace, elem, content, mustUnderstand, encodingStyle | 
    107         header.add( SOAPHeaderItem.new( namespace, elem, content, mustUnderstand, encodingStyle )) 
    108       end 
    109     end 
    110  
    111     # Preparing body. 
    112     body = SOAPBody.new( request.method ) 
    113  
    114     # Tree construction. 
    115     soapTree = marshal( ns, header, body ) 
    116  
    117     return soapTree 
    118   end 
    119  
    120   # Send the request. 
    121   def sendRequest( request, tree ) 
    122     # Serialize. 
    123     sendString = tree.to_s 
    124  
    125     # Send request. 
    126     receiveString = @handler.send( request.namespace, request.name, sendString ) 
    127  
    128     receiveString 
    129   end 
    130  
    131   # SOAP Fault checking. 
    132   def checkFault( ns, body ) 
    133     if ( body.isFault ) 
    134       raise FaultError.new( body.data ) 
    135     end 
    136   end 
    137 end 
     1require 'soap/proxy' 
  • trunk/lib/SOAPStreamHandler.rb

    r19 r24  
    1 =begin 
    2 SOAP4R 
    3 Copyright (C) 2000 NAKAMURA Hiroshi. 
    4  
    5 This program is free software; you can redistribute it and/or modify it under 
    6 the terms of the GNU General Public License as published by the Free Software 
    7 Foundation; either version 2 of the License, or (at your option) any later 
    8 version. 
    9  
    10 This program is distributed in the hope that it will be useful, but WITHOUT ANY 
    11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
    12 PRATICULAR PURPOSE. See the GNU General Public License for more details. 
    13  
    14 You should have received a copy of the GNU General Public License along with 
    15 this program; if not, write to the Free Software Foundation, Inc., 675 Mass 
    16 Ave, Cambridge, MA 02139, USA. 
    17 =end 
    18  
    19 require 'socket' 
    20 require 'timeout' 
    21  
    22 require 'SOAP' 
    23 require 'http-access' 
    24 require 'uri' 
    25  
    26 class SOAPStreamHandler 
    27   public 
    28  
    29   attr_reader :endPoint 
    30  
    31   def initialize( endPoint ) 
    32     @endPoint = endPoint 
    33   end 
    34 end 
    35  
    36  
    37 class SOAPHTTPPostStreamHandler < SOAPStreamHandler 
    38   public 
    39    
    40   MediaType = 'text/xml' 
    41  
    42   NofRetry = 10       # [times] 
    43   CallTimeout = 3