restfulie 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/README.textile +83 -7
  2. data/Rakefile +98 -13
  3. data/lib/restfulie/client/base.rb +48 -53
  4. data/lib/restfulie/client/configuration.rb +69 -0
  5. data/lib/restfulie/client/http/adapter.rb +487 -0
  6. data/lib/restfulie/client/http/atom_ext.rb +87 -0
  7. data/lib/restfulie/client/http/cache.rb +28 -0
  8. data/lib/restfulie/client/http/error.rb +80 -0
  9. data/lib/restfulie/client/http/marshal.rb +147 -0
  10. data/lib/restfulie/client/http.rb +13 -0
  11. data/lib/restfulie/client.rb +8 -56
  12. data/lib/restfulie/common/builder/builder_base.rb +58 -0
  13. data/lib/restfulie/common/builder/helpers.rb +22 -0
  14. data/lib/restfulie/common/builder/marshalling/atom.rb +197 -0
  15. data/lib/restfulie/common/builder/marshalling/base.rb +12 -0
  16. data/lib/restfulie/common/builder/marshalling/json.rb +2 -0
  17. data/lib/restfulie/common/builder/marshalling.rb +16 -0
  18. data/lib/restfulie/common/builder/rules/collection_rule.rb +10 -0
  19. data/lib/restfulie/common/builder/rules/link.rb +20 -0
  20. data/lib/restfulie/common/builder/rules/links.rb +9 -0
  21. data/lib/restfulie/common/builder/rules/member_rule.rb +8 -0
  22. data/lib/restfulie/common/builder/rules/namespace.rb +25 -0
  23. data/lib/restfulie/common/builder/rules/rules_base.rb +76 -0
  24. data/lib/restfulie/common/builder.rb +16 -0
  25. data/lib/restfulie/common/errors.rb +9 -0
  26. data/lib/restfulie/{logger.rb → common/logger.rb} +3 -5
  27. data/lib/restfulie/common/representation/atom.rb +48 -0
  28. data/lib/restfulie/common/representation/generic.rb +33 -0
  29. data/lib/restfulie/common/representation/xml.rb +24 -0
  30. data/lib/restfulie/common/representation.rb +10 -0
  31. data/lib/restfulie/common.rb +23 -0
  32. data/lib/restfulie/server/action_controller/base.rb +31 -0
  33. data/lib/restfulie/server/action_controller/params_parser.rb +62 -0
  34. data/lib/restfulie/server/action_controller/restful_responder.rb +39 -0
  35. data/lib/restfulie/server/action_controller/routing/restful_route.rb +14 -0
  36. data/lib/restfulie/server/action_controller/routing.rb +12 -0
  37. data/lib/restfulie/server/action_controller.rb +15 -0
  38. data/lib/restfulie/server/action_view/helpers.rb +45 -0
  39. data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +15 -0
  40. data/lib/restfulie/server/action_view/template_handlers.rb +13 -0
  41. data/lib/restfulie/server/action_view.rb +8 -0
  42. data/lib/restfulie/server/configuration.rb +21 -0
  43. data/lib/restfulie/server/core_ext/array.rb +45 -0
  44. data/lib/restfulie/server/core_ext.rb +1 -0
  45. data/lib/restfulie/server/restfulie_controller.rb +1 -17
  46. data/lib/restfulie/server.rb +15 -0
  47. data/lib/restfulie.rb +4 -72
  48. data/lib/vendor/atom/configuration.rb +24 -0
  49. data/lib/vendor/atom/pub.rb +250 -0
  50. data/lib/vendor/atom/xml/parser.rb +373 -0
  51. data/lib/vendor/atom.rb +771 -0
  52. metadata +94 -33
  53. data/lib/restfulie/client/atom_media_type.rb +0 -75
  54. data/lib/restfulie/client/cache.rb +0 -103
  55. data/lib/restfulie/client/entry_point.rb +0 -94
  56. data/lib/restfulie/client/extensions/http.rb +0 -116
  57. data/lib/restfulie/client/helper.rb +0 -28
  58. data/lib/restfulie/client/instance.rb +0 -158
  59. data/lib/restfulie/client/request_execution.rb +0 -321
  60. data/lib/restfulie/client/state.rb +0 -36
  61. data/lib/restfulie/media_type.rb +0 -143
  62. data/lib/restfulie/media_type_control.rb +0 -115
  63. data/lib/restfulie/media_type_defaults.rb +0 -51
  64. data/lib/restfulie/server/atom_media_type.rb +0 -115
  65. data/lib/restfulie/server/base.rb +0 -91
  66. data/lib/restfulie/server/controller.rb +0 -122
  67. data/lib/restfulie/server/instance.rb +0 -102
  68. data/lib/restfulie/server/marshalling.rb +0 -47
  69. data/lib/restfulie/server/opensearch/description.rb +0 -54
  70. data/lib/restfulie/server/opensearch.rb +0 -18
  71. data/lib/restfulie/server/transition.rb +0 -93
  72. data/lib/restfulie/unmarshalling.rb +0 -131
  73. data/lib/vendor/jeokkarak/hashi.rb +0 -65
  74. data/lib/vendor/jeokkarak/jeokkarak.rb +0 -81
