wrest 0.0.5-java

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.
Files changed (45) hide show
  1. data/README.rdoc +101 -0
  2. data/Rakefile +243 -0
  3. data/VERSION.yml +4 -0
  4. data/bin/jwrest +3 -0
  5. data/bin/wrest +3 -0
  6. data/bin/wrest_shell.rb +21 -0
  7. data/lib/wrest.rb +41 -0
  8. data/lib/wrest/components.rb +19 -0
  9. data/lib/wrest/components/attributes_container.rb +123 -0
  10. data/lib/wrest/components/mutators.rb +21 -0
  11. data/lib/wrest/components/mutators/base.rb +27 -0
  12. data/lib/wrest/components/mutators/xml_simple_type_caster.rb +31 -0
  13. data/lib/wrest/core_ext/hash.rb +5 -0
  14. data/lib/wrest/core_ext/hash/conversions.rb +25 -0
  15. data/lib/wrest/core_ext/string.rb +5 -0
  16. data/lib/wrest/core_ext/string/conversions.rb +23 -0
  17. data/lib/wrest/exceptions.rb +1 -0
  18. data/lib/wrest/exceptions/unsupported_content_type_exception.rb +15 -0
  19. data/lib/wrest/resource.rb +18 -0
  20. data/lib/wrest/resource/base.rb +69 -0
  21. data/lib/wrest/resource/collection.rb +12 -0
  22. data/lib/wrest/response.rb +38 -0
  23. data/lib/wrest/translators.rb +25 -0
  24. data/lib/wrest/translators/content_types.rb +20 -0
  25. data/lib/wrest/translators/json.rb +21 -0
  26. data/lib/wrest/translators/xml.rb +24 -0
  27. data/lib/wrest/uri.rb +74 -0
  28. data/lib/wrest/uri_template.rb +32 -0
  29. data/lib/wrest/version.rb +22 -0
  30. data/spec/custom_matchers/custom_matchers.rb +2 -0
  31. data/spec/rcov.opts +4 -0
  32. data/spec/spec.opts +6 -0
  33. data/spec/spec_helper.rb +18 -0
  34. data/spec/wrest/components/attributes_container_spec.rb +184 -0
  35. data/spec/wrest/components/mutators/base_spec.rb +18 -0
  36. data/spec/wrest/components/mutators/xml_simple_type_caster_spec.rb +41 -0
  37. data/spec/wrest/core_ext/hash/conversions_spec.rb +22 -0
  38. data/spec/wrest/core_ext/string/conversions_spec.rb +16 -0
  39. data/spec/wrest/resource/base_spec.rb +158 -0
  40. data/spec/wrest/response_spec.rb +21 -0
  41. data/spec/wrest/translators/xml_spec.rb +12 -0
  42. data/spec/wrest/translators_spec.rb +9 -0
  43. data/spec/wrest/uri_spec.rb +131 -0
  44. data/spec/wrest/uri_template_spec.rb +28 -0
  45. metadata +139 -0
