restfulie 0.6.0 → 0.7.0

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 (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