nitro 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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