rsence 2.0.0.6.pre → 2.0.0.7.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/INSTALL.rdoc +39 -25
- data/VERSION +1 -1
- data/conf/default_conf.yaml +0 -3
- data/lib/conf/default.rb +59 -60
- data/lib/daemon/daemon.rb +269 -280
- data/lib/http/broker.rb +47 -14
- data/lib/http/rackup.rb +4 -0
- data/lib/http/request.rb +47 -49
- data/lib/http/response.rb +47 -45
- data/lib/plugins/gui_plugin.rb +22 -21
- data/lib/plugins/guiparser.rb +95 -94
- data/lib/plugins/plugin.rb +300 -295
- data/lib/plugins/plugin_plugins.rb +64 -40
- data/lib/plugins/plugin_sqlite_db.rb +63 -63
- data/lib/plugins/plugin_util.rb +95 -104
- data/lib/plugins/pluginmanager.rb +373 -414
- data/lib/plugins/plugins.rb +11 -4
- data/lib/plugins/servlet.rb +10 -9
- data/lib/session/msg.rb +249 -248
- data/lib/session/sessionmanager.rb +364 -373
- data/lib/session/sessionstorage.rb +265 -272
- data/lib/transporter/transporter.rb +164 -169
- data/lib/util/gzstring.rb +2 -0
- data/lib/values/hvalue.rb +224 -224
- data/lib/values/valuemanager.rb +98 -98
- data/plugins/index_html/index_html.rb +1 -32
- metadata +4 -4
data/lib/plugins/plugin.rb
CHANGED
@@ -6,300 +6,305 @@
|
|
6
6
|
# with this software package. If not, contact licensing@riassence.com
|
7
7
|
##
|
8
8
|
|
9
|
-
## = Abstract
|
10
|
-
## The Plugin class is the base class for extending server logic.
|
11
|
-
## A single Plugin instance serves the requests of all sessions,
|
12
|
-
## which makes them very cpu and memory efficient compared to systems,
|
13
|
-
## where the server classes are constructed and destructed for each
|
14
|
-
## request.
|
15
|
-
##
|
16
|
-
## Plugins are designed to be contained in a plugin directory bundle and
|
17
|
-
## to be loaded by the +PluginManager+, which is also responsible for
|
18
|
-
## delegating the events and other calls throughout the system.
|
19
|
-
##
|
20
|
-
## == Anatomy of a plugin bundle
|
21
|
-
## The plugin bundle contains all data needed to run the plugin. Design
|
22
|
-
## your plugin without any hard-coded paths, remember that it's intended
|
23
|
-
## to be deployed by "dropping" the whole plugin into one of the server's
|
24
|
-
## plugins directories.
|
25
|
-
##
|
26
|
-
## The +PluginManager+ looks for such bundles and evaluates them into an
|
27
|
-
## anonymous +Module+ namespace. The content of the ruby source file
|
28
|
-
## is then responsible for including its libraries, constructing an
|
29
|
-
## instance of itself and registering itself as a part of the system.
|
30
|
-
##
|
31
|
-
## It's advised to use the +GUIPlugin+ class for plugins that handle
|
32
|
-
## user interfaces. Usage of the +Plugin+ bundle is advised to use
|
33
|
-
## for plugins that provide extra functionality, value responders
|
34
|
-
## and other utilities that supplement the user interface.
|
35
|
-
##
|
36
|
-
## You must call the +#register+ method after the class is constructed.
|
37
|
-
## Otherwise, the class is not connected to the system and just discarded
|
38
|
-
## and then garbage collected.
|
39
|
-
##
|
40
|
-
## == Messages
|
41
|
-
## As a side effect of having single instances of plugins serve the requests
|
42
|
-
## of all sessions, the request/response/session messaging is implemented
|
43
|
-
## as messaging objects. These objects contain or delegate all the necessary
|
44
|
-
## hooks required by the complete request/response cycle.
|
45
|
-
##
|
46
|
-
## The naming convention of the +Message+ instance is +msg+ and it's
|
47
|
-
## given as the first parameter of methods needing it.
|
48
|
-
##
|
49
|
-
## Use +msg.ses_id+ to identify the session's serial number and +msg.user_id+
|
50
|
-
## to identify the user's identity.
|
51
|
-
##
|
52
|
-
## Use the +msg.session+ +Hash+ to store any persistent data
|
53
|
-
## associated with the user's session, preferably using the name of the
|
54
|
-
## plugin or its registered name as the primary key entry in the Hash.
|
55
|
-
## The session data is persistent; it's stored in the session database
|
56
|
-
## by +SessionStorage+ automatically.
|
57
|
-
##
|
58
|
-
## The +msg+ instance also provides access to the +Request+ and +Response+
|
59
|
-
## objects as +msg.request+ and +msg.response+, respectively.
|
60
|
-
##
|
61
|
-
## Use the +msg.run+ method to call other plugins.
|
62
|
-
##
|
63
|
-
## To append js source code to be evaluated in the client, use the +msg.reply+
|
64
|
-
## call. The +msg.console+ call appends messages to the browser's js console.
|
65
|
-
##
|
66
|
-
##
|
67
|
-
## == Session -related event methods
|
68
|
-
## The +#get_ses+ method returns (or creates and returns) the entry in
|
69
|
-
## the session based on the name your plugin is registered as. It's advised
|
70
|
-
## to use this call instead of manually managing +msg.session+ in most cases.
|
71
|
-
##
|
72
|
-
## The +#idle+ method is called each time a client performs a data
|
73
|
-
## synchronization or "idle poll" request.
|
74
|
-
##
|
75
|
-
## The +#init_ses+ method is called once in the same request a new session
|
76
|
-
## is created. A new session is created, when a user enters accesses the
|
77
|
-
## server the first time, or the first time after the previous session is
|
78
|
-
## expired.
|
79
|
-
##
|
80
|
-
## The +#init_ui+ method is called by the "main" plugin after the client has
|
81
|
-
## booted successfully. The +GUIPlugin+ class extends this method to
|
82
|
-
## automatically load and initialize the user interface from a data structure.
|
83
|
-
##
|
84
|
-
## The +#restore_ses+ method is called once in the same request an old
|
85
|
-
## session is restored. A session is restored, when the user returns to
|
86
|
-
## the page or reloads the page before the session is expired.
|
87
|
-
##
|
88
|
-
## === When the server is configured to restore previous sessions (default):
|
89
|
-
## If the user accesses the same page using the same browser (in different
|
90
|
-
## tabs or windows), only the most recently restored one is valid, while
|
91
|
-
## the previous ones are immediately invalidated.
|
92
|
-
## If your application is intended to support several sessions per browser,
|
93
|
-
## enable session cloning in the configuration file.
|
94
|
-
##
|
95
|
-
## === When the server is configured to restore and clone previous sessions:
|
96
|
-
## When sessions are cloned, the previous session is not invalidated and
|
97
|
-
## exists until timing out as a result of the web browser window being closed
|
98
|
-
## or client computer losing network connectivity for a certain (configurable)
|
99
|
-
## time frame.
|
100
|
-
##
|
101
|
-
## The +#cloned_target+ method is like +#restore_ses+, but called when
|
102
|
-
## the session is a clone of a previous session.
|
103
|
-
##
|
104
|
-
## The +#cloned_source+ method is called on the next request of the previous
|
105
|
-
## session after it has been cloned.
|
106
|
-
##
|
107
|
-
## == Server event methods
|
108
|
-
## Extend the +#init+ method to invoke constructor functionality that
|
109
|
-
## depends on the plugin to be constructed and registered as a part of
|
110
|
-
## the system.
|
111
|
-
##
|
112
|
-
## Extend the +#open+, +#flush+ and +#close+ methods to open, flush and close
|
113
|
-
## streams or other similar functionality.
|
114
|
-
##
|
115
|
-
## == Data handling
|
116
|
-
## The data exchange system exists to support bi-directional
|
117
|
-
## data synchronization between the browser and the plugin. The values
|
118
|
-
## are stored in the session as +HValue+ instances.
|
119
|
-
##
|
120
|
-
## Values support Hashes, Arrays, Strings, Numbers, Booleans and
|
121
|
-
## combinations of them. The data is automatically converted between
|
122
|
-
## ruby objects (server) and json objects (client).
|
123
|
-
##
|
124
|
-
## Each instance may be bound to plugin methods that are used as
|
125
|
-
## value change notification responders.
|
126
|
-
##
|
127
|
-
## When a method is bound to the value, the method is called as an
|
128
|
-
## event notification whenever the client has changed the value and
|
129
|
-
## synchronizes it to the server. The responders act as validators
|
130
|
-
## by default.
|
131
|
-
##
|
132
|
-
## Values are also bound in the client to classes implementing the
|
133
|
-
## HValueResponder interface, like any derivate of HControl. See the
|
134
|
-
## client documentation for instructions about using them.
|
135
|
-
##
|
136
|
-
## To define a value responder method, it needs to respond to exactly
|
137
|
-
## two parameters: the +Message+ instance +msg+ and the HValue object
|
138
|
-
## (in that order). The method's return value must be either +true+
|
139
|
-
## or +false+. When the method returns +false+, the change is discarded
|
140
|
-
## and the previously server-set value is sent back to the client.
|
141
|
-
##
|
142
|
-
## A minimal value responder method is defined like this:
|
143
|
-
##
|
144
|
-
## def my_value_responder( msg, my_value )
|
145
|
-
## return true
|
146
|
-
## end
|
147
|
-
##
|
148
|
-
## To access the content of the value, use the +HValue#data+ attribute.
|
149
|
-
##
|
150
|
-
## def int_between_100_and_200( msg, value )
|
151
|
-
## data = value.data.to_i
|
152
|
-
## return ( data >= 100 and data <= 200 )
|
153
|
-
## end
|
154
|
-
##
|
155
|
-
## To change the content of the value, use the +HValue#set+ method.
|
156
|
-
##
|
157
|
-
## def int_between_100_and_200( msg, value )
|
158
|
-
## data = value.data.to_i
|
159
|
-
## value.set( msg, 100 ) if data < 100
|
160
|
-
## value.set( msg, 200 ) if data > 200
|
161
|
-
## return true
|
162
|
-
## end
|
163
|
-
##
|
164
|
-
## == Defining values
|
165
|
-
## The simplest and recommended way of defining the values is to define
|
166
|
-
## the value configuration file +values.yaml+. Its configuration is then
|
167
|
-
## applied to sessions automatically.
|
168
|
-
##
|
169
|
-
##
|
170
|
-
## === Syntax reference of the contents of a +values.yaml+ file:
|
171
|
-
##
|
172
|
-
## # The name of the value (:value_name).
|
173
|
-
## # A hash key in the yaml syntax
|
174
|
-
## :value_name:
|
175
|
-
##
|
176
|
-
## # All of these keys are optional!
|
177
|
-
##
|
178
|
-
## # Default value, a string "Foo" here.
|
179
|
-
## # Defaults to 0
|
180
|
-
## :value: Foo
|
181
|
-
##
|
182
|
-
## # A plugin method to call to define the default value
|
183
|
-
## # instead of the one defined in :value
|
184
|
-
## :value_call:
|
185
|
-
## :plugin: plugin_name # defaults to the plugin where defined
|
186
|
-
##
|
187
|
-
## # Mandatory; name of the method to call
|
188
|
-
## :method: method_name
|
189
|
-
##
|
190
|
-
## # Optional, list of parameter values for the :method
|
191
|
-
## :args:
|
192
|
-
## # three parameters: 1, 'foo', 3
|
193
|
-
## - 1
|
194
|
-
## - foo
|
195
|
-
## - 3
|
196
|
-
##
|
197
|
-
## # When false, doesn't pass the msg as the first parameter.
|
198
|
-
## # Defaults to true
|
199
|
-
## :uses_msg: true
|
200
|
-
##
|
201
|
-
## # Restore the default, when the session is restored; defaults to false
|
202
|
-
## :restore_default: false
|
203
|
-
##
|
204
|
-
## # List of value responder methods to bind.
|
205
|
-
## :responders:
|
206
|
-
## -
|
207
|
-
## # name of plugin to call, defaults to the plugin where defined:
|
208
|
-
## :plugin: plugin_name
|
209
|
-
##
|
210
|
-
## # mandatory, name of the method to call
|
211
|
-
## :method: method_name
|
212
|
-
##
|
213
|
-
## # Another responder, this one using the same plugin where defined:
|
214
|
-
## - :method: another_method
|
215
|
-
##
|
216
|
-
## # Another value, this one just defining the defaults
|
217
|
-
## # by supplying an empty Hash:
|
218
|
-
## # (value: 0, default restored, no responders or calls)
|
219
|
-
## :value_with_defaults: {}
|
220
|
-
##
|
221
|
-
## # This value defines a Number (123) and doesn't restore
|
222
|
-
## # the default, when restoring the session.
|
223
|
-
## :one_two_three:
|
224
|
-
## :value: 123
|
225
|
-
## :restore_default: false
|
226
|
-
##
|
227
|
-
## # This value gets a random string and specifies a responder,
|
228
|
-
## # that ensures it's unique, if changed in the client.
|
229
|
-
## :random_unique_string:
|
230
|
-
## :value_call:
|
231
|
-
## :method: get_unique_random_string
|
232
|
-
## :uses_msg: false
|
233
|
-
## :responders:
|
234
|
-
## - :method: ensure_unique_random_string
|
235
|
-
##
|
236
|
-
## = Examples
|
237
|
-
## More examples are available in the repository;
|
238
|
-
## http://svn.rsence.org/contrib/plugins
|
239
|
-
## ..as well as the standard "main" plugin in the "plugins" directory.
|
240
|
-
##
|
241
|
-
##
|
242
|
-
## == A minimal Plugin bundle
|
243
|
-
## The minimal active plugin bundle (named "name_of_plugin")
|
244
|
-
## is defined like this:
|
245
|
-
##
|
246
|
-
## [dir] name_of_plugin
|
247
|
-
## |
|
248
|
-
## +---[file] name_of_plugin.rb
|
249
|
-
##
|
250
|
-
## This sample Plugin doesn't do anything except construct itself and
|
251
|
-
## respond as 'name_of_plugin'.
|
252
|
-
##
|
253
|
-
## Plugin.new.register('name_of_plugin')
|
254
|
-
##
|
255
|
-
## However, this is not very useful in itself, so you'll need to extend
|
256
|
-
## its functionality to do anything useful.
|
257
|
-
##
|
258
|
-
## == A simple Plugin extension
|
259
|
-
## This plugin logs session events to the logs/session_log file.
|
260
|
-
##
|
261
|
-
## [dir] ses_logger
|
262
|
-
## |
|
263
|
-
## +---[file] ses_logger.rb
|
264
|
-
## |
|
265
|
-
## +---[dir] logs
|
266
|
-
## |
|
267
|
-
## +---[file] session_log
|
268
|
-
##
|
269
|
-
## == Contents of "ses_logger.rb"
|
270
|
-
##
|
271
|
-
## class SessionLogger < Plugin
|
272
|
-
## def init
|
273
|
-
## super
|
274
|
-
## @logfile = false
|
275
|
-
## end
|
276
|
-
## def open
|
277
|
-
## log_path = compose_plugin_path( 'session_log', 'logs' )
|
278
|
-
## @logfile = File.open( log_path, 'a' )
|
279
|
-
## end
|
280
|
-
## def close
|
281
|
-
## @logfile.close if @logfile
|
282
|
-
## @logfile = false
|
283
|
-
## end
|
284
|
-
## def flush
|
285
|
-
## @logfile.flush if @logfile
|
286
|
-
## end
|
287
|
-
## def init_ses( msg )
|
288
|
-
## super
|
289
|
-
## @logfile.write( "#{Time.new} -- Session id #{msg.ses_id} was created.\n" )
|
290
|
-
## end
|
291
|
-
## def restore_ses( msg )
|
292
|
-
## super
|
293
|
-
## @logfile.write( "#{Time.new} -- Session id #{msg.ses_id} was restored.\n" )
|
294
|
-
## end
|
295
|
-
## def idle( msg )
|
296
|
-
## @logfile.write( "#{Time.new} -- Client of session id #{msg.ses_id} connected.\n" )
|
297
|
-
## end
|
298
|
-
## end
|
299
|
-
## SessionLogger.new.register( 'ses_logger' )
|
300
|
-
##
|
301
9
|
module ::RSence
|
302
10
|
module Plugins
|
11
|
+
|
12
|
+
## = Abstract
|
13
|
+
##
|
14
|
+
## The PluginTemplate is used to create a Plugin mimic class in
|
15
|
+
## Plugins.bundle_loader using the Plugins.PluginWrapper mimic.
|
16
|
+
##
|
17
|
+
## The Plugin class is the base class for extending server logic.
|
18
|
+
## A single Plugin instance serves the requests of all sessions,
|
19
|
+
## which makes them very cpu and memory efficient compared to systems,
|
20
|
+
## where the server classes are constructed and destructed for each
|
21
|
+
## request.
|
22
|
+
##
|
23
|
+
## Plugins are designed to be contained in a plugin directory bundle and
|
24
|
+
## to be loaded by the +PluginManager+, which is also responsible for
|
25
|
+
## delegating the events and other calls throughout the system.
|
26
|
+
##
|
27
|
+
## == Anatomy of a plugin bundle
|
28
|
+
## The plugin bundle contains all data needed to run the plugin. Design
|
29
|
+
## your plugin without any hard-coded paths, remember that it's intended
|
30
|
+
## to be deployed by "dropping" the whole plugin into one of the server's
|
31
|
+
## plugins directories.
|
32
|
+
##
|
33
|
+
## The +PluginManager+ looks for such bundles and evaluates them into an
|
34
|
+
## anonymous +Module+ namespace. The content of the ruby source file
|
35
|
+
## is then responsible for including its libraries, constructing an
|
36
|
+
## instance of itself and registering itself as a part of the system.
|
37
|
+
##
|
38
|
+
## It's advised to use the +GUIPlugin+ class for plugins that handle
|
39
|
+
## user interfaces. Usage of the +Plugin+ bundle is advised to use
|
40
|
+
## for plugins that provide extra functionality, value responders
|
41
|
+
## and other utilities that supplement the user interface.
|
42
|
+
##
|
43
|
+
## You must call the +#register+ method after the class is constructed.
|
44
|
+
## Otherwise, the class is not connected to the system and just discarded
|
45
|
+
## and then garbage collected.
|
46
|
+
##
|
47
|
+
## == Messages
|
48
|
+
## As a side effect of having single instances of plugins serve the requests
|
49
|
+
## of all sessions, the request/response/session messaging is implemented
|
50
|
+
## as messaging objects. These objects contain or delegate all the necessary
|
51
|
+
## hooks required by the complete request/response cycle.
|
52
|
+
##
|
53
|
+
## The naming convention of the +Message+ instance is +msg+ and it's
|
54
|
+
## given as the first parameter of methods needing it.
|
55
|
+
##
|
56
|
+
## Use +msg.ses_id+ to identify the session's serial number and +msg.user_id+
|
57
|
+
## to identify the user's identity.
|
58
|
+
##
|
59
|
+
## Use the +msg.session+ +Hash+ to store any persistent data
|
60
|
+
## associated with the user's session, preferably using the name of the
|
61
|
+
## plugin or its registered name as the primary key entry in the Hash.
|
62
|
+
## The session data is persistent; it's stored in the session database
|
63
|
+
## by +SessionStorage+ automatically.
|
64
|
+
##
|
65
|
+
## The +msg+ instance also provides access to the +Request+ and +Response+
|
66
|
+
## objects as +msg.request+ and +msg.response+, respectively.
|
67
|
+
##
|
68
|
+
## Use the +msg.run+ method to call other plugins.
|
69
|
+
##
|
70
|
+
## To append js source code to be evaluated in the client, use the +msg.reply+
|
71
|
+
## call. The +msg.console+ call appends messages to the browser's js console.
|
72
|
+
##
|
73
|
+
##
|
74
|
+
## == Session -related event methods
|
75
|
+
## The +#get_ses+ method returns (or creates and returns) the entry in
|
76
|
+
## the session based on the name your plugin is registered as. It's advised
|
77
|
+
## to use this call instead of manually managing +msg.session+ in most cases.
|
78
|
+
##
|
79
|
+
## The +#idle+ method is called each time a client performs a data
|
80
|
+
## synchronization or "idle poll" request.
|
81
|
+
##
|
82
|
+
## The +#init_ses+ method is called once in the same request a new session
|
83
|
+
## is created. A new session is created, when a user enters accesses the
|
84
|
+
## server the first time, or the first time after the previous session is
|
85
|
+
## expired.
|
86
|
+
##
|
87
|
+
## The +#init_ui+ method is called by the "main" plugin after the client has
|
88
|
+
## booted successfully. The +GUIPlugin+ class extends this method to
|
89
|
+
## automatically load and initialize the user interface from a data structure.
|
90
|
+
##
|
91
|
+
## The +#restore_ses+ method is called once in the same request an old
|
92
|
+
## session is restored. A session is restored, when the user returns to
|
93
|
+
## the page or reloads the page before the session is expired.
|
94
|
+
##
|
95
|
+
## === When the server is configured to restore previous sessions (default):
|
96
|
+
## If the user accesses the same page using the same browser (in different
|
97
|
+
## tabs or windows), only the most recently restored one is valid, while
|
98
|
+
## the previous ones are immediately invalidated.
|
99
|
+
## If your application is intended to support several sessions per browser,
|
100
|
+
## enable session cloning in the configuration file.
|
101
|
+
##
|
102
|
+
## === When the server is configured to restore and clone previous sessions:
|
103
|
+
## When sessions are cloned, the previous session is not invalidated and
|
104
|
+
## exists until timing out as a result of the web browser window being closed
|
105
|
+
## or client computer losing network connectivity for a certain (configurable)
|
106
|
+
## time frame.
|
107
|
+
##
|
108
|
+
## The +#cloned_target+ method is like +#restore_ses+, but called when
|
109
|
+
## the session is a clone of a previous session.
|
110
|
+
##
|
111
|
+
## The +#cloned_source+ method is called on the next request of the previous
|
112
|
+
## session after it has been cloned.
|
113
|
+
##
|
114
|
+
## == Server event methods
|
115
|
+
## Extend the +#init+ method to invoke constructor functionality that
|
116
|
+
## depends on the plugin to be constructed and registered as a part of
|
117
|
+
## the system.
|
118
|
+
##
|
119
|
+
## Extend the +#open+, +#flush+ and +#close+ methods to open, flush and close
|
120
|
+
## streams or other similar functionality.
|
121
|
+
##
|
122
|
+
## == Data handling
|
123
|
+
## The data exchange system exists to support bi-directional
|
124
|
+
## data synchronization between the browser and the plugin. The values
|
125
|
+
## are stored in the session as +HValue+ instances.
|
126
|
+
##
|
127
|
+
## Values support Hashes, Arrays, Strings, Numbers, Booleans and
|
128
|
+
## combinations of them. The data is automatically converted between
|
129
|
+
## ruby objects (server) and json objects (client).
|
130
|
+
##
|
131
|
+
## Each instance may be bound to plugin methods that are used as
|
132
|
+
## value change notification responders.
|
133
|
+
##
|
134
|
+
## When a method is bound to the value, the method is called as an
|
135
|
+
## event notification whenever the client has changed the value and
|
136
|
+
## synchronizes it to the server. The responders act as validators
|
137
|
+
## by default.
|
138
|
+
##
|
139
|
+
## Values are also bound in the client to classes implementing the
|
140
|
+
## HValueResponder interface, like any derivate of HControl. See the
|
141
|
+
## client documentation for instructions about using them.
|
142
|
+
##
|
143
|
+
## To define a value responder method, it needs to respond to exactly
|
144
|
+
## two parameters: the +Message+ instance +msg+ and the HValue object
|
145
|
+
## (in that order). The method's return value must be either +true+
|
146
|
+
## or +false+. When the method returns +false+, the change is discarded
|
147
|
+
## and the previously server-set value is sent back to the client.
|
148
|
+
##
|
149
|
+
## A minimal value responder method is defined like this:
|
150
|
+
##
|
151
|
+
## def my_value_responder( msg, my_value )
|
152
|
+
## return true
|
153
|
+
## end
|
154
|
+
##
|
155
|
+
## To access the content of the value, use the +HValue#data+ attribute.
|
156
|
+
##
|
157
|
+
## def int_between_100_and_200( msg, value )
|
158
|
+
## data = value.data.to_i
|
159
|
+
## return ( data >= 100 and data <= 200 )
|
160
|
+
## end
|
161
|
+
##
|
162
|
+
## To change the content of the value, use the +HValue#set+ method.
|
163
|
+
##
|
164
|
+
## def int_between_100_and_200( msg, value )
|
165
|
+
## data = value.data.to_i
|
166
|
+
## value.set( msg, 100 ) if data < 100
|
167
|
+
## value.set( msg, 200 ) if data > 200
|
168
|
+
## return true
|
169
|
+
## end
|
170
|
+
##
|
171
|
+
## == Defining values
|
172
|
+
## The simplest and recommended way of defining the values is to define
|
173
|
+
## the value configuration file +values.yaml+. Its configuration is then
|
174
|
+
## applied to sessions automatically.
|
175
|
+
##
|
176
|
+
##
|
177
|
+
## === Syntax reference of the contents of a +values.yaml+ file:
|
178
|
+
##
|
179
|
+
## # The name of the value (:value_name).
|
180
|
+
## # A hash key in the yaml syntax
|
181
|
+
## :value_name:
|
182
|
+
##
|
183
|
+
## # All of these keys are optional!
|
184
|
+
##
|
185
|
+
## # Default value, a string "Foo" here.
|
186
|
+
## # Defaults to 0
|
187
|
+
## :value: Foo
|
188
|
+
##
|
189
|
+
## # A plugin method to call to define the default value
|
190
|
+
## # instead of the one defined in :value
|
191
|
+
## :value_call:
|
192
|
+
## :plugin: plugin_name # defaults to the plugin where defined
|
193
|
+
##
|
194
|
+
## # Mandatory; name of the method to call
|
195
|
+
## :method: method_name
|
196
|
+
##
|
197
|
+
## # Optional, list of parameter values for the :method
|
198
|
+
## :args:
|
199
|
+
## # three parameters: 1, 'foo', 3
|
200
|
+
## - 1
|
201
|
+
## - foo
|
202
|
+
## - 3
|
203
|
+
##
|
204
|
+
## # When false, doesn't pass the msg as the first parameter.
|
205
|
+
## # Defaults to true
|
206
|
+
## :uses_msg: true
|
207
|
+
##
|
208
|
+
## # Restore the default, when the session is restored; defaults to false
|
209
|
+
## :restore_default: false
|
210
|
+
##
|
211
|
+
## # List of value responder methods to bind.
|
212
|
+
## :responders:
|
213
|
+
## -
|
214
|
+
## # name of plugin to call, defaults to the plugin where defined:
|
215
|
+
## :plugin: plugin_name
|
216
|
+
##
|
217
|
+
## # mandatory, name of the method to call
|
218
|
+
## :method: method_name
|
219
|
+
##
|
220
|
+
## # Another responder, this one using the same plugin where defined:
|
221
|
+
## - :method: another_method
|
222
|
+
##
|
223
|
+
## # Another value, this one just defining the defaults
|
224
|
+
## # by supplying an empty Hash:
|
225
|
+
## # (value: 0, default restored, no responders or calls)
|
226
|
+
## :value_with_defaults: {}
|
227
|
+
##
|
228
|
+
## # This value defines a Number (123) and doesn't restore
|
229
|
+
## # the default, when restoring the session.
|
230
|
+
## :one_two_three:
|
231
|
+
## :value: 123
|
232
|
+
## :restore_default: false
|
233
|
+
##
|
234
|
+
## # This value gets a random string and specifies a responder,
|
235
|
+
## # that ensures it's unique, if changed in the client.
|
236
|
+
## :random_unique_string:
|
237
|
+
## :value_call:
|
238
|
+
## :method: get_unique_random_string
|
239
|
+
## :uses_msg: false
|
240
|
+
## :responders:
|
241
|
+
## - :method: ensure_unique_random_string
|
242
|
+
##
|
243
|
+
## = Examples
|
244
|
+
## More examples are available in the repository;
|
245
|
+
## http://svn.rsence.org/contrib/plugins
|
246
|
+
## ..as well as the standard "main" plugin in the "plugins" directory.
|
247
|
+
##
|
248
|
+
##
|
249
|
+
## == A minimal Plugin bundle
|
250
|
+
## The minimal active plugin bundle (named "name_of_plugin")
|
251
|
+
## is defined like this:
|
252
|
+
##
|
253
|
+
## [dir] name_of_plugin
|
254
|
+
## |
|
255
|
+
## +---[file] name_of_plugin.rb
|
256
|
+
##
|
257
|
+
## This sample Plugin doesn't do anything except construct itself and
|
258
|
+
## respond as 'name_of_plugin'.
|
259
|
+
##
|
260
|
+
## Plugin.new.register('name_of_plugin')
|
261
|
+
##
|
262
|
+
## However, this is not very useful in itself, so you'll need to extend
|
263
|
+
## its functionality to do anything useful.
|
264
|
+
##
|
265
|
+
## == A simple Plugin extension
|
266
|
+
## This plugin logs session events to the logs/session_log file.
|
267
|
+
##
|
268
|
+
## [dir] ses_logger
|
269
|
+
## |
|
270
|
+
## +---[file] ses_logger.rb
|
271
|
+
## |
|
272
|
+
## +---[dir] logs
|
273
|
+
## |
|
274
|
+
## +---[file] session_log
|
275
|
+
##
|
276
|
+
## == Contents of "ses_logger.rb"
|
277
|
+
##
|
278
|
+
## class SessionLogger < Plugin
|
279
|
+
## def init
|
280
|
+
## super
|
281
|
+
## @logfile = false
|
282
|
+
## end
|
283
|
+
## def open
|
284
|
+
## log_path = bundle_path( 'session_log', 'logs' )
|
285
|
+
## @logfile = File.open( log_path, 'a' )
|
286
|
+
## end
|
287
|
+
## def close
|
288
|
+
## @logfile.close if @logfile
|
289
|
+
## @logfile = false
|
290
|
+
## end
|
291
|
+
## def flush
|
292
|
+
## @logfile.flush if @logfile
|
293
|
+
## end
|
294
|
+
## def init_ses( msg )
|
295
|
+
## super
|
296
|
+
## @logfile.write( "#{Time.new} -- Session id #{msg.ses_id} was created.\n" )
|
297
|
+
## end
|
298
|
+
## def restore_ses( msg )
|
299
|
+
## super
|
300
|
+
## @logfile.write( "#{Time.new} -- Session id #{msg.ses_id} was restored.\n" )
|
301
|
+
## end
|
302
|
+
## def idle( msg )
|
303
|
+
## @logfile.write( "#{Time.new} -- Client of session id #{msg.ses_id} connected.\n" )
|
304
|
+
## end
|
305
|
+
## end
|
306
|
+
## SessionLogger.new.register( 'ses_logger' )
|
307
|
+
##
|
303
308
|
class PluginTemplate
|
304
309
|
include PluginUtil
|
305
310
|
def self.bundle_type; :Plugin; end
|
@@ -394,7 +399,7 @@ module ::RSence
|
|
394
399
|
#
|
395
400
|
# These definitions are accessible as the +@values+ attribute.
|
396
401
|
def init_values
|
397
|
-
values_path =
|
402
|
+
values_path = bundle_path( 'values.yaml' )
|
398
403
|
return yaml_read( values_path )
|
399
404
|
end
|
400
405
|
|
@@ -418,7 +423,7 @@ module ::RSence
|
|
418
423
|
# Returns the source code of the javascript file +name+ in the 'js'
|
419
424
|
# subdirectory of the plugin bundle.
|
420
425
|
def read_js( js_name )
|
421
|
-
file_read(
|
426
|
+
file_read( bundle_path( js_name, 'js', '.js' ) )
|
422
427
|
end
|
423
428
|
|
424
429
|
# Deprecated name of +#read_js+
|
@@ -435,7 +440,7 @@ module ::RSence
|
|
435
440
|
if not ses.has_key?(:deps)
|
436
441
|
ses[:deps] = []
|
437
442
|
end
|
438
|
-
path =
|
443
|
+
path = bundle_path( js_name, 'js', '.js' )
|
439
444
|
unless ses[:deps].include?( path )
|
440
445
|
ses[:deps].push( path )
|
441
446
|
return file_read( path )
|