strelka 0.0.1.pre.187 → 0.0.1.pre.193

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data.tar.gz.sig +0 -0
  2. data/ChangeLog +94 -26
  3. data/Manifest.txt +4 -2
  4. data/examples/apps/ws-echo +17 -0
  5. data/lib/strelka/app.rb +26 -24
  6. data/lib/strelka/app/auth.rb +2 -1
  7. data/lib/strelka/app/errors.rb +1 -1
  8. data/lib/strelka/app/filters.rb +1 -1
  9. data/lib/strelka/app/negotiation.rb +1 -1
  10. data/lib/strelka/app/parameters.rb +2 -2
  11. data/lib/strelka/app/restresources.rb +1 -1
  12. data/lib/strelka/app/routing.rb +3 -2
  13. data/lib/strelka/app/sessions.rb +3 -3
  14. data/lib/strelka/app/templating.rb +3 -3
  15. data/lib/strelka/authprovider.rb +2 -10
  16. data/lib/strelka/behavior/plugin.rb +3 -3
  17. data/lib/strelka/httprequest.rb +5 -2
  18. data/lib/strelka/httprequest/session.rb +3 -2
  19. data/lib/strelka/httpresponse/session.rb +8 -9
  20. data/lib/strelka/mixins.rb +15 -0
  21. data/lib/strelka/plugins.rb +257 -0
  22. data/lib/strelka/router/default.rb +27 -2
  23. data/lib/strelka/session.rb +20 -2
  24. data/lib/strelka/session/db.rb +20 -10
  25. data/lib/strelka/session/default.rb +41 -18
  26. data/spec/lib/helpers.rb +1 -1
  27. data/spec/strelka/app/auth_spec.rb +1 -1
  28. data/spec/strelka/app/errors_spec.rb +1 -1
  29. data/spec/strelka/app/filters_spec.rb +1 -1
  30. data/spec/strelka/app/negotiation_spec.rb +1 -1
  31. data/spec/strelka/app/parameters_spec.rb +1 -1
  32. data/spec/strelka/app/restresources_spec.rb +1 -1
  33. data/spec/strelka/app/routing_spec.rb +4 -1
  34. data/spec/strelka/app/sessions_spec.rb +63 -17
  35. data/spec/strelka/app/templating_spec.rb +1 -1
  36. data/spec/strelka/app_spec.rb +13 -5
  37. data/spec/strelka/httprequest/session_spec.rb +44 -23
  38. data/spec/strelka/httprequest_spec.rb +21 -0
  39. data/spec/strelka/httpresponse/session_spec.rb +143 -0
  40. data/spec/strelka/{app/plugins_spec.rb → plugins_spec.rb} +64 -53
  41. data/spec/strelka/router/default_spec.rb +15 -0
  42. data/spec/strelka/router/exclusive_spec.rb +14 -0
  43. data/spec/strelka/session/db_spec.rb +11 -0
  44. data/spec/strelka/session/default_spec.rb +10 -2
  45. metadata +119 -37
  46. metadata.gz.sig +0 -0
  47. data/lib/strelka/app/plugins.rb +0 -284
