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,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