soap-lc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,155 @@
1
+ require 'soap/lc/response'
2
+
3
+ module SOAP
4
+ class Request
5
+ def initialize( wsdl ) #:nodoc:
6
+ @wsdl = wsdl
7
+ @request = nil
8
+ end
9
+
10
+ # Call a method for the current Request and get a SOAP::Response
11
+ #
12
+ # Example:
13
+ # wsdl = SOAP::LC.new( ).wsdl( "http://..." )
14
+ # request = wsdl.request( )
15
+ # response = request.myMethod( :param1 => "hello" )
16
+ # # => #<SOAP::Response:0xNNNNNN>
17
+ def method_missing( id, *args )
18
+ call( id.id2name, args[0] )
19
+ end
20
+
21
+ # Call a method for the current Request and get a SOAP::Response
22
+ #
23
+ # Example:
24
+ # wsdl = SOAP::LC.new( ).wsdl( "http://..." )
25
+ # request = wsdl.request( )
26
+ # response = request.call( "myMethod", :param1 => "hello" )
27
+ # # => #<SOAP::Response:0xNNNNNN>
28
+ def call( methodName, args )
29
+ args = (args || {}).keys_to_sym!
30
+
31
+ # Get Binding
32
+ binding = @wsdl.bindings.getBindingForOperationName( methodName )
33
+ raise SOAP::LCNoMethodError, "Undefined method `#{methodName}'" if binding.nil?
34
+
35
+ # Get Binding Operation
36
+ binding_operation = binding.operations[methodName]
37
+
38
+ # Get PortType
39
+ portType = @wsdl.portTypes[binding.type.nns]
40
+ portType_operation = portType.operations[methodName]
41
+
42
+ # Get message for input operation
43
+ input_message = @wsdl.messages[portType_operation[:input][:message].nns]
44
+
45
+ # Create method
46
+ soap_method = "<#{methodName} xmlns=\"#{@wsdl.targetNamespace}\">\n"
47
+ input_message.parts.each do |_, attrs|
48
+
49
+ case attrs[:mode]
50
+ when :type
51
+ if SOAP::XSD::ANY_SIMPLE_TYPE.include?( attrs[attrs[:mode]].nns )
52
+ # Part refer to a builtin SimpleType
53
+ soap_method << SOAP::XSD.displayBuiltinType( attrs[:name], args, 1, 1 )
54
+ else
55
+ # Part refer to an XSD simpleType or complexType defined in types
56
+ element = @wsdl.types[attrs[attrs[:mode]].nns][:value]
57
+ case element[:type]
58
+ when :simpleType
59
+ soap_method << "<#{attrs[:name]}>\n#{element.display( @wsdl.types, args )}\n</#{attrs[:name]}>\n" # MAYBE ##########
60
+ when :complexType
61
+ soap_method << "<#{attrs[:name]}>\n#{element.display( @wsdl.types, args )}\n</#{attrs[:name]}>\n" # MAYBE ##########
62
+ else
63
+ raise SOAP::LCWSDLError, "Malformated part #{attrs[:name]}"
64
+ end
65
+ end
66
+ when :element
67
+ # Part refer to an XSD element
68
+ element = @wsdl.types[attrs[attrs[:mode]].nns][:value]
69
+ case element[:type]
70
+ when :simpleType
71
+ soap_method << element[element[:type]].display( @wsdl.types, args )
72
+ when :complexType
73
+ soap_method << element[element[:type]].display( @wsdl.types, args )
74
+ else
75
+ raise SOAL::LCWSDLError, "Malformated element `#{attrs[attrs[:mode]]}'"
76
+ end
77
+
78
+ ## TODO ---------- USE element[:key]
79
+ else
80
+ raise SOAP::LCWSDLError, "Malformated part #{attrs[:name]}"
81
+ end
82
+ end
83
+ soap_method += "</#{methodName}>\n"
84
+
85
+ # Create SOAP Envelope
86
+ envelope = soap_envelop do
87
+ soap_header + soap_body( soap_method )
88
+ end
89
+
90
+ # Create headers
91
+ headers = {
92
+ 'Content-Type' => 'application/soap+xml; charset=utf-8',
93
+ 'Content-Length' => "#{envelope.length}"
94
+ }
95
+ # Add SOAPAction to headers (if exist)
96
+ action = begin
97
+ binding_operation[:soapAction]
98
+ rescue
99
+ nil
100
+ end
101
+ headers['SOAPAction'] = action unless action.nil? or action.length == 0
102
+
103
+ # Search URI
104
+ service_port = @wsdl.services.getServicePortForBindingName( binding.name )
105
+ address = service_port[:address]
106
+
107
+ # Complete request
108
+ @request = {
109
+ :headers => headers,
110
+ :envelope => envelope,
111
+ :uri => address,
112
+ :response => @wsdl.messages[portType_operation[:output][:message].nns].name
113
+ }
114
+
115
+ return self
116
+ end
117
+
118
+ # Get the SOAP Body for the request
119
+ def soap_body( soap_method )
120
+ "<SOAP-ENV:Body>\n" + soap_method + "</SOAP-ENV:Body>\n"
121
+ end
122
+
123
+ # Send request to the server and get a response (SOAP::Response)
124
+ def response( )
125
+ return( SOAP::Response.new( @request ) )
126
+ end
127
+ alias_method :result, :response
128
+
129
+ # Get the SOAP Envelope for the request
130
+ def envelope( )
131
+ @request[:envelope] || nil
132
+ end
133
+
134
+ # Get request headers
135
+ def headers( )
136
+ @request[:headers] || nil
137
+ end
138
+
139
+ private
140
+ def soap_envelop( &b )
141
+ "<SOAP-ENV:Envelope
142
+ xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"
143
+ xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"
144
+ xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
145
+ xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
146
+ SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" +
147
+ yield() +
148
+ '</SOAP-ENV:Envelope>'
149
+ end
150
+
151
+ def soap_header()
152
+ "<SOAP-ENV:Header/>\n"
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+
4
+ module SOAP
5
+ class Response
6
+ # XML response
7
+ attr_reader :to_xml
8
+ # Hash response
9
+ attr_reader :to_h
10
+
11
+ def initialize( request ) #:nodoc:
12
+ url = URI.parse( request[:uri] )
13
+ @soap_response = Net::HTTP.new( url.host, url.port ).start { |http|
14
+ http.post( url.request_uri, request[:envelope], request[:headers] )
15
+ }
16
+
17
+ @to_xml = @soap_response.body
18
+ @to_h = Hash.from_xml( @soap_response.body )["Envelope"]["Body"][request[:response]]
19
+ end
20
+
21
+ # Return SOAP error
22
+ def error
23
+ @soap_response.error!
24
+ end
25
+
26
+ def method_missing( id, *args ) #:nodoc:
27
+ puts id.id2name
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,42 @@
1
+ require 'soap/lc/wsdl/parser'
2
+ require 'soap/lc/request'
3
+
4
+ module SOAP
5
+ class WSDL
6
+ attr_reader :parse
7
+
8
+ def initialize( uri ) #:nodoc:
9
+ @parse = SOAP::WSDL::Parser.new( uri )
10
+ end
11
+
12
+ # Call a method for the current WSDL and get the corresponding SOAP::Request
13
+ #
14
+ # Example:
15
+ # wsdl = SOAP::LC.new( ).wsdl( "http://..." )
16
+ # request = wsdl.myMethod( :param1 => "hello" )
17
+ # # => #<SOAP::Request:0xNNNNNN>
18
+ def method_missing( id, *args )
19
+ return request.call( id.id2name, args[0] )
20
+ end
21
+
22
+ # Call a method for the current WSDL and get the corresponding SOAP::Request
23
+ #
24
+ # Example:
25
+ # wsdl = SOAP::LC.new( ).wsdl( "http://..." )
26
+ # request = wsdl.call( "myMethod", { :param1 => "hello" } )
27
+ # # => #<SOAP::Request:0xNNNNNN>
28
+ def call( name, args )
29
+ return request.call( name, args )
30
+ end
31
+
32
+ # Get a SOAP::Request object for the current WSDL
33
+ #
34
+ # Example:
35
+ # wsdl = SOAP::LC.new( ).wsdl( "http://..." )
36
+ # request = wsdl.request( )
37
+ # # => #<SOAP::Request:0xNNNNNN>
38
+ def request( )
39
+ return SOAP::Request.new( @parse )
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,160 @@
1
+ module SOAP
2
+ class WSDL
3
+ class Bindings < Hash
4
+ def getBindingForOperationName( name )
5
+ self.each do |binding_name, binding|
6
+ return binding if binding.operations.keys.include?(name)
7
+ end
8
+ return nil
9
+ end
10
+ end
11
+
12
+ class Binding
13
+ attr_reader :operations
14
+ attr_reader :name
15
+ attr_reader :type
16
+ attr_reader :style
17
+ attr_reader :transport
18
+
19
+ def initialize( element )
20
+ @operations = Hash.new
21
+ @name = element.attributes['name']
22
+ @type = element.attributes['type'] # because of Object#type
23
+ @style = nil
24
+ @transport = nil
25
+
26
+ # Process all binding and operation
27
+ element.find_all {|e| e.class == REXML::Element }.each { |operation|
28
+ case operation.name
29
+ when "binding"
30
+ # Get binding attributs
31
+ operation.attributes.each { |name, value|
32
+ case name
33
+ when 'style'
34
+ @style = value
35
+ when 'transport'
36
+ @transport = value
37
+ else
38
+ warn "Ignoring attribut `#{name}' for wsdlsoap:binding in binding `#{element.attributes['name']}'"
39
+ end
40
+ }
41
+ when "operation"
42
+ # Store operations
43
+ @operations[operation.attributes['name']] = Hash.new()
44
+
45
+ # Get operation attributs
46
+ operation.attributes.each { |name, value|
47
+ case name
48
+ when 'name'
49
+ @operations[operation.attributes['name']][:name] = value
50
+ else
51
+ warn "Ignoring attribut `#{name}' for operation `#{operation.attributes['name']}' in binding `#{element.attributes['name']}'"
52
+ end
53
+ }
54
+
55
+ # Store operation input, output, fault and operation
56
+ operation.find_all {|e| e.class == REXML::Element }.each { |action|
57
+ case action.name
58
+ when "operation"
59
+ # Get operation attributs
60
+ action.attributes.each { |name, value|
61
+ case name
62
+ when 'soapAction'
63
+ @operations[operation.attributes['name']][:soapAction] = value
64
+ else
65
+ warn "Ignoring attribut `#{name}' for wsdlsoap:operation in operation `#{operation.attributes['name']}' in binding `#{element.attributes['name']}'"
66
+ end
67
+ }
68
+ when "input"
69
+ @operations[operation.attributes['name']][:input] = Hash.new
70
+
71
+ # Store input attributs
72
+ action.attributes.each { |name, value|
73
+ case name
74
+ when 'name'
75
+ @operations[operation.attributes['name']][:input][:name] = value
76
+ else
77
+ warn "Ignoring attribut `#{name}' in #{action.name} `#{action.attributes['name']}' in operation `#{operation.attributes['name']}' for binding `#{element.attributes['name']}'"
78
+ end
79
+ }
80
+
81
+ # Store body
82
+ action.find_all {|e| e.class == REXML::Element }.each { |body|
83
+ case body.name
84
+ when "body"
85
+ @operations[operation.attributes['name']][:input][:body] = Hash.new
86
+
87
+ # Store body attributes
88
+ body.attributes.each { |name, value|
89
+ @operations[operation.attributes['name']][:input][:body][name.to_sym] = value
90
+ }
91
+ else
92
+ warn "Ignoring element `#{body.name}' in #{action.name} `#{action.attributes['name']}' in operation `#{operation.attributes['name']}' for binding `#{element.attributes['name']}'"
93
+ end
94
+ }
95
+ when "output"
96
+ @operations[operation.attributes['name']][:output] = Hash.new
97
+
98
+ # Store input attributs
99
+ action.attributes.each { |name, value|
100
+ case name
101
+ when 'name'
102
+ @operations[operation.attributes['name']][:output][:name] = value
103
+ else
104
+ warn "Ignoring attribut `#{name}' in #{action.name} `#{action.attributes['name']}' in operation `#{operation.attributes['name']}' for binding `#{element.attributes['name']}'"
105
+ end
106
+ }
107
+
108
+ # Store body
109
+ action.find_all {|e| e.class == REXML::Element }.each { |body|
110
+ case body.name
111
+ when "body"
112
+ @operations[operation.attributes['name']][:output][:body] = Hash.new
113
+
114
+ # Store body attributes
115
+ body.attributes.each { |name, value|
116
+ @operations[operation.attributes['name']][:output][:body][name.to_sym] = value
117
+ }
118
+ else
119
+ warn "Ignoring element `#{body.name}' in #{action.name} `#{action.attributes['name']}' in operation `#{operation.attributes['name']}' for binding `#{element.attributes['name']}'"
120
+ end
121
+ }
122
+ when "fault"
123
+ @operations[operation.attributes['name']][:fault] = Hash.new
124
+
125
+ # Store input attributs
126
+ action.attributes.each { |name, value|
127
+ case name
128
+ when 'name'
129
+ @operations[operation.attributes['name']][:fault][:name] = value
130
+ else
131
+ warn "Ignoring attribut `#{name}' in #{action.name} `#{action.attributes['name']}' in operation `#{operation.attributes['name']}' for binding `#{element.attributes['name']}'"
132
+ end
133
+ }
134
+
135
+ # Store body
136
+ action.find_all {|e| e.class == REXML::Element }.each { |body|
137
+ case body.name
138
+ when "body"
139
+ @operations[operation.attributes['name']][:fault][:body] = Hash.new
140
+
141
+ # Store body attributes
142
+ body.attributes.each { |name, value|
143
+ @operations[operation.attributes['name']][:fault][:body][name.to_sym] = value
144
+ }
145
+ else
146
+ warn "Ignoring element `#{body.name}' in #{action.name} `#{action.attributes['name']}' in operation `#{operation.attributes['name']}' for binding `#{element.attributes['name']}'"
147
+ end
148
+ }
149
+ else
150
+ warn "Ignoring element `#{action.name}' in operation `#{operation.attributes['name']}' for binding `#{element.attributes['name']}'"
151
+ end
152
+ }
153
+ else
154
+ warn "Ignoring element `#{operation.name}' in binding `#{element.attributes['name']}'"
155
+ end
156
+ }
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,44 @@
1
+ require 'soap/lc/error'
2
+
3
+ module SOAP
4
+ class WSDL
5
+ class Messages < Hash
6
+ end
7
+
8
+ class Message
9
+ attr_reader :parts
10
+ attr_reader :name
11
+
12
+ def initialize( element )
13
+ @parts = Hash.new
14
+ @name = element.attributes['name']
15
+
16
+ # Process all parts
17
+ element.find_all {|e| e.class == REXML::Element }.each { |part|
18
+ case part.name
19
+ when "part"
20
+ @parts[part.attributes['name']] = Hash.new
21
+
22
+ # Store part attributs
23
+ part.attributes.each { |name, value|
24
+ case name
25
+ when 'name'
26
+ @parts[part.attributes['name']][:name] = value
27
+ when 'element'
28
+ @parts[part.attributes['name']][:element] = value
29
+ @parts[part.attributes['name']][:mode] = :element
30
+ when 'type'
31
+ @parts[part.attributes['name']][:type] = value
32
+ @parts[part.attributes['name']][:mode] = :type
33
+ else
34
+ warn "Ignoring attribut `#{name}' in part `#{part.attributes['name']}' for message `#{element.attributes['name']}'"
35
+ end
36
+ }
37
+ else
38
+ warn "Ignoring element `#{part.name}' in message `#{element.attributes['name']}'"
39
+ end
40
+ }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,109 @@
1
+ require 'open-uri'
2
+ require 'rexml/document'
3
+
4
+ require 'soap/lc/error'
5
+ require 'soap/lc/wsdl/message'
6
+ require 'soap/lc/wsdl/portType'
7
+ require 'soap/lc/wsdl/binding'
8
+ require 'soap/lc/wsdl/service'
9
+ require 'soap/lc/xsd'
10
+
11
+ module SOAP
12
+ class WSDL
13
+ class Parser
14
+ attr_reader :types
15
+ attr_reader :messages
16
+ attr_reader :portTypes
17
+ attr_reader :bindings
18
+ attr_reader :services
19
+
20
+ attr_reader :prefixes
21
+ attr_reader :targetNamespace
22
+
23
+ attr_reader :document
24
+
25
+ def initialize( uri )
26
+ @types = SOAP::XSD.new()
27
+ @messages = SOAP::WSDL::Messages.new
28
+ @portTypes = SOAP::WSDL::PortTypes.new
29
+ @bindings = SOAP::WSDL::Bindings.new
30
+ @services = SOAP::WSDL::Services.new
31
+
32
+ @prefixes = Hash.new
33
+ @targetNamespace = ""
34
+
35
+ # Get WSDL
36
+ source = nil
37
+ begin
38
+ open( uri ) do |f|
39
+ source = f.read
40
+ end
41
+ rescue Errno::ECONNREFUSED, Errno::ENOENT, OpenURI::HTTPError => e
42
+ raise SOAP::LCError, "Can't open '#{uri}' : #{e.message}"
43
+ end
44
+
45
+ # Parse WSDL content
46
+ @document = REXML::Document.new( source )
47
+
48
+ processAttributes @document.root.attributes
49
+ processContent @document.root.children
50
+ end
51
+
52
+ private
53
+ def processAttributes( attributes )
54
+ @targetNamespace = attributes["targetNamespace"]
55
+ attributes.values.each{ |attribute|
56
+ if attribute.prefix == "xmlns" then
57
+ @prefixes[attribute.name] = attribute.value
58
+ end
59
+ }
60
+ if(default_namespace = attributes["xmlns"]) then
61
+ @prefixes["__default__"] = default_namespace
62
+ end
63
+ end
64
+
65
+ def processContent( elements )
66
+ elements.find_all {|e| e.class == REXML::Element }.each { |element|
67
+ case element.name
68
+ when "types"
69
+ processTypes( element )
70
+ when "message"
71
+ processMessage( element )
72
+ when "portType"
73
+ processPortType( element )
74
+ when "binding"
75
+ processBinding( element )
76
+ when "service"
77
+ processService( element )
78
+ else
79
+ warn "Ignoring #{element}"
80
+ end
81
+ }
82
+ end
83
+
84
+ def processTypes( element )
85
+ @types.add_schema( element )
86
+ end
87
+
88
+ def processMessage( element )
89
+ name = element.attributes['name']
90
+ @messages[name] = SOAP::WSDL::Message.new( element )
91
+ end
92
+
93
+ def processPortType( element )
94
+ name = element.attributes['name']
95
+ @portTypes[name] = SOAP::WSDL::PortType.new( element )
96
+ end
97
+
98
+ def processBinding( element )
99
+ name = element.attributes['name']
100
+ @bindings[name] = SOAP::WSDL::Binding.new( element )
101
+ end
102
+
103
+ def processService( element )
104
+ name = element.attributes['name']
105
+ @services[name] = SOAP::WSDL::Service.new( element )
106
+ end
107
+ end
108
+ end
109
+ end