mikisvaz-simplews 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt ADDED
@@ -0,0 +1,57 @@
1
+ == 1.3.2 2009-03-21
2
+
3
+ == 1.3.1 2008-12-20
4
+
5
+ * 1 minor enhancement:
6
+ * Use Marshal instead of YAML, it seems faster...
7
+
8
+ * 1 mayor enhancement:
9
+ * Removed old versions of job based servers
10
+
11
+ == 1.3.0 2008-12-20
12
+
13
+ * 1 minor enhancement:
14
+ * New version for asynchronous job. In this case it uses fork to spawn new
15
+ processes.
16
+
17
+
18
+
19
+ == 1.1.7 2008-11-27
20
+
21
+ * 2 minor enhancement:
22
+ * Inline methods are prepended '_inline_' to avoid polluting namespace
23
+ * Asynchronous jobs have a hash where they can save information, it is
24
+ accessible through the 'info' WS method in YAML format
25
+
26
+ == 1.1.6 2008-11-24
27
+
28
+ * 1 minor enhancement:
29
+ * Added documentation
30
+
31
+
32
+ == 1.1.5 2008-10-28
33
+
34
+ * 1 major enhancement:
35
+ * Jobs save their states across reboots of the server
36
+
37
+ == 1.1.4 2008-10-28
38
+
39
+ * 1 major enhancement:
40
+ * Web Service with asynchronous jobs
41
+
42
+ == 1.0.2 2008-10-28
43
+
44
+ * 1 bug fix:
45
+ * In using the easy client driver creation
46
+
47
+ == 1.0.1 2008-10-27
48
+
49
+ * 1 major enhancement:
50
+ * Easy creation of client driver. Connects to a url and retrieves the WSDL
51
+ and uses it to generate driver
52
+
53
+
54
+ == 1.0.0 2008-10-10
55
+
56
+ * 1 major enhancement:
57
+ * Initial release
data/Manifest.txt ADDED
@@ -0,0 +1,26 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ config/hoe.rb
7
+ config/requirements.rb
8
+ lib/simplews.rb
9
+ lib/simplews/jobs.rb
10
+ script/console
11
+ script/destroy
12
+ script/generate
13
+ script/txt2html
14
+ setup.rb
15
+ simplews.gemspec
16
+ tasks/deployment.rake
17
+ tasks/environment.rake
18
+ tasks/website.rake
19
+ test/simplews/test_jobs.rb
20
+ test/test_helper.rb
21
+ test/test_simplews.rb
22
+ website/index.html
23
+ website/index.txt
24
+ website/javascripts/rounded_corners_lite.inc.js
25
+ website/stylesheets/screen.css
26
+ website/template.html.erb
data/PostInstall.txt ADDED
@@ -0,0 +1,7 @@
1
+
2
+ For more information on simplews, see http://simplews.rubyforge.org
3
+
4
+ NOTE: Change this information in PostInstall.txt
5
+ You can also delete it if you don't want it.
6
+
7
+
data/README.rdoc ADDED
@@ -0,0 +1,92 @@
1
+ = simpleWS
2
+
3
+ == DESCRIPTION:
4
+
5
+ This defines a class that can simplifies creating Web Services. It inherits from soap2r's
6
+ SOAP::RPC::StandaloneServer and provides a few enhancements, the most important the fact that
7
+ it is able to produce the WSDL automatically.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+
12
+ == SYNOPSIS:
13
+
14
+ Each Web Service provided is described using the method 'serve', which takes
15
+ as arguments the name of the service, the name of its arguments, the type of
16
+ its arguments and an optional block of code. If a block of code is provided,
17
+ it will be the one executed when the service is called, if not, a function
18
+ with the same name will be used. The types for the arguments are listed here,
19
+ along with the WSDL type that it is translated to:
20
+
21
+ :string => 'xsd:string',
22
+ :integer => 'xsd:integer',
23
+ :array => 'tns:ArrayOfString',
24
+ :hash => 'tns:Map',
25
+ :binary => 'xsd:base64Binary',
26
+
27
+ The type of the result value may also be specified using the name :return,
28
+ this means no argument may be called :return. If it is not specified there
29
+ will be no return value.
30
+
31
+ Following is an example of use:
32
+
33
+ class TestWS < SimpleWS
34
+ def hi(name)
35
+ "Hi #{name}, how are you?"
36
+ end
37
+
38
+ def initialize(*args)
39
+ super(*args)
40
+ serve :hi, %(name), :name => :string, :return => :string
41
+
42
+ serve :bye, %(name), :name => :string, :return => :string do |name
43
+ "Bye bye #{name}. See you soon."
44
+ end
45
+ end
46
+ end
47
+
48
+ The constructor accepts a number of parameters. The name of the server, a
49
+ description, the host and the port, along with any other arguments one wishes
50
+ to pass to the SOAP::RPC::StandaloneServer constructor
51
+
52
+ This is an example of instantiating the above server:
53
+
54
+ server = TestWS.new("TestWS", "Greeting Services", 'localhost', '1984')
55
+ server.wsdl("TestWS.wsdl")
56
+
57
+ The function 'wsdl' saves the WSDL describing the services and the location
58
+ provided as an argument.
59
+
60
+
61
+ == REQUIREMENTS:
62
+
63
+ Requires soap4r gem to be installed.
64
+
65
+ == INSTALL:
66
+
67
+ sudo gem install simpleWS
68
+
69
+ == LICENSE:
70
+
71
+ (The MIT License)
72
+
73
+ Copyright (c) 2008 Miguel Vazquez (miguel.vazquez@fdi.ucm.es)
74
+
75
+ Permission is hereby granted, free of charge, to any person obtaining
76
+ a copy of this software and associated documentation files (the
77
+ 'Software'), to deal in the Software without restriction, including
78
+ without limitation the rights to use, copy, modify, merge, publish,
79
+ distribute, sublicense, and/or sell copies of the Software, and to
80
+ permit persons to whom the Software is furnished to do so, subject to
81
+ the following conditions:
82
+
83
+ The above copyright notice and this permission notice shall be
84
+ included in all copies or substantial portions of the Software.
85
+
86
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
87
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
88
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
89
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
90
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
91
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
92
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/simplews'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.new('simplews', SimpleWS::VERSION) do |p|
7
+ p.developer('Miguel Vazquez', 'mikisvaz@yahoo.com')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
10
+ p.rubyforge_name = p.name # TODO this is default value
11
+ # p.extra_deps = [
12
+ # ['activesupport','>= 2.0.2'],
13
+ # ]
14
+ p.extra_dev_deps = [
15
+ ['newgem', ">= #{::Newgem::VERSION}"]
16
+ ]
17
+
18
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
19
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
20
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
21
+ p.rsync_args = '-av --delete --ignore-errors'
22
+ end
23
+
24
+ require 'newgem/tasks' # load /tasks/*.rake
25
+ Dir['tasks/**/*.rake'].each { |t| load t }
26
+
27
+ # TODO - want other tests/tasks run by default? Add them to the list
28
+ # task :default => [:spec, :features]
data/config/hoe.rb ADDED
@@ -0,0 +1,73 @@
1
+ require 'simplews/version'
2
+
3
+ AUTHOR = 'Miguel Vazquez' # can also be an array of Authors
4
+ EMAIL = "miguel.vazquez@fdi.ucm.es"
5
+ DESCRIPTION = "Simplifies the development of Web Services, producing WSDL automatically for example. Wraps soap4r."
6
+ GEM_NAME = 'simplews' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'simplews' # The unix name for your project
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+ EXTRA_DEPENDENCIES = [
11
+ # ['activesupport', '>= 1.3.1']
12
+ ] # An array of rubygem dependencies [name, version]
13
+
14
+ @config_file = "~/.rubyforge/user-config.yml"
15
+ @config = nil
16
+ RUBYFORGE_USERNAME = "unknown"
17
+ def rubyforge_username
18
+ unless @config
19
+ begin
20
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
21
+ rescue
22
+ puts <<-EOS
23
+ ERROR: No rubyforge config file found: #{@config_file}
24
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
25
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
26
+ EOS
27
+ exit
28
+ end
29
+ end
30
+ RUBYFORGE_USERNAME.replace @config["username"]
31
+ end
32
+
33
+
34
+ REV = nil
35
+ # UNCOMMENT IF REQUIRED:
36
+ # REV = YAML.load(`svn info`)['Revision']
37
+ VERS = Simplews::VERSION::STRING + (REV ? ".#{REV}" : "")
38
+ RDOC_OPTS = ['--quiet', '--title', 'simplews documentation',
39
+ "--opname", "index.html",
40
+ "--line-numbers",
41
+ "--main", "README",
42
+ "--inline-source"]
43
+
44
+ class Hoe
45
+ def extra_deps
46
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
47
+ @extra_deps
48
+ end
49
+ end
50
+
51
+ # Generate all the Rake tasks
52
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
53
+ $hoe = Hoe.new(GEM_NAME, VERS) do |p|
54
+ p.developer(AUTHOR, EMAIL)
55
+ p.description = DESCRIPTION
56
+ p.summary = DESCRIPTION
57
+ p.url = HOMEPATH
58
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
59
+ p.test_globs = ["test/**/test_*.rb"]
60
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
61
+
62
+ # == Optional
63
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
64
+ #p.extra_deps = EXTRA_DEPENDENCIES
65
+
66
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
67
+ end
68
+
69
+ CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
70
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
71
+ $hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
72
+ $hoe.rsync_args = '-av --delete --ignore-errors'
73
+ $hoe.spec.post_install_message = File.open(File.dirname(__FILE__) + "/../PostInstall.txt").read rescue ""
@@ -0,0 +1,15 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
data/lib/simplews.rb ADDED
@@ -0,0 +1,258 @@
1
+ require 'soap/rpc/standaloneServer'
2
+ require 'builder'
3
+
4
+
5
+ # SimpleWS is a class that wraps SOAP::RPC::StandaloneServer to ease the
6
+ # implementation of Web Services, specifically the generation of the
7
+ # +WSDL+ file. It provides a particular syntax that allows to specify
8
+ # the methods that are going to be served along with the types of the
9
+ # parameters and of the response so that the +WSDL+ can be generated
10
+ # accordingly. Actual Servers can be instances of this class where
11
+ # methods are assigned dynamically or of classes that extend SimpleWS.
12
+ # class TestWS < SimpleWS
13
+ # def hi(name)
14
+ # "Hi #{name}, how are you?"
15
+ # end
16
+ #
17
+ # def initialize(*args)
18
+ # super(*args)
19
+ # serve :hi, %w(name), :name => :string, :return => :string
20
+ #
21
+ # serve :bye, %w(name), :name => :string, :return => :string do |name|
22
+ # "Bye bye #{name}. See you soon."
23
+ # end
24
+ #
25
+ # end
26
+ # end
27
+ #
28
+ # # Creating a server and starting it
29
+ #
30
+ # server = TestWS.new("TestWS", "Greeting Services", 'localhost', '1984')
31
+ # server.wsdl("TestWS.wsdl")
32
+ #
33
+ # Thread.new do
34
+ # server.start
35
+ # end
36
+ #
37
+ # # Client code. This could be run in another process.
38
+ #
39
+ # driver = SimpleWS::get_driver('http://localhost:1984', "TestWS")
40
+ # puts driver.hi('Gladis') #=> "Hi Gladis, how are you?"
41
+ # puts driver.bye('Gladis') #=> "Bye bye Gladis. See you soon."
42
+ #
43
+
44
+
45
+
46
+ class SimpleWS < SOAP::RPC::StandaloneServer
47
+ VERSION = "1.3.2"
48
+
49
+
50
+ # This is a helper function for clients. Given the +url+ where the
51
+ # server is listening, as well as the name of the server, it can
52
+ # manually access the +wsdl+ function and retrieve the complete +WSDL+
53
+ # file. This works *only* in web servers of class SimpleWS, not on
54
+ # the general SOAP::RPC::StandaloneServer or any other type of web
55
+ # server.
56
+ def self.get_wsdl(url, name)
57
+ require 'soap/rpc/driver'
58
+ driver = SOAP::RPC::Driver.new(url, "urn:#{ name }")
59
+ driver.add_method('wsdl')
60
+ driver.wsdl
61
+ end
62
+
63
+ # Builds on the get_wsdl function to provide the client with a
64
+ # reference to the driver. Again, only works with SimpleWS servers.
65
+ def self.get_driver(url, name)
66
+ require 'soap/wsdlDriver'
67
+ require 'fileutils'
68
+
69
+ tmp = File.open("/tmp/simpleWS.wsdl",'w')
70
+ tmp.write SimpleWS::get_wsdl(url, name)
71
+ tmp.close
72
+ driver = SOAP::WSDLDriverFactory.new( "/tmp/simpleWS.wsdl" ).create_rpc_driver
73
+ FileUtils.rm "/tmp/simpleWS.wsdl"
74
+
75
+ driver
76
+ end
77
+
78
+ # Creates an instance of a Server. The parameter +name+ specifies the
79
+ # +namespace+ used in the +WSDL+, +description+ is the description
80
+ # also included in the +WSDL+. The parameters +host+ and +port+,
81
+ # specify where the server will be listening, they are parameters of
82
+ # the +super+ class SOAP::RPC::StandaloneServer, they are made
83
+ # explicit here because they are included in the +WSDL+ as well.
84
+ def initialize(name="WS", description="", host="localhost", port="1984", *args)
85
+ super(description, "urn:#{ name }", host, port, *args)
86
+ @host = host
87
+ @port = port
88
+ @name = name
89
+ @description = description
90
+ @messages = []
91
+ @operations = []
92
+ @bindings = []
93
+
94
+ serve :wsdl, %w(), :return => :string
95
+ end
96
+
97
+
98
+ # This method tells the server to provide a method named by the +name+
99
+ # parameter, with arguments listed in the +args+ parameter. The
100
+ # +types+ parameter specifies the types of the arguments as will be
101
+ # described in the +WSDL+ file (see the TYPES2WSDL constant). The
102
+ # actual method called will be the one with the same name. Optionally
103
+ # a block can be provided, this block will be used to define a
104
+ # function named as in name.
105
+ #
106
+ # If the method returns something, then the type of the return value
107
+ # must be specified in the +types+ parameter as :return. If not value
108
+ # for :return parameter is specified in the +types+ parameter the
109
+ # method is taken to return no value. Other than that, if a parameter
110
+ # type is omitted it is taken to be :string.
111
+ def serve(name, args=[], types={}, &block)
112
+
113
+ if block
114
+ inline_name = "_inline_" + name.to_s
115
+ add_to_ruby(inline_name, &block)
116
+ add_method_as(self,inline_name, name.to_s,*args)
117
+ else
118
+ add_method(self,name.to_s,*args)
119
+ end
120
+
121
+ add_to_wsdl(name, args, types)
122
+
123
+ nil
124
+ end
125
+
126
+ # If +filename+ is specified it saves the +WSDL+ file in that file. If
127
+ # no +filename+ is specified it returns a string containing the
128
+ # +WSDL+. The no parameter version is served by default, so that
129
+ # clients can use this method to access the complete +WSDL+ file, as
130
+ # used in get_wsdl and get_driver.
131
+ def wsdl(filename = nil)
132
+ wsdl = WSDL_STUB.dup
133
+ wsdl.gsub!(/\$\{MESSAGES\}/m,@messages.join("\n"))
134
+ wsdl.gsub!(/\$\{OPERATIONS\}/m,@operations.join("\n"))
135
+ wsdl.gsub!(/\$\{BINDINGS\}/m,@bindings.join("\n"))
136
+ wsdl.gsub!(/\$\{NAME\}/,@name)
137
+ wsdl.gsub!(/\$\{DESCRIPTION\}/,@description)
138
+ wsdl.gsub!(/\$\{LOCATION\}/,"http://#{ @host }:#{ @port }")
139
+ if filename
140
+ fwsdl = File.open(filename,'w')
141
+ fwsdl.write(wsdl)
142
+ fwsdl.close
143
+ nil
144
+ else
145
+ wsdl
146
+ end
147
+ end
148
+
149
+ private
150
+
151
+ def add_to_ruby(name, &block)
152
+ self.class.send(:define_method, name, block)
153
+ end
154
+
155
+ def add_to_wsdl(name, args, types)
156
+ message = Builder::XmlMarkup.new(:indent => 2).message :name => "#{ name }Request" do |xml|
157
+ args.each{|param|
158
+ type = types[param.to_s] || types[param.to_sym] || :string
159
+ type = type.to_sym
160
+ xml.part :name => param, :type => TYPES2WSDL[type]
161
+ }
162
+ end
163
+ @messages << message
164
+ message = Builder::XmlMarkup.new(:indent => 2).message :name => "#{ name }Response" do |xml|
165
+ type = types[:return] || types["return"]
166
+ if type
167
+ type = type.to_sym
168
+ xml.part :name => 'return', :type => TYPES2WSDL[type]
169
+ end
170
+ end
171
+ @messages << message
172
+
173
+ operation = Builder::XmlMarkup.new(:indent => 2).operation :name => "#{ name }" do |xml|
174
+ xml.input :message => "tns:#{ name }Request"
175
+ xml.output :message => "tns:#{ name }Response"
176
+ end
177
+
178
+ @operations << operation
179
+
180
+ binding = Builder::XmlMarkup.new(:indent => 2).operation :name => "#{ name }" do |xml|
181
+ xml.tag! 'soap:operation'.to_sym, :soapAction => "urn:${NAME}##{name}", :style => 'rpc'
182
+ xml.input do |xml|
183
+ xml.tag! 'soap:body'.to_sym, :namespace => "urn:${NAME}", :encodingStyle => "http://schemas.xmlsoap.org/soap/encoding/", :use => "encoded"
184
+ end
185
+ xml.output do |xml|
186
+ xml.tag! 'soap:body'.to_sym, :namespace => "urn:${NAME}", :encodingStyle => "http://schemas.xmlsoap.org/soap/encoding/", :use => "encoded"
187
+ end
188
+ end
189
+
190
+ @bindings << binding
191
+
192
+ end
193
+
194
+
195
+ WSDL_STUB =<<EOT
196
+ <?xml version="1.0"?>
197
+ <definitions xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
198
+ xmlns:tns="${NAME}-NS"
199
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
200
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
201
+ xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
202
+ xmlns:si="http://soapinterop.org/xsd"
203
+ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
204
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
205
+ xmlns="http://schemas.xmlsoap.org/wsdl/"
206
+ targetNamespace="${NAME}-NS">
207
+
208
+
209
+ <types>
210
+ <schema xmlns="http://www.w3.org/2001/XMLSchema"
211
+ targetNamespace="${NAME}-NS"
212
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
213
+ xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
214
+ <complexType name="ArrayOfString">
215
+ <complexContent>
216
+ <restriction base="soapenc:Array">
217
+ <attribute ref="soapenc:arrayType"
218
+ wsdl:arrayType="string[]"/>
219
+ </restriction>
220
+ </complexContent>
221
+ </complexType>
222
+ </schema>
223
+ </types>
224
+
225
+ ${MESSAGES}
226
+ <portType name="${NAME}">
227
+ ${OPERATIONS}
228
+ </portType>
229
+
230
+ <binding name="${NAME}Binding" type="tns:${NAME}">
231
+ <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
232
+ ${BINDINGS}
233
+ </binding>
234
+ <service name="${NAME}">
235
+ <documentation>${DESCRIPTION}</documentation>
236
+
237
+ <port name="${NAME}" binding="tns:${NAME}Binding">
238
+ <soap:address location="${LOCATION}"/>
239
+ </port>
240
+ </service>
241
+
242
+ </definitions>
243
+ EOT
244
+
245
+ TYPES2WSDL = {
246
+ :boolean => 'xsd:boolean',
247
+ :string => 'xsd:string',
248
+ :integer => 'xsd:integer',
249
+ :float => 'xsd:float',
250
+ :array => 'tns:ArrayOfString',
251
+ :hash => 'tns:Map',
252
+ :binary => 'xsd:base64Binary',
253
+ }
254
+
255
+
256
+ end
257
+
258
+