@@ -0,0 +1,20 @@
1
+ # Copyright 2009 Sidu Ponnappa
2
+
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ # Unless required by applicable law or agreed to in writing, software distributed under the License
7
+ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8
+ # See the License for the specific language governing permissions and limitations under the License.
9
+
10
+ module Wrest
11
+ module Translators
12
+ # Maps content types to deserialisers
13
+ CONTENT_TYPES = {
14
+ 'application/xml' => Wrest::Translators::Xml,
15
+ 'text/xml' => Wrest::Translators::Xml,
16
+ 'application/json' => Wrest::Translators::Json,
17
+ 'text/javascript' => Wrest::Translators::Json
18
+ }
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ # Copyright 2009 Sidu Ponnappa
2
+
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ # Unless required by applicable law or agreed to in writing, software distributed under the License
7
+ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8
+ # See the License for the specific language governing permissions and limitations under the License.
9
+
10
+ require 'json'
11
+
12
+ module Wrest
13
+ module Translators
14
+ # Knows how to deserialise json.
15
+ # Depends on the json gem.
16
+ Json = lambda{|response|
17
+ JSON.parse(response.body)
18
+ }
19
+ end
20
+ end
21
+
@@ -0,0 +1,24 @@
1
+ # Copyright 2009 Sidu Ponnappa
2
+
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ # Unless required by applicable law or agreed to in writing, software distributed under the License
7
+ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8
+ # See the License for the specific language governing permissions and limitations under the License.
9
+
10
+ require 'xmlsimple'
11
+
12
+ module Wrest
13
+ module Translators
14
+ # Knows how to deserialise xml.
15
+ # Depends on the xmlsimple gem.
16
+ Xml = lambda{|response|
17
+ XmlSimple.xml_in(
18
+ response.body,
19
+ 'keeproot' => true
20
+ )
21
+ }
22
+ end
23
+ end
24
+
data/lib/wrest/uri.rb ADDED
@@ -0,0 +1,74 @@
1
+ # Copyright 2009 Sidu Ponnappa
2
+
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ # Unless required by applicable law or agreed to in writing, software distributed under the License
7
+ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8
+ # See the License for the specific language governing permissions and limitations under the License.
9
+
10
+ module Wrest #:nodoc:
11
+ # Wrest::Uri provides a simple api for
12
+ # REST calls. String#to_uri is a convenience
13
+ # method to build a Wrest::Uri from a string url.
14
+ class Uri
15
+ attr_reader :uri
16
+ def initialize(uri_string)
17
+ @uri = URI.parse(uri_string)
18
+ end
19
+
20
+ def eql?(other)
21
+ self == other
22
+ end
23
+
24
+ def ==(other)
25
+ return false if other.class != self.class
26
+ return other.uri == self.uri
27
+ end
28
+
29
+ def hash
30
+ self.uri.hash + self.class.object_id
31
+ end
32
+
33
+ # Make a HTTP get request to this URI.
34
+ # Remember to escape the parameter strings using URI.escape
35
+ def get(parameters = {}, headers = {})
36
+ do_request 'get', parameters.empty? ? @uri.request_uri : "#{@uri.request_uri}?#{parameters.to_query}", headers.stringify_keys
37
+ end
38
+
39
+ def put(body = '', headers = {})
40
+ do_request 'put', @uri.request_uri, body.to_s, headers.stringify_keys
41
+ end
42
+
43
+ def post(body = '', headers = {})
44
+ do_request 'post', @uri.request_uri, body.to_s, headers.stringify_keys
45
+ end
46
+
47
+ def delete(headers = {})
48
+ do_request 'delete', @uri.request_uri, headers.stringify_keys
49
+ end
50
+
51
+ def do_request(method, url, *args)
52
+ response = nil
53
+
54
+ Wrest.logger.info "#{method} -> #{url}"
55
+ time = Benchmark.realtime { response = Wrest::Response.new(http.send(method, url, *args)) }
56
+ Wrest.logger.info "--> %d %s (%d %.2fs)" % [response.code, response.message, response.body ? response.body.length : 0, time]
57
+
58
+ response
59
+ end
60
+
61
+ def https?
62
+ @uri.is_a?(URI::HTTPS)
63
+ end
64
+
65
+ def http
66
+ http = Net::HTTP.new(@uri.host, @uri.port)
67
+ if https?
68
+ http.use_ssl = true
69
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
70
+ end
71
+ http
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,32 @@
1
+ # Copyright 2009 Sidu Ponnappa
2
+
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ # Unless required by applicable law or agreed to in writing, software distributed under the License
7
+ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8
+ # See the License for the specific language governing permissions and limitations under the License.
9
+
10
+ module Wrest
11
+ class UriTemplate
12
+ attr_reader :uri_pattern
13
+ def initialize(uri_pattern)
14
+ @uri_pattern = uri_pattern.clone
15
+ end
16
+
17
+ # Builds a new Wrest::Uri from this uri template
18
+ # by replacing the keys in the options that match with
19
+ # the corressponding values.
20
+ #
21
+ # Example:
22
+ # template = UriTemplate.new("http://localhost:3000/:resource/:id.:format")
23
+ # template.to_uri(:resource => 'shen_coins', :id => 5, :format => :json)
24
+ # => #<Wrest::Uri:0x1225514 @uri=#<URI::HTTP:0x9127d8 URL:http://localhost:3000/shen_coins/5.json>>
25
+ def to_uri(options = {})
26
+ options.inject(uri_pattern.clone) do |uri_string, tuple|
27
+ key, value = tuple
28
+ uri_string.gsub(":#{key.to_s}", value.to_s)
29
+ end.to_uri
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ # Copyright 2009 Sidu Ponnappa
2
+
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ # Unless required by applicable law or agreed to in writing, software distributed under the License
7
+ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8
+ # See the License for the specific language governing permissions and limitations under the License.
9
+
10
+ module Wrest
11
+ module VERSION
12
+ unless defined? MAJOR
13
+ MAJOR = 0
14
+ MINOR = 0
15
+ TINY = 5
16
+
17
+ STRING = [MAJOR, MINOR, TINY].join('.')
18
+
19
+ SUMMARY = "wrest version #{STRING}"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,2 @@
1
+ module CustomMatchers
2
+ end
data/spec/rcov.opts ADDED
@@ -0,0 +1,4 @@
1
+ --text-report
2
+ --html
3
+ --exclude-only ^\/usr,^\/Library,^\/System,spec\/
4
+ --output coverage
data/spec/spec.opts ADDED
@@ -0,0 +1,6 @@
1
+ --colour
2
+ --format
3
+ progress
4
+ --loadby
5
+ mtime
6
+ --reverse
@@ -0,0 +1,18 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/wrest")
2
+ require 'spec'
3
+
4
+ ["/custom_matchers/**/*.rb"].each{|directory|
5
+ Dir["#{File.expand_path(File.dirname(__FILE__) + directory)}"].each { |file|
6
+ require file
7
+ }
8
+ }
9
+
10
+ Wrest.logger = Logger.new(File.open("#{WREST_ROOT}/../log/test.log", 'a'))
11
+
12
+ def p(*args)
13
+ super *(args << caller[0])
14
+ end
15
+
16
+ Spec::Runner.configure do |config|
17
+ config.include(CustomMatchers)
18
+ end
@@ -0,0 +1,184 @@
1
+ # Copyright 2009 Sidu Ponnappa
2
+
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ # Unless required by applicable law or agreed to in writing, software distributed under the License
7
+ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8
+ # See the License for the specific language governing permissions and limitations under the License.
9
+
10
+ require File.dirname(__FILE__) + '/../../spec_helper'
11
+
12
+ module Wrest::Components
13
+ describe AttributesContainer do
14
+ class HumanBeing
15
+ include AttributesContainer
16
+ has_attributes :id
17
+ end
18
+
19
+ it "should allow instantiation with no attributes" do
20
+ lambda{ HumanBeing.new }.should_not raise_error
21
+ end
22
+
23
+ describe 'has_attributes' do
24
+ describe 'method creation' do
25
+ before :each do
26
+ @Demon = Class.new
27
+ end
28
+
29
+ it "should define attribute getters at the class level" do
30
+ kai_wren = @Demon.new
31
+ kai_wren.methods.should_not include('trainer')
32
+
33
+ @Demon.class_eval{
34
+ include AttributesContainer
35
+ has_attributes :trainer
36
+ }
37
+
38
+ kai_wren.methods.should include('trainer')
39
+ end
40
+
41
+ it "should define attribute setters at the class level" do
42
+ kai_wren = @Demon.new
43
+ kai_wren.methods.should_not include('trainer=')
44
+
45
+ @Demon.class_eval{
46
+ include AttributesContainer
47
+ has_attributes :trainer
48
+ }
49
+
50
+ kai_wren.methods.should include('trainer=')
51
+ end
52
+
53
+ it "should define attribute query methods at the class level" do
54
+ kai_wren = @Demon.new
55
+ kai_wren.methods.should_not include('trainer?')
56
+
57
+ @Demon.class_eval{
58
+ include AttributesContainer
59
+ has_attributes :trainer
60
+ }
61
+ kai_wren.methods.should include('trainer?')
62
+ end
63
+ end
64
+
65
+ describe 'method functionality' do
66
+ before :each do
67
+ @Demon = Class.new
68
+ @Demon.class_eval{
69
+ include AttributesContainer
70
+ has_attributes :trainer
71
+
72
+ def method_missing(method_name, *args)
73
+ # Ensuring that the instance level
74
+ # attribute methods don't kick in
75
+ # by overriding method_missing
76
+ raise NoMethodError.new("Method #{method_name} was invoked, but doesn't exist", method_name)
77
+ end
78
+ }
79
+ @kai_wren = @Demon.new
80
+ end
81
+
82
+ it "should define attribute getters at the class level" do
83
+ @kai_wren.instance_variable_get("@attributes")[:trainer] = 'Viss'
84
+ @kai_wren.trainer.should == 'Viss'
85
+ end
86
+
87
+ it "should define attribute setters at the class level" do
88
+ @kai_wren.trainer = 'Viss'
89
+ @kai_wren.instance_variable_get("@attributes")[:trainer].should == 'Viss'
90
+ end
91
+
92
+ it "should define attribute query methods at the class level" do
93
+ @kai_wren.trainer?.should be_false
94
+ @kai_wren.instance_variable_get("@attributes")[:trainer] = 'Viss'
95
+ @kai_wren.trainer?.should be_true
96
+ end
97
+ end
98
+ end
99
+
100
+ describe 'provides an attributes interface which' do
101
+ before :each do
102
+ @li_piao = HumanBeing.new(:id => 5, :profession => 'Natural Magician', 'enhanced_by' => 'Kai Wren')
103
+ end
104
+
105
+ it "should provide a generic key based getter that requires symbols" do
106
+ @li_piao[:profession].should == "Natural Magician"
107
+ @li_piao['profession'].should == "Natural Magician"
108
+ end
109
+
110
+ it "should provide a generic key based getter that understands symbols" do
111
+ @li_piao[:enhanced_by] = "Viss"
112
+ @li_piao.instance_variable_get('@attributes')[:enhanced_by].should == "Viss"
113
+ end
114
+
115
+ it "should provide a generic key based getter that translates strings to symbols" do
116
+ @li_piao['enhanced_by'] = "Viss"
117
+ @li_piao.instance_variable_get('@attributes')[:enhanced_by].should == "Viss"
118
+ end
119
+
120
+ it "should fail when getter methods for attributes that don't exist are invoked" do
121
+ lambda{ @li_piao.ooga }.should raise_error(NoMethodError)
122
+ end
123
+
124
+ it "should provide getter methods for attributes" do
125
+ @li_piao.profession.should == 'Natural Magician'
126
+ @li_piao.enhanced_by.should == 'Kai Wren'
127
+ end
128
+
129
+ it "should respond to getter methods for attributes" do
130
+ @li_piao.should respond_to(:profession)
131
+ @li_piao.should respond_to(:enhanced_by)
132
+ end
133
+
134
+ it "should not respond to getter methods for attributes that don't exist" do
135
+ @li_piao.should_not respond_to(:gods)
136
+ end
137
+
138
+ it "should create a setter method when one is invoked for attributes that don't exist" do
139
+ @li_piao.niece = 'Li Plum'
140
+ @li_piao.instance_variable_get('@attributes')[:niece].should == 'Li Plum'
141
+ @li_piao.niece.should == 'Li Plum'
142
+ end
143
+
144
+ it "should provide setter methods for attributes" do
145
+ @li_piao.enhanced_by = 'He of the Towers of Light'
146
+ @li_piao.instance_variable_get('@attributes')[:enhanced_by].should == 'He of the Towers of Light'
147
+ end
148
+
149
+ it "should respond to setter methods for attributes" do
150
+ @li_piao.should respond_to(:profession=)
151
+ @li_piao.should respond_to(:enhanced_by=)
152
+ end
153
+
154
+ it "should not respond to setter methods for attributes that don't exist" do
155
+ @li_piao.should_not respond_to(:god=)
156
+ end
157
+
158
+ it "should fail when query methods for attributes that don't exist are invoked" do
159
+ lambda{ @li_piao.ooga? }.should raise_error(NoMethodError)
160
+ end
161
+
162
+ it "should provide query methods for attributes" do
163
+ li_piao = HumanBeing.new( :profession => 'Natural Magician', :enhanced_by => nil)
164
+ li_piao.profession?.should be_true
165
+ li_piao.enhanced_by?.should be_false
166
+ end
167
+
168
+ it "should respond to query methods for attributes" do
169
+ @li_piao.should respond_to(:profession?)
170
+ @li_piao.should respond_to(:enhanced_by?)
171
+ end
172
+
173
+ it "should not respond to query methods for attributes that don't exist" do
174
+ @li_piao.should_not respond_to(:theronic?)
175
+ end
176
+
177
+ it "should override methods which already exist on the container" do
178
+ @li_piao.id.should == 5
179
+ @li_piao.id = 6
180
+ @li_piao.id.should == 6
181
+ end
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,18 @@
1
+ # Copyright 2009 Sidu Ponnappa
2
+
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ # Unless required by applicable law or agreed to in writing, software distributed under the License
7
+ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8
+ # See the License for the specific language governing permissions and limitations under the License.
9
+
10
+ require File.dirname(__FILE__) + '/../../../spec_helper'
11
+
12
+ module Wrest::Components
13
+ describe Mutators::Base do
14
+ it "should return a tuple unchanged" do
15
+ Mutators::Base.new.mutate([:ooga, :booga]).should == [:ooga, :booga]
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,41 @@
1
+ # Copyright 2009 Sidu Ponnappa
2
+
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ # Unless required by applicable law or agreed to in writing, software distributed under the License
7
+ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8
+ # See the License for the specific language governing permissions and limitations under the License.
9
+
10
+ require File.dirname(__FILE__) + '/../../../spec_helper'
11
+
12
+ module Wrest::Components
13
+ describe Mutators::XmlSimpleTypeCaster do
14
+ before(:each) do
15
+ @mutator = Mutators::XmlSimpleTypeCaster.new
16
+ end
17
+
18
+ # {"lead-bottle"=>[{"name"=>["Wooz"], "universe-id"=>[{"type"=>"integer", "nil"=>"true"}], "id"=>[{"type"=>"integer", "content"=>"1"}]}]}
19
+ it "should underscore the key in a tuple" do
20
+ @mutator.mutate(["universe-id", ["1"]]).should == ["universe_id", "1"]
21
+ end
22
+
23
+ it "should typecast a nil value in a tuple" do
24
+ @mutator.mutate(
25
+ ["universe-id", [{"type"=>"integer", "nil"=>"true"}]]
26
+ ).should == ["universe_id", nil]
27
+ end
28
+
29
+ it "should leave a string value in a tuple unchanged" do
30
+ @mutator.mutate(
31
+ ["name", ["Wooz"]]
32
+ ).should == ["name", "Wooz"]
33
+ end
34
+
35
+ it "should cast an integer value in a tuple" do
36
+ @mutator.mutate(
37
+ ["id", [{"type"=>"integer", "content"=>"1"}]]
38
+ ).should == ["id", 1]
39
+ end
40
+ end
41
+ end