nitro 0.1.2

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 (119) hide show
  1. data/AUTHORS +8 -0
  2. data/ChangeLog +1546 -0
  3. data/LICENCE +32 -0
  4. data/README +278 -0
  5. data/RELEASES +7 -0
  6. data/Rakefile +79 -0
  7. data/bin/cluster.rb +219 -0
  8. data/doc/architecture.txt +28 -0
  9. data/doc/bugs.txt +7 -0
  10. data/doc/css.txt +20 -0
  11. data/doc/ideas.txt +120 -0
  12. data/doc/pg.txt +47 -0
  13. data/doc/svn.txt +82 -0
  14. data/doc/todo.txt +30 -0
  15. data/etc/new-project.rb +18 -0
  16. data/examples/simple/README +15 -0
  17. data/examples/simple/app.rb +31 -0
  18. data/examples/simple/conf/apache.conf +100 -0
  19. data/examples/simple/conf/config.rb +89 -0
  20. data/examples/simple/conf/debug-config.rb +53 -0
  21. data/examples/simple/conf/live-config.rb +48 -0
  22. data/examples/simple/conf/overrides.rb +9 -0
  23. data/examples/simple/conf/requires.rb +51 -0
  24. data/examples/simple/ctl +32 -0
  25. data/examples/simple/env.rb +33 -0
  26. data/examples/simple/install.rb +12 -0
  27. data/examples/simple/lib/articles/entities.rb +35 -0
  28. data/examples/simple/lib/articles/lc-en.rb +36 -0
  29. data/examples/simple/lib/articles/methods.rb +55 -0
  30. data/examples/simple/lib/articles/part.rb +58 -0
  31. data/examples/simple/logs/access_log +2 -0
  32. data/examples/simple/logs/apache.log +3 -0
  33. data/examples/simple/logs/app.log +1 -0
  34. data/examples/simple/logs/events.log +1 -0
  35. data/examples/simple/root/add-article.sx +15 -0
  36. data/examples/simple/root/article-form.ss +20 -0
  37. data/examples/simple/root/comments-form.ss +16 -0
  38. data/examples/simple/root/comments.si +30 -0
  39. data/examples/simple/root/index.sx +44 -0
  40. data/examples/simple/root/shader/shader.xsl +100 -0
  41. data/examples/simple/root/shader/style.css +9 -0
  42. data/examples/simple/root/view-article.sx +30 -0
  43. data/examples/tiny/app.rb +30 -0
  44. data/examples/tiny/conf/apache.conf +100 -0
  45. data/examples/tiny/conf/config.rb +67 -0
  46. data/examples/tiny/conf/requires.rb +40 -0
  47. data/examples/tiny/ctl +31 -0
  48. data/examples/tiny/logs/access_log +9 -0
  49. data/examples/tiny/logs/apache.log +9 -0
  50. data/examples/tiny/root/index.sx +35 -0
  51. data/lib/n/app/cluster.rb +219 -0
  52. data/lib/n/app/cookie.rb +86 -0
  53. data/lib/n/app/filters/autologin.rb +50 -0
  54. data/lib/n/app/fragment.rb +67 -0
  55. data/lib/n/app/handlers.rb +120 -0
  56. data/lib/n/app/handlers/code-handler.rb +184 -0
  57. data/lib/n/app/handlers/page-handler.rb +612 -0
  58. data/lib/n/app/request-part.rb +59 -0
  59. data/lib/n/app/request.rb +653 -0
  60. data/lib/n/app/script.rb +398 -0
  61. data/lib/n/app/server.rb +53 -0
  62. data/lib/n/app/session.rb +224 -0
  63. data/lib/n/app/user.rb +47 -0
  64. data/lib/n/app/webrick-servlet.rb +213 -0
  65. data/lib/n/app/webrick.rb +70 -0
  66. data/lib/n/application.rb +187 -0
  67. data/lib/n/config.rb +31 -0
  68. data/lib/n/db.rb +217 -0
  69. data/lib/n/db/README +232 -0
  70. data/lib/n/db/connection.rb +369 -0
  71. data/lib/n/db/make-release.sh +26 -0
  72. data/lib/n/db/managed.rb +235 -0
  73. data/lib/n/db/mixins.rb +282 -0
  74. data/lib/n/db/mysql.rb +342 -0
  75. data/lib/n/db/psql.rb +378 -0
  76. data/lib/n/db/tools.rb +110 -0
  77. data/lib/n/db/utils.rb +99 -0
  78. data/lib/n/events.rb +118 -0
  79. data/lib/n/l10n.rb +22 -0
  80. data/lib/n/logger.rb +33 -0
  81. data/lib/n/macros.rb +53 -0
  82. data/lib/n/mixins.rb +46 -0
  83. data/lib/n/parts.rb +154 -0
  84. data/lib/n/properties.rb +194 -0
  85. data/lib/n/server.rb +61 -0
  86. data/lib/n/server/PLAYBACK.txt +8 -0
  87. data/lib/n/server/RESEARCH.txt +13 -0
  88. data/lib/n/server/filter.rb +77 -0
  89. data/lib/n/shaders.rb +167 -0
  90. data/lib/n/sitemap.rb +188 -0
  91. data/lib/n/std.rb +69 -0
  92. data/lib/n/sync/clc.rb +108 -0
  93. data/lib/n/sync/handler.rb +221 -0
  94. data/lib/n/sync/server.rb +170 -0
  95. data/lib/n/tools/README +11 -0
  96. data/lib/n/ui/date-select.rb +74 -0
  97. data/lib/n/ui/pager.rb +187 -0
  98. data/lib/n/ui/popup.rb +45 -0
  99. data/lib/n/ui/select.rb +41 -0
  100. data/lib/n/ui/tabs.rb +34 -0
  101. data/lib/n/utils/array.rb +92 -0
  102. data/lib/n/utils/cache.rb +144 -0
  103. data/lib/n/utils/gfx.rb +108 -0
  104. data/lib/n/utils/hash.rb +148 -0
  105. data/lib/n/utils/html.rb +147 -0
  106. data/lib/n/utils/http.rb +98 -0
  107. data/lib/n/utils/mail.rb +28 -0
  108. data/lib/n/utils/number.rb +31 -0
  109. data/lib/n/utils/pool.rb +66 -0
  110. data/lib/n/utils/string.rb +297 -0
  111. data/lib/n/utils/template.rb +38 -0
  112. data/lib/n/utils/time.rb +91 -0
  113. data/lib/n/utils/uri.rb +193 -0
  114. data/lib/xsl/base.xsl +205 -0
  115. data/lib/xsl/ce.xsl +30 -0
  116. data/lib/xsl/localization.xsl +23 -0
  117. data/lib/xsl/xforms.xsl +26 -0
  118. data/test/run.rb +95 -0
  119. metadata +187 -0