@@ -1,284 +0,0 @@
1
- # -*- ruby -*-
2
- # vim: set nosta noet ts=4 sw=4:
3
- # encoding: utf-8
4
-
5
- require 'set'
6
- require 'tsort'
7
-
8
- require 'strelka' unless defined?( Strelka )
9
- require 'strelka/app' unless defined?( Strelka::App )
10
- require 'strelka/mixins'
11
-
12
- class Strelka::App
13
- extend Strelka::MethodUtilities
14
-
15
- # A topologically-sorted hash for plugin management
16
- class PluginRegistry < Hash
17
- include TSort
18
- alias_method :tsort_each_node, :each_key
19
- def tsort_each_child( node, &block )
20
- mod = fetch( node ) { [] }
21
- if mod.respond_to?( :successors )
22
- mod.successors.each( &block )
23
- else
24
- mod.each( &block )
25
- end
26
- end
27
- end
28
-
29
-
30
- ##
31
- # The Hash of loaded plugin modules, keyed by their downcased and symbolified
32
- # name (e.g., Strelka::App::Templating => :templating)
33
- singleton_attr_reader :loaded_plugins
34
- @loaded_plugins = PluginRegistry.new
35
-
36
-
37
- # Plugin Module extension -- adds registration, load-order support, etc.
38
- module Plugin
39
-
40
- ### Mixin hook -- extend including objects instead.
41
- def self::included( mod )
42
- mod.extend( self )
43
- end
44
-
45
-
46
- ### Extension hook -- Extend the given object with methods for setting it
47
- ### up as a plugin for Strelka::Apps.
48
- def self::extended( object )
49
- Strelka.log.debug "Extending %p as a Strelka::App::Plugin" % [ object ]
50
-
51
- super
52
- name = object.plugin_name
53
- object.instance_variable_set( :@successors, Set.new )
54
-
55
- # Register any pending dependencies for the newly-loaded plugin
56
- if (( deps = Strelka::App.loaded_plugins[name] ))
57
- Strelka.log.debug " installing deferred deps for %p" % [ name ]
58
- object.run_after( *deps )
59
- end
60
-
61
- Strelka.log.debug " adding %p (%p) to the plugin registry" % [ name, object ]
62
- Strelka::App.loaded_plugins[ name ] = object
63
- end
64
-
65
-
66
- #############################################################
67
- ### A P P E N D E D M E T H O D S
68
- #############################################################
69
-
70
- # An Array that tracks which plugins should be installed after itself.
71
- attr_reader :successors
72
-
73
-
74
- ### Return the name of the receiving plugin
75
- def plugin_name
76
- name = self.name || "anonymous#{self.object_id}"
77
- name.sub!( /.*::/, '' )
78
- return name.downcase.to_sym
79
- end
80
-
81
-
82
- ### Register the receiver as needing to be run before +other_plugins+ for requests, and
83
- ### *after* them for responses.
84
- def run_before( *other_plugins )
85
- name = self.plugin_name
86
- other_plugins.each do |other_name|
87
- Strelka::App.loaded_plugins[ other_name ] ||= []
88
- mod = Strelka::App.loaded_plugins[ other_name ]
89
-
90
- if mod.respond_to?( :run_after )
91
- mod.run_after( name )
92
- else
93
- Strelka.log.debug "%p plugin not yet loaded; setting up pending deps" % [ other_name ]
94
- mod << name
95
- end
96
- end
97
- end
98
-
99
-
100
- ### Register the receiver as needing to be run after +other_plugins+ for requests, and
101
- ### *before* them for responses.
102
- def run_after( *other_plugins )
103
- Strelka.log.debug " %p will run after %p" % [ self, other_plugins ]
104
- self.successors.merge( other_plugins )
105
- end
106
-
107
- end # module Plugin
108
-
109
-
110
- # Plugin system
111
- module Plugins
112
-
113
- ### Inclusion callback -- add class methods and instance variables without
114
- ### needing a separate call to #extend.
115
- def self::included( klass )
116
- klass.extend( ClassMethods )
117
- super
118
- end
119
-
120
-
121
- ### Class methods to add to classes with plugins.
122
- module ClassMethods
123
-
124
- ##
125
- # If plugins have already been installed, this will be the call frame
126
- # they were first installed from. This is used to warn about installing
127
- # plugins twice.
128
- attr_accessor :plugins_installed_from
129
-
130
-
131
- ### Returns +true+ if the plugins for the extended app class have already
132
- ### been installed.
133
- def plugins_installed?
134
- return !self.plugins_installed_from.nil?
135
- end
136
-
137
-
138
- ### Extension callback -- add instance variables to extending objects.
139
- def inherited( subclass )
140
- super
141
- @plugins ||= []
142
- subclass.instance_variable_set( :@plugins, @plugins.dup )
143
- subclass.instance_variable_set( :@plugins_installed_from, nil )
144
- end
145
-
146
-
147
- ### Load the plugins with the given +names+ and install them.
148
- def plugins( *names )
149
- Strelka.log.info "Adding plugins: %s" % [ names.flatten.map(&:to_s).join(', ') ]
150
-
151
- # Load the associated Plugin Module objects
152
- names.flatten.each {|name| self.load_plugin(name) }
153
-
154
- # Add the name/s to the list of mixins to apply on startup
155
- @plugins |= names
156
-
157
- # Install the declarative half of the plugin immediately
158
- names.each do |name|
159
- plugin = nil
160
-
161
- if name.is_a?( Module )
162
- plugin = name
163
- else
164
- plugin = Strelka::App.loaded_plugins[ name ]
165
- end
166
-
167
- Strelka.log.debug " registering %p" % [ name ]
168
- self.register_plugin( plugin )
169
- end
170
- end
171
- alias_method :plugin, :plugins
172
-
173
-
174
- ### Load the plugin with the given +name+
175
- def load_plugin( name )
176
-
177
- # Just return Modules as-is
178
- return name if name.is_a?( Strelka::App::Plugin )
179
- mod = Strelka::App.loaded_plugins[ name.to_sym ]
180
-
181
- unless mod.is_a?( Module )
182
- Strelka.log.debug "Loading plugin from strelka/app/#{name}"
183
- require "strelka/app/#{name}"
184
- mod = Strelka::App.loaded_plugins[ name.to_sym ] or
185
- raise "#{name} plugin didn't load correctly."
186
- end
187
-
188
- return mod
189
- end
190
-
191
-
192
- ### Register the plugin +mod+ in the receiving class. This adds any
193
- ### declaratives and class-level data necessary for configuring the
194
- ### plugin.
195
- def register_plugin( mod )
196
- if mod.const_defined?( :ClassMethods )
197
- cm_mod = mod.const_get(:ClassMethods)
198
- Strelka.log.debug " adding class methods from %p" % [ cm_mod ]
199
-
200
- extend( cm_mod )
201
- cm_mod.instance_variables.each do |ivar|
202
- Strelka.log.debug " copying class instance variable %s" % [ ivar ]
203
- ival = cm_mod.instance_variable_get( ivar )
204
-
205
- # Don't duplicate modules/classes or immediates
206
- instance_variable_set( ivar, Strelka::DataUtilities.deep_copy(ival) )
207
- end
208
- end
209
- end
210
-
211
-
212
- ### Install the mixin part of plugins immediately before the first instance
213
- ### is created.
214
- def new( * )
215
- self.install_plugins unless self.plugins_installed?
216
- super
217
- end
218
-
219
-
220
- ### Install the mixin part of the plugin, in the order determined by
221
- ### the plugin registry based on the run_before and run_after specifications
222
- ### of the plugins themselves.
223
- def install_plugins
224
- if self.plugins_installed?
225
- Strelka.log.warn "Plugins were already installed for %p from %p" %
226
- [ self, self.plugins_installed_from ]
227
- Strelka.log.info "I'll attempt to install any new ones, but plugin ordering"
228
- Strelka.log.info "and other functionality might exhibit strange behavior."
229
- else
230
- Strelka.log.info "Installing plugins for %p." % [ self ]
231
- end
232
-
233
- sorted_plugins = Strelka::App.loaded_plugins.tsort.reverse
234
-
235
- sorted_plugins.each do |name|
236
- mod = Strelka::App.loaded_plugins[ name ]
237
-
238
- unless @plugins.include?( name ) || @plugins.include?( mod )
239
- Strelka.log.debug " skipping %s" % [ name ]
240
- next
241
- end
242
-
243
- Strelka.log.info " including %p." % [ mod ]
244
- include( mod )
245
- end
246
-
247
- self.plugins_installed_from = caller( 1 ).first
248
- end
249
-
250
- end # module ClassMethods
251
-
252
-
253
- #
254
- # :section: Extension Points
255
- #
256
-
257
- ### The main extension-point for the plugin system. Strelka::App supers to this method
258
- ### with a block that processes the actual request, and the plugins implement this
259
- ### method to add their own functionality.
260
- def handle_request( request, &block )
261
- raise LocalJumpError,
262
- "no block given; plugin supering without preserving arguments?" unless block
263
- return block.call( request )
264
- end
265
-
266
-
267
- ### An alternate extension-point for the plugin system. Plugins can implement this method
268
- ### to alter or replace the +request+ before the regular request/response cycle begins.
269
- def fixup_request( request )
270
- return request
271
- end
272
-
273
-
274
- ### An alternate extension-point for the plugin system. Plugins can implement this method
275
- ### to alter or replace the +response+ after the regular request/response cycle is finished.
276
- def fixup_response( response )
277
- return response
278
- end
279
-
280
- end # module Plugins
281
-
282
- end # class Strelka::App
283
-
284
-