wrest 0.0.5-java

Sign up to get free protection for your applications and to get access to all the features.
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