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,187 @@
1
+ # = Pager
2
+ #
3
+ # code: gmosx
4
+ #
5
+ # (c) 2004 Navel, all rights reserved.
6
+ # $Id: pager.rb 71 2004-10-18 10:50:22Z gmosx $
7
+
8
+ module N; module UI
9
+
10
+ # === Design:
11
+ #
12
+ # The new version is carefully designed for scaleability. It stores
13
+ # only the items for one page.
14
+ # The name parameter is needed, multiple pagers can coexist in
15
+ # a single page. Unlike the v1/v2 pagers this pager leverages the
16
+ # SQL LIMIT option to optimize database interaction.
17
+ #
18
+ # The pager does not extend Array (it includes an Array instead) to
19
+ # avoid a concat() in the initialization step.
20
+ #
21
+ # TODO:
22
+ # - Extend from array? (would be more elegant)
23
+ #
24
+ # === Example:
25
+ #
26
+ # INVESTIGATE:
27
+ # mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name
28
+ # -> WHERE id > 100 LIMIT 10;
29
+ # mysql> SELECT FOUND_ROWS();
30
+ #
31
+ class Pager < Array
32
+ attr_accessor :name, :idx, :page, :page_count
33
+ # total count of items
34
+ attr_accessor :total_count
35
+ # page items
36
+ attr_accessor :page_items
37
+ # read needed variables from the request.
38
+ attr_accessor :request
39
+
40
+ def initialize(name, request, items_per_page, items = nil)
41
+ raise "items_per_page should be > 0" unless items_per_page > 0
42
+
43
+ @request, @name = request, name
44
+ @page = request.get("__pg#{@name}", 1)
45
+ @items_per_page = items_per_page
46
+ @start_idx = (@page - 1) * items_per_page
47
+
48
+ if items
49
+ set(items.size())
50
+ # gmosx, FIXME: not exactly what i want!
51
+ items.slice!(@start_idx, @items_per_page)
52
+ end
53
+ end
54
+
55
+ def set(total_count)
56
+ @total_count = total_count
57
+ @page_count = (@total_count.to_f() / @items_per_page).ceil()
58
+ end
59
+
60
+ def first_page
61
+ return 1
62
+ end
63
+
64
+ def last_page
65
+ return @page_count
66
+ end
67
+
68
+ def previous_page
69
+ return [@page - 1, 1].max()
70
+ end
71
+
72
+ def next_page
73
+ return [@page + 1, @page_count].min()
74
+ end
75
+
76
+ # Iterator
77
+ #
78
+ def each(&block)
79
+ @page_items.each(&block)
80
+ end
81
+
82
+ # Iterator
83
+ # Returns 1-based index.
84
+ #
85
+ def each_with_index
86
+ idx = @start_idx
87
+ for item in @page_items
88
+ yield(idx + 1, item)
89
+ idx += 1
90
+ end
91
+ end
92
+
93
+ def empty?
94
+ return @items.empty?
95
+ end
96
+
97
+ def size
98
+ return @items.size()
99
+ end
100
+
101
+ # Returns the range of the current page.
102
+ #
103
+ def page_range
104
+ s = @idx
105
+ e = [@idx + @items_per_page - 1, all_total_count].min
106
+
107
+ return [s, e]
108
+ end
109
+
110
+ # Override if needed.
111
+ #
112
+ def nav_range
113
+ # effective range = 10 pages.
114
+ s = [@page - 5, 1].max()
115
+ e = [@page + 9, @page_count].min()
116
+
117
+ d = 9 - (e - s)
118
+ e += d if d < 0
119
+
120
+ return (s..e)
121
+ end
122
+
123
+ # Override this method in your application
124
+ # if needed.
125
+ # TODO: better markup.
126
+ #
127
+ def navigation
128
+ nav = ""
129
+
130
+ unless @page == first_page()
131
+ nav << %{
132
+ <div class="first"><a href="#{target_uri(first_page())}">����</a></div>
133
+ <div class="previous"><a href="#{target_uri(previous_page())}">�����������</a></div>
134
+ }
135
+ end
136
+
137
+ unless @page == last_page()
138
+ nav << %{
139
+ <div class="last"><a href="#{target_uri(last_page())}">�����</a></div>
140
+ <div class="next"><a href="#{target_uri(next_page())}">�������</a></div>
141
+ }
142
+ end
143
+
144
+ nav << %{<ul>}
145
+
146
+ for i in nav_range()
147
+ if i == @page
148
+ nav << %{
149
+ <li class="active">#{i}</li>
150
+ }
151
+ else
152
+ nav << %{
153
+ <li><a href="#{target_uri(i)}">#{i}</a></li>
154
+ }
155
+ end
156
+ end
157
+
158
+ nav << %{</ul>}
159
+
160
+ return nav
161
+ end
162
+
163
+ # Create an appropriate SQL limit clause.
164
+ # Returns postgres/mysql compatible limit.
165
+ #
166
+ def sql_limit
167
+ if @start_idx > 0
168
+ return "LIMIT #{@items_per_page} OFFSET #{@start_idx}"
169
+ else
170
+ # gmosx: perhaps this is optimized ? naaaaaah...
171
+ return "LIMIT #{@items_per_page}"
172
+ end
173
+ end
174
+
175
+ # ------------------------------------------------------------------
176
+
177
+ # Generate the target URI.
178
+ #
179
+ def target_uri(page)
180
+ params = {"__pg#{@name}" => page}
181
+ return N::UriUtils.update_query_string(@request.uri, params)
182
+ end
183
+ private :target_uri
184
+
185
+ end
186
+
187
+ end; end # module
@@ -0,0 +1,45 @@
1
+ # = Popup
2
+ #
3
+ # code: gmosx
4
+ #
5
+ # (c) 2004 Navel, all rights reserved.
6
+ # $Id: popup.rb 71 2004-10-18 10:50:22Z gmosx $
7
+
8
+ module N; module UI
9
+
10
+ # = Popup
11
+ #
12
+ class Popup
13
+
14
+ # Emit the needed javascript.
15
+ # Alternatively use this code: <script src="/r/js/std.js">#{}</script>
16
+ #
17
+ def self.script
18
+ %[
19
+ function newWin(url, name, w, h, scroll) {
20
+ var pleft = (screen.width - w) / 2;
21
+ var ptop = (screen.height - h) / 2;
22
+ var settings = 'height=' + h + ',width=' + w + ',top=' + ptop + ',left=' + pleft + ',scrollbars=' + scroll + ',resizable';
23
+
24
+ win = window.open(url, name, settings);
25
+
26
+ return false;
27
+ }
28
+ ]
29
+ end
30
+
31
+ # gmosx: keep the leading / to be IE friendly.
32
+ #
33
+ def self.onclick(uri, width, height, title = "Popup", type="PAGE", options = "scrollbars=yes,resizable", container = "/p/glue/popup.sx")
34
+ %[javascript: var pwl = (screen.width - #{width}) / 2; var pwt = (screen.height - #{height}) / 2; window.open('#{container}?uri=#{uri};type=#{type}', '#{title}', 'width=#{width},height=#{height},top='+pwt+',left='+pwl+', #{options}'); return false"]
35
+ end
36
+
37
+ # gmosx: keep the leading / to be IE friendly.
38
+ #
39
+ def self.link(uri, width, height, link = "link", title = "Popup", type="PAGE", options = "scrollbars=yes,resizable", container = "/p/glue/popup.sx")
40
+ %[<a href="#" onclick="#{self.onclick(uri, width, height, title, type, options, container)}">#{link}</a>]
41
+ end
42
+ end
43
+
44
+ end; end # module
45
+
@@ -0,0 +1,41 @@
1
+ # = Select
2
+ #
3
+ # code: gmosx
4
+ #
5
+ # (c) 2004 Navel, all rights reserved.
6
+ # $Id: select.rb 71 2004-10-18 10:50:22Z gmosx $
7
+
8
+ module N; module UI
9
+
10
+ class Select
11
+
12
+ # Generalized select. Dont create the enclosing selects to
13
+ # be flexible.
14
+ # Example:
15
+ #
16
+ # <select name="param" onchange="submit()">
17
+ # #{N::UI::Select.render_options(
18
+ # paramvalue,
19
+ # [-1, 1, 2, 3],
20
+ # ["-- Enter Options --", "Man", "Woman", "None"]
21
+ # )}
22
+ # </select>
23
+ #
24
+ def self.render_options(paramvalue, values, options)
25
+ str = ""
26
+
27
+ values.each_with_index { |val, idx|
28
+ if paramvalue == val
29
+ str << %{<option value="#{val}" selected="1">#{options[idx]}</option>}
30
+ else
31
+ str << %{<option value="#{val}">#{options[idx]}</option>}
32
+ end
33
+ }
34
+
35
+ return str
36
+ end
37
+
38
+ end
39
+
40
+ end; end # module
41
+
@@ -0,0 +1,34 @@
1
+ # = Tabs
2
+ #
3
+ # code: gmosx
4
+ #
5
+ # (c) 2004 Navel, all rights reserved.
6
+ # $Id: tabs.rb 71 2004-10-18 10:50:22Z gmosx $
7
+
8
+ module N; module UI
9
+
10
+ # Render a tabs bar
11
+ #
12
+ # Example:
13
+ #
14
+ # #{N::UI.tabs(request,
15
+ # ["Page1", "Page2", "Page3"]
16
+ # }
17
+ #
18
+ def self.tabs(request, options, param)
19
+ tabs = []
20
+
21
+ selected = request.get(param, 0)
22
+
23
+ options.each_with_index { |opt, idx|
24
+ if idx == selected
25
+ tabs << %|<strong>#{opt}</strong>|
26
+ else
27
+ tabs << %|<a href="#{request.expand_uri(param => idx)}">#{opt}</a>|
28
+ end
29
+ }
30
+
31
+ return %|<div class="tabs">#{tabs.join('<span class="sep">|</span>')}</div>|
32
+ end
33
+
34
+ end; end # module
@@ -0,0 +1,92 @@
1
+ # = General arrays utilities collection
2
+ #
3
+ # === Design:
4
+ #
5
+ # Implement as a module to avoid class polution. You can still Ruby's
6
+ # advanced features to include the module in your class.
7
+ # Passing the object to act upon allows to check for nil, which isn't
8
+ # possible if you use self.
9
+ #
10
+ # code:: gmosx, ekarak
11
+ #
12
+ # (c) 2002-2003 Navel, all rights reserved.
13
+ # $Id: array.rb 71 2004-10-18 10:50:22Z gmosx $
14
+
15
+ require "sync"
16
+
17
+ module N
18
+
19
+ # == SafeArray
20
+ #
21
+ # A thread-safe array. We use a sync object instead of a mutex,
22
+ # because it is re-entrant.
23
+ # An exclusive lock is needed when writing, a shared lock IS NEEDED
24
+ # when reading
25
+
26
+ class SafeArray < Array
27
+
28
+ attr :sync
29
+
30
+ # gmosx: delegator is not used.
31
+
32
+ def initialize(delegator = nil)
33
+ @sync = ::Sync.new()
34
+ end
35
+
36
+ def << (value)
37
+ return @sync.synchronize(::Sync::SH) {
38
+ super
39
+ }
40
+ end
41
+
42
+ def delete_if(&block)
43
+ return @sync.synchronize(::Sync::SH) {
44
+ super
45
+ }
46
+ end
47
+
48
+ def [](key)
49
+ return @sync.synchronize(::Sync::SH) {
50
+ super
51
+ }
52
+ end
53
+
54
+ def []=(key, value)
55
+ return @sync.synchronize(::Sync::EX) {
56
+ super
57
+ }
58
+ end
59
+
60
+ def delete(key)
61
+ return @sync.synchronize(::Sync::EX) {
62
+ super
63
+ }
64
+ end
65
+
66
+ def clear
67
+ @sync.synchronize(::Sync::EX) {
68
+ super
69
+ }
70
+ end
71
+
72
+ def size
73
+ return @sync.synchronize(::Sync::SH) {
74
+ super
75
+ }
76
+ end
77
+
78
+ def shift
79
+ return @sync.synchronize(::Sync::EX) {
80
+ super
81
+ }
82
+ end
83
+
84
+ def unshift(el)
85
+ return @sync.synchronize(::Sync::EX) {
86
+ super
87
+ }
88
+ end
89
+
90
+ end # SafeArray
91
+
92
+ end # module
@@ -0,0 +1,144 @@
1
+ # = Cache
2
+ #
3
+ # Various caching mechanisms.
4
+ #
5
+ # code:
6
+ # George Moschovitis <gm@navel.gr>
7
+ # Anastasios Koutoumanos <ak@navel.gr>
8
+ #
9
+ # (c) 2004 Navel, all rights reserved.
10
+ # $Id: cache.rb 71 2004-10-18 10:50:22Z gmosx $
11
+
12
+ module N;
13
+
14
+ # = LRUCache
15
+ #
16
+ # A cache utilizing a simple LRU (Least Recently Used) policy.
17
+ # The items managed by this cache must respond to the #key method.
18
+ # Attempts to optimize reads rather than inserts!
19
+ #
20
+ # LRU semantics are enforced by inserting the items in a queue.
21
+ # The lru item is always at the tail. Two special sentinels
22
+ # (head, tail) are used to simplify (?) the code.
23
+ #
24
+ class LRUCache < Hash
25
+
26
+ # Mix this in your class to make LRU-managable.
27
+ #
28
+ module Item
29
+ attr_accessor :lru_key, :lru_prev, :lru_next
30
+ end
31
+
32
+ # head-tail sentinels
33
+ #
34
+ class Sentinel; include Item; end
35
+
36
+ # the maximum number of items in the cache
37
+ attr_accessor :max_items
38
+
39
+ # the head sentinel
40
+ attr :head
41
+ # the tail sentinel, tail.prev points to the lru item.
42
+ attr :tail
43
+
44
+ #
45
+ #
46
+ def initialize(max_items)
47
+ @max_items = max_items
48
+ lru_clear()
49
+ end
50
+
51
+ # Lookup an item in the cache
52
+ #
53
+ def [](key)
54
+ if item = super
55
+ return lru_touch(item)
56
+ end
57
+ end
58
+
59
+ # The inserted item is considered mru!
60
+ #
61
+ def []=(key, item)
62
+ item = super
63
+ item.lru_key = key
64
+ lru_insert(item)
65
+ end
66
+
67
+ # Delete an item from the cache
68
+ #
69
+ def delete(key)
70
+ if item = super
71
+ lru_delete(item)
72
+ end
73
+ end
74
+
75
+ # Clear the cache
76
+ #
77
+ def clear
78
+ super
79
+ lru_clear()
80
+ end
81
+
82
+ # The first (mru) element in the cache
83
+ #
84
+ def first
85
+ @head.lru_next
86
+ end
87
+
88
+ # The last (lru) element in the cache
89
+ #
90
+ def last
91
+ @tail.lru_prev
92
+ end
93
+ alias_method :lru, :last
94
+
95
+ private
96
+
97
+ # Delete an item from the lru list.
98
+ #
99
+ def lru_delete(item)
100
+ lru_join(item.lru_prev, item.lru_next)
101
+ return item
102
+ end
103
+
104
+ # Join two items in the lru list
105
+ # Return y to allow for chaining
106
+ #
107
+ def lru_join(x, y)
108
+ x.lru_next = y
109
+ y.lru_prev = x
110
+ return y
111
+ end
112
+
113
+ # Append a child item to a parent item in the lru list
114
+ # (Re)inserts the child in the list.
115
+ #
116
+ def lru_append(parent, child)
117
+ lru_join(child, parent.lru_next)
118
+ lru_join(parent, child)
119
+ end
120
+
121
+ # Insert an item
122
+ #
123
+ def lru_insert(item)
124
+ delete(last.lru_key) if size() > @max_items
125
+ lru_append(@head, item)
126
+ end
127
+
128
+ # Touch an item, make mru!
129
+ # Returns the item
130
+ #
131
+ def lru_touch(item)
132
+ lru_append(@head, lru_delete(item))
133
+ end
134
+
135
+ # Clear the lru
136
+ #
137
+ def lru_clear
138
+ @head = Sentinel.new
139
+ @tail = Sentinel.new
140
+ lru_join(@head, @tail)
141
+ end
142
+ end
143
+
144
+ end # module