data/lib/restfulie.rb CHANGED
@@ -1,77 +1,9 @@
1
- #
2
- # Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
3
- # All rights reserved.
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
- #
17
-
18
- require 'restfulie/logger'
19
-
20
- require 'net/http'
21
- require 'uri'
22
- require 'vendor/jeokkarak/jeokkarak'
23
-
24
- require 'restfulie/media_type'
25
-
26
- require 'restfulie/client'
27
-
28
- require 'restfulie/server/base'
29
- require 'restfulie/server/controller'
30
- require 'restfulie/server/instance'
31
- require 'restfulie/server/marshalling'
32
- require 'restfulie/server/transition'
33
- require 'restfulie/server/restfulie_controller'
34
- require 'restfulie/server/atom_media_type'
35
- require 'restfulie/unmarshalling'
36
-
37
- # Author:: Guilherme Silveira (mailto:guilherme.silveira@caelum.com.br)
38
-
39
- # This module controls global options for the Restfulie framework.
40
1
  module Restfulie
2
+ ROOT_PATH = File.dirname(__FILE__)
3
+ $LOAD_PATH.unshift(ROOT_PATH) unless $LOAD_PATH.include?(ROOT_PATH)
41
4
 
42
- # Sets this class as a restfulie class.
43
- # You may pass a block defining your own transitions.
44
- #
45
- # The transitions added will be concatenated with any extra transitions provided by your resource through
46
- # the use of state and transition definitions.
47
- # For every transition its name is the only mandatory field:
48
- # options = {}
49
- # [:show, options] # will generate a link to your controller's show action
50
- #
51
- # The options can be used to override restfulie's conventions:
52
- # options[:rel] = "refresh" # will create a rel named refresh
53
- # options[:action] = "destroy" # will link to the destroy method
54
- # options[:controller] = another controller # will use another controller's action
55
- #
56
- # Any extra options will be passed to the target controller url_for method in order to retrieve
57
- # the transition's uri.
58
- def acts_as_restfulie
59
- extend Restfulie::Server::Base
60
- extend Restfulie::MediaTypeControl
61
- include Restfulie::Server::Instance
62
- include Restfulie::Server::Marshalling
63
- extend Restfulie::Unmarshalling #TODO still needs testing. e.g. server model has from_xml
64
- #TODO and need to test (de)serialization with both AR and no-AR
65
-
66
- self.send :define_method, :following_transitions do
67
- transitions = []
68
- yield( self, transitions ) if block_given?
69
- transitions
70
- end
71
- end
72
-
73
5
  end
74
6
 
75
- Object.extend Restfulie
7
+ require 'restfulie/client'
8
+ require 'restfulie/server'
76
9
 