@@ -0,0 +1,398 @@
1
+ # = Base class for scripts.
2
+ #
3
+ # Typically a handler evaluates a script. The base class describing
4
+ # a script is defined here.
5
+ # A generalized fragment caching system is also defined.
6
+ #
7
+ # see handlers/page-handler::PageScript for more information.
8
+ #
9
+ # TODO:
10
+ # - convert all methods to __ to avoid collisions.
11
+ #
12
+ # code:
13
+ # George Moschovitis <gm@navel.gr>
14
+ #
15
+ # (c) 2003 Navel, all rights reserved.
16
+ # $Id: script.rb 71 2004-10-18 10:50:22Z gmosx $
17
+
18
+ require "fileutils"
19
+
20
+ require "n/utils/cache"
21
+ require "n/app/fragment"
22
+
23
+ module N
24
+
25
+ # = ScriptExitException
26
+ #
27
+ # Raise this Exception in your Script to avoid processing.
28
+ # Typicaly used in request.redirect scenarios!
29
+ #
30
+ class ScriptExitException < Exception; end
31
+
32
+ end # module
33
+
34
+ module N; module App
35
+
36
+ # = Script
37
+ #
38
+ # Base class for scripts. Typically a handler evaluates a script.
39
+ # The base class describing a script is defined here.
40
+ # A generalized fragment caching system is also defined.
41
+ #
42
+ # see handlers/page-handler::PageScript for more information.
43
+ #--
44
+ # no need to prepend __ to the attributes! (@ is prepended)
45
+ #++
46
+ #
47
+ class Script
48
+ # gmosx: it would be a good idea to make this a singleton, but we
49
+ # had some problems when redefining the class when monitor_scripts
50
+ # is enabled. investigate this!
51
+ # include Singleton
52
+
53
+ # the full path to the actual script file
54
+ attr_accessor :path
55
+
56
+ # the sub scripts.
57
+ attr_accessor :sub_scripts
58
+
59
+ attr_accessor :key
60
+
61
+ # is this script cacheable? NONE, SERVER, DOWNSTREAM, CLIENT
62
+ attr_accessor :cacheability
63
+
64
+ def initialize(path)
65
+ @path = "#$root_dir/#{path}"
66
+
67
+ # gmosx, INVESTIGATE: createtime == filemtime ?
68
+
69
+ # the creation time for this script-class
70
+ @create_time = Time.now
71
+
72
+ # when the filename was last modified
73
+ @file_mtime = File.mtime(@path).to_i
74
+
75
+ # sub-scripts set: a set of files this script depends on.
76
+ # We use a hash to implement a set.
77
+ @sub_scripts = N::SafeArray.new
78
+
79
+ # a cache for the script outputs (fragments). Keeps multiple revisions
80
+ # of the script output according to user, access rights etc.
81
+ # must be thread safe because it is shared accross threads.
82
+ #
83
+ # gmosx: DONT DEPRECATE THIS! if we switch to FastCGI, perhaps
84
+ # this will be needed!
85
+ #
86
+ # DISK CACHING IS SLOW!
87
+ #
88
+ @fragment_cache = N::LRUCache.new(1000)
89
+
90
+ __init()
91
+ end
92
+
93
+ # This method is called at compile time to perform
94
+ # additional initialization.
95
+ #
96
+ def __init
97
+ end
98
+
99
+ # This method is called before rendering to perform
100
+ # additional initialization.
101
+ #
102
+ def __init_render(request)
103
+ # nop
104
+ end
105
+
106
+ # Tag for this request
107
+ #
108
+ def __tag(request)
109
+ # gmosx: dont return nil!
110
+ return ""
111
+ end
112
+
113
+ # Recursively calculate tag.
114
+ #
115
+ def __calc_tag(request)
116
+ tag = __tag(request)
117
+
118
+ if @sub_scripts
119
+ for script in @sub_scripts
120
+ tag << script.__calc_tag(request)
121
+ end
122
+ end
123
+
124
+ return tag
125
+ end
126
+
127
+ # Calculate LastModified for HTTP1.1 caching
128
+ # Return the last modified time for this script.
129
+ #
130
+ def __lm(request)
131
+ return nil
132
+ end
133
+
134
+ # Calculate LastModified for HTTP1.1 caching
135
+ # takes into account all subscripts! also takes into account
136
+ # the script file modification
137
+ #
138
+ def __calc_lm(request)
139
+ unless lm = __lm(request)
140
+ lm = @file_mtime
141
+ else
142
+ lm = @file_mtime if @file_mtime > lm
143
+ end
144
+
145
+ if @sub_scripts
146
+ for script in @sub_scripts
147
+ if slm = script.__calc_lm(request)
148
+ unless lm
149
+ lm = slm
150
+ else
151
+ lm = slm if slm > lm
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ return lm
158
+ end
159
+
160
+ # Calculates the ETag fof HTTP1.1 caching. This etag is typically
161
+ # used in the downstream, so we can be VERY granular :-) ie
162
+ # we can even encode a user id!
163
+ #
164
+ # Coded by top level scripts only!
165
+ # Typically combines __tag and __last_modified
166
+ #
167
+ def __etag(request)
168
+ return "#{__calc_lm(request)}#{__calc_tag(request)}#{request.tag}" # .hash.to_s
169
+ end
170
+
171
+ # Is this script cacheable for this request?
172
+ #
173
+ def __cache?(request)
174
+ # By default if lm is overriden the page is cacheable
175
+ return __lm(request)
176
+ end
177
+
178
+ #---------------------------------------------------------------------
179
+ # Caching logic:
180
+ #
181
+
182
+ # gmosx, DEPRECATED: the following caching methods are deprecated!
183
+ # they are still used by rx handler though!
184
+
185
+ # clear the fragment_cache
186
+ #
187
+ def __cache_clear
188
+ @fragment_cache.clear
189
+ end
190
+
191
+ # get a fragment from the fragment cache in a thread safe manner.
192
+ #
193
+ # Output:
194
+ # the fragment object encapsulating the output of this script.
195
+ #
196
+ def __cache_get(key)
197
+ return @fragment_cache[key]
198
+ end
199
+
200
+ # add a new fragment in the fragment cache in a thread safe manner.
201
+ # encapsulate the fragment text (== body) in a fragment object.
202
+ #
203
+ def __cache_put(key, fragment)
204
+ @fragment_cache[key] = fragment
205
+ end
206
+
207
+ #--------------------------------------------------------------------------
208
+ # Rendering logic:
209
+
210
+ # renders the script as html output to be send to the
211
+ # borwser.
212
+ # the output of this script is the script fragment.
213
+ # this method is constructed dynamically by the handler.
214
+ #
215
+ # Design:
216
+ #
217
+ # the parameters to this method are visible to page scripts.
218
+ # in order to avoid namespace pollution and dangerous bugs in the
219
+ # scripts we prepend an underscore to differentiate them. n1 used
220
+ # @variables (class attributes) but we believe they where thread-unsafe.
221
+ #
222
+ def __render(request)
223
+ end
224
+
225
+ # Dynamically include ("inject") a subpage (fragment) in this page.
226
+ # Dynamic means at run-time.
227
+ #
228
+ def __inject(url, request)
229
+ return ""
230
+ end
231
+
232
+ # Dynamically include ("inject") a subpage (fragment) in this page.
233
+ # Dynamic means at run-time.
234
+
235
+ def __include(url, request)
236
+ return ""
237
+ end
238
+
239
+ def __create_time
240
+ return @create_time
241
+ end
242
+
243
+ def __file_mtime
244
+ return @file_mtime
245
+ end
246
+
247
+ def __path
248
+ return @path
249
+ end
250
+
251
+ #--------------------------------------------------------------------------
252
+ # Actions:
253
+
254
+ def admin?(request)
255
+ return false;
256
+ end
257
+
258
+ # Encodes an action url to the same page.
259
+ # Params is almost always != nil, no need to optimize the case.
260
+ #
261
+ def __action(request, params = nil)
262
+ if request.parameters.empty?
263
+ return "#{request.translated_uri}?#{params}"
264
+ else
265
+ return "#{request.translated_uri}?#{request.query_string};#{params}"
266
+ end
267
+ end
268
+ alias_method :_a, :__action
269
+
270
+ #--------------------------------------------------------------------------
271
+ # Hooks:
272
+
273
+ # executed prior to script evaluation, even for cached fragments!
274
+ # not used yet.
275
+ #
276
+ def __pre_evaluate(request)
277
+ end
278
+
279
+ # executed after script evaluation, even for cached fragments!
280
+ # not used yet.
281
+
282
+ def __post_evaluate(request)
283
+ end
284
+
285
+ # Pre-render hook. NOT executed for cached fragments
286
+ # not used yet.
287
+ #
288
+ # Returns:
289
+ # text that is prepended to the request, by default the EMPTY_STRING
290
+ #
291
+ def __pre_render(request)
292
+ return EMPTY_STRING
293
+ end
294
+
295
+ # Post-render hook. NOT executed for cached fragments.
296
+ # not used yet.
297
+ #
298
+ # Returns:
299
+ # text that is appended to the request, by default the EMPTY_STRING
300
+ #
301
+ def __post_render(request)
302
+ return EMPTY_STRING
303
+ end
304
+
305
+ # Calculate a hash modifier (flag) to differentiate caching according
306
+ # to user roles or other dynamic conditions. The calculated flag
307
+ # is appended to the fragmant hash.
308
+ #
309
+ # Design:
310
+ # use this separate method to allow the top level page to
311
+ # collect the flags for all sub-pages and build
312
+ # a super-flag.
313
+ #
314
+ def cache_flag(request)
315
+ return Fragment::ADMIN_FLAG if admin?(request)
316
+ end
317
+
318
+ # enable fragment caching for this script?
319
+ # to avoid storing in the cache uncacheable fragments
320
+ #
321
+ def cache?(request)
322
+ # gmosx: AAAAAAAAARGHHH!!! NASTY keep this false!
323
+ # to save memory!
324
+ return false
325
+ end
326
+
327
+ # is the output of the script (the fragment) valid for this request?
328
+ # used for cache invalidation calculations. By default returns false.
329
+ #
330
+ # Input:
331
+ # __fragment_key: the server automatically generates a fragment_key (typically
332
+ # the request.real_path) and passes this to this methods for further
333
+ # customization. The key passed is the base key, the method is responsible to
334
+ # build the final key (taking user roles, etc into account).
335
+ # request: used to customize the fragment_key for this request.
336
+ # customized fragment_keys denote request classes.
337
+ #
338
+ # Output:
339
+ # is the fragment valid for this request?
340
+ #
341
+ # Side-effects:
342
+ # WARNING: the method potentially modifies __fragment_key!
343
+ #
344
+ def cache_valid?(fragment, request)
345
+ return false
346
+ end
347
+
348
+ # authorize access to this script ?
349
+ #
350
+ def __authorize?(request)
351
+ return true
352
+ end
353
+
354
+ # get the shader to use for this script
355
+ #
356
+ def __shader(request)
357
+ return nil
358
+ end
359
+
360
+ # force a logged-in user for this page.
361
+ # implemented like the n1-version to avoid checking everytime
362
+ # for login, use the if __force method.
363
+ #
364
+ def __force_login(request)
365
+ if request.session["USER"].anonymous?
366
+ request.redirect("/id/login.sx?_go=#{request.uri}")
367
+ return false
368
+ end
369
+ return true
370
+ end
371
+
372
+ # --------------------------------------------------------------------
373
+ # Macros
374
+ # TODO: create more usefull macros for admin?/cache_valid? etc.
375
+
376
+ # Sets cache?() to return true
377
+ #
378
+ def self.enable_cache!
379
+ class_eval %{
380
+ def __cache?(request)
381
+ return true
382
+ end
383
+ }
384
+ end
385
+
386
+ # Evals a standard admin?() method.
387
+ #
388
+ def self.admin_role(role)
389
+ class_eval %{
390
+ def admin?(request)
391
+ return request.user.role?("#{role}")
392
+ end
393
+ }
394
+ end
395
+
396
+ end # class
397
+
398
+ end; end # module
@@ -0,0 +1,53 @@
1
+ # = AppServer
2
+ #
3
+ # code:: gmosx
4
+ #
5
+ # (c) 2004 Navel, all rights reserved.
6
+ # $Id: server.rb 89 2004-10-20 12:55:58Z gmosx $
7
+
8
+ require "drb"
9
+
10
+ require "n/application"
11
+ require "n/server"
12
+ require "n/app/session"
13
+
14
+ module N; module App
15
+
16
+ # = AppServerMixin
17
+ #
18
+ module ServerMixin
19
+
20
+ def initialize_app
21
+ if $drb_state
22
+ # Cluster
23
+ $lm = N::Cluster::Slm.new($drb_lm_server, "druby://:8000")
24
+ $sessions = DRbObject.new(nil, $drb_sessions_cluster)
25
+ else
26
+ $lm = N::SafeHash.new
27
+ $sessions = N::App::SessionManager.new
28
+ end
29
+
30
+ # initialize app
31
+ initialize_sitemap()
32
+ initialize_shaders()
33
+ initialize_events()
34
+ end
35
+
36
+ end
37
+
38
+ # = AppServer
39
+ #
40
+ # The Application Server. Handles dynamic requests in a web application.
41
+ # Dont keepalive (or use a VERY SMALL keepalive). Typically this server
42
+ # is used along with a standars http server that handles other resources.
43
+ #
44
+ class Server < N::Server
45
+ include N::App::ServerMixin
46
+
47
+ def initialize(name = "AppServer")
48
+ super
49
+ initialize_app()
50
+ end
51
+ end
52
+
53
+ end; end # module