77
- include ActiveSupport::CoreExtensions::Hash
@@ -0,0 +1,24 @@
1
+ # Copyright (c) 2008 The Kaphan Foundation
2
+ #
3
+ # For licensing information see LICENSE.txt.
4
+ #
5
+ # Please visit http://www.peerworks.org/contact for further information.
6
+ #
7
+
8
+ module Atom
9
+ class Configuration
10
+ def self.auth_hmac_enabled?
11
+ unless defined?(@auth_hmac_enabled)
12
+ begin
13
+ gem 'auth-hmac'
14
+ require 'auth-hmac'
15
+ @auth_hmac_enabled = true
16
+ rescue
17
+ @auth_hmac_enabled = false
18
+ end
19
+ else
20
+ @auth_hmac_enabled
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,250 @@
1
+ # Copyright (c) 2008 The Kaphan Foundation
2
+ #
3
+ # For licensing information see LICENSE.txt.
4
+ #
5
+ # Please visit http://www.peerworks.org/contact for further information.
6
+ #
7
+
8
+ require 'vendor/atom'
9
+ require 'vendor/atom/configuration'
10
+ require 'vendor/atom/xml/parser'
11
+ require 'vendor/atom/version'
12
+ require 'xml/libxml'
13
+ require 'uri'
14
+ require 'net/http'
15
+
16
+ module Atom
17
+ module Pub
18
+ class NotSupported < StandardError; end
19
+ class ProtocolError < StandardError
20
+ attr_reader :response
21
+ def initialize(response)
22
+ @response = response
23
+ end
24
+
25
+ def to_s
26
+ "Invalid response: #{@response}"
27
+ end
28
+ end
29
+
30
+ class Service
31
+ include Atom::Xml::Parseable
32
+ namespace Atom::Pub::NAMESPACE
33
+ elements :workspaces
34
+ loadable! do |reader, message, severity, base, line|
35
+ if severity == XML::Reader::SEVERITY_ERROR
36
+ raise ArgumentError, "#{message} at #{line}"
37
+ end
38
+ end
39
+
40
+ def initialize(xml = nil)
41
+ @workspaces = []
42
+
43
+ if xml
44
+ begin
45
+ if next_node_is?(xml, 'service', Atom::Pub::NAMESPACE)
46
+ xml.read
47
+ parse(xml)
48
+ else
49
+ raise ArgumentError, "XML document was missing atom:service"
50
+ end
51
+ ensure
52
+ xml.close
53
+ end
54
+ end
55
+
56
+ yield(self) if block_given?
57
+ end
58
+ end
59
+
60
+ class Categories < DelegateClass(Array)
61
+ include Atom::Xml::Parseable
62
+ elements :categories, :class => Atom::Category
63
+ attribute :href, :fixed
64
+
65
+ def initialize(o)
66
+ super([])
67
+ parse(o, :once => true)
68
+ o.read
69
+ parse(o)
70
+ end
71
+
72
+ remove_method :categories
73
+ def categories; self; end
74
+
75
+ # True true if fixed was 'yes' or 'true'
76
+ def fixed?
77
+ !self.fixed.nil? && %w(yes true).include?(self.fixed.downcase)
78
+ end
79
+ end
80
+
81
+ class Workspace
82
+ include Atom::Xml::Parseable
83
+ element :title, :class => Content, :namespace => Atom::NAMESPACE
84
+ elements :collections
85
+
86
+ def initialize(o = nil)
87
+ @collections = []
88
+
89
+ case o
90
+ when XML::Reader
91
+ o.read
92
+ parse(o)
93
+ when Hash
94
+ o.each do |k, v|
95
+ self.send("#{k}=".to_sym, v)
96
+ end
97
+ end
98
+
99
+ yield(self) if block_given?
100
+ end
101
+ end
102
+
103
+ class Collection
104
+ include Atom::Xml::Parseable
105
+ attribute :href
106
+ element :title, :class => Content, :namespace => Atom::NAMESPACE
107
+ element :categories, :class => Categories
108
+ elements :accepts, :content_only => true
109
+
110
+ def initialize(o = nil)
111
+ @accepts = []
112
+ case o
113
+ when XML::Reader
114
+ # do it once to get the attributes
115
+ parse(o, :once => true)
116
+ # now step into the element and the sub tree
117
+ o.read
118
+ parse(o)
119
+ when Hash
120
+ o.each do |k, v|
121
+ self.send("#{k}=", v)
122
+ end
123
+ end
124
+
125
+ yield(self) if block_given?
126
+ end
127
+
128
+ def feed(opts = {})
129
+ if href
130
+ Atom::Feed.load_feed(URI.parse(href), opts)
131
+ end
132
+ end
133
+
134
+ def publish(entry, opts = {})
135
+ uri = URI.parse(href)
136
+ response = nil
137
+ Net::HTTP.start(uri.host, uri.port) do |http|
138
+ request = Net::HTTP::Post.new(uri.request_uri, headers)
139
+ if opts[:user] && opts[:pass]
140
+ request.basic_auth(opts[:user], opts[:pass])
141
+ elsif opts[:hmac_access_id] && opts[:hmac_secret_key]
142
+ if Atom::Configuration.auth_hmac_enabled?
143
+ AuthHMAC.sign!(request, opts[:hmac_access_id], opts[:hmac_secret_key])
144
+ else
145
+ raise ArgumentError, "AuthHMAC credentials provides by auth-hmac gem is not installed"
146
+ end
147
+ end
148
+ response = http.request(request, entry.to_xml.to_s)
149
+ end
150
+
151
+ case response
152
+ when Net::HTTPCreated
153
+ published = begin
154
+ Atom::Entry.load_entry(response.body)
155
+ rescue ArgumentError
156
+ entry
157
+ end
158
+
159
+ if response['Location']
160
+ if published.edit_link
161
+ published.edit_link.href = response['Location']
162
+ else
163
+ published.links << Atom::Link.new(:rel => 'edit', :href => response['Location'])
164
+ end
165
+ end
166
+
167
+ published
168
+ else
169
+ raise Atom::Pub::ProtocolError, response
170
+ end
171
+ end
172
+
173
+ private
174
+ def headers
175
+ {'Accept' => 'application/atom+xml',
176
+ 'Content-Type' => 'application/atom+xml;type=entry',
177
+ 'User-Agent' => "rAtom #{Atom::VERSION::STRING}"
178
+ }
179
+ end
180
+ end
181
+ end
182
+
183
+ class Entry
184
+ def save!(opts = {})
185
+ if edit = edit_link
186
+ uri = URI.parse(edit.href)
187
+ response = nil
188
+ Net::HTTP.start(uri.host, uri.port) do |http|
189
+ request = Net::HTTP::Put.new(uri.request_uri, headers)
190
+ if opts[:user] && opts[:pass]
191
+ request.basic_auth(opts[:user], opts[:pass])
192
+ elsif opts[:hmac_access_id] && opts[:hmac_secret_key]
193
+ if Atom::Configuration.auth_hmac_enabled?
194
+ AuthHMAC.sign!(request, opts[:hmac_access_id], opts[:hmac_secret_key])
195
+ else
196
+ raise ArgumentError, "AuthHMAC credentials provides by auth-hmac gem is not installed"
197
+ end
198
+ end
199
+
200
+ response = http.request(request, self.to_xml)
201
+ end
202
+
203
+ case response
204
+ when Net::HTTPSuccess
205
+ else
206
+ raise Atom::Pub::ProtocolError, response
207
+ end
208
+ else
209
+ raise Atom::Pub::NotSupported, "Entry does not have an edit link"
210
+ end
211
+ end
212
+
213
+ def destroy!(opts = {})
214
+ if edit = edit_link
215
+ uri = URI.parse(edit.href)
216
+ response = nil
217
+ Net::HTTP.start(uri.host, uri.port) do |http|
218
+ request = Net::HTTP::Delete.new(uri.request_uri, {'Accept' => 'application/atom+xml', 'User-Agent' => "rAtom #{Atom::VERSION::STRING}"})
219
+ if opts[:user] && opts[:pass]
220
+ request.basic_auth(opts[:user], opts[:pass])
221
+ elsif opts[:hmac_access_id] && opts[:hmac_secret_key]
222
+ if Atom::Configuration.auth_hmac_enabled?
223
+ AuthHMAC.sign!(request, opts[:hmac_access_id], opts[:hmac_secret_key])
224
+ else
225
+ raise ArgumentError, "AuthHMAC credentials provides by auth-hmac gem is not installed"
226
+ end
227
+ end
228
+
229
+ response = http.request(request)
230
+ end
231
+
232
+ case response
233
+ when Net::HTTPSuccess
234
+ else
235
+ raise Atom::Pub::ProtocolError, response
236
+ end
237
+ else
238
+ raise Atom::Pub::NotSupported, "Entry does not have an edit link"
239
+ end
240
+ end
241
+
242
+ private
243
+ def headers
244
+ {'Accept' => 'application/atom+xml',
245
+ 'Content-Type' => 'application/atom+xml;type=entry',
246
+ 'User-Agent' => "rAtom #{Atom::VERSION::STRING}"
247
+ }
248
+ end
249
+ end
250
+ end