nitro 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +4 -1
- data/ChangeLog +290 -7
- data/README +3 -3
- data/RELEASES +94 -0
- data/Rakefile +7 -7
- data/benchmark/og/bench.rb +11 -10
- data/{ChangeLog.1 → doc/ChangeLog.1} +0 -0
- data/doc/apache.txt +9 -0
- data/doc/architecture.txt +1 -27
- data/doc/bugs.txt +11 -4
- data/doc/config.txt +22 -0
- data/doc/og_config.txt +35 -0
- data/doc/og_tutorial.txt +595 -0
- data/doc/tutorial.txt +22 -0
- data/examples/blog/conf/apache.conf +30 -0
- data/examples/blog/conf/lhttpd.conf +2 -2
- data/examples/blog/lib/blog/controller.rb +11 -2
- data/examples/blog/log/apache.error_log +5528 -0
- data/examples/blog/root/fcgi.rb +1 -1
- data/examples/blog/run.rb +9 -3
- data/examples/flash/run.rb +2 -2
- data/examples/no_xsl_blog/conf/apache.conf +30 -0
- data/examples/no_xsl_blog/conf/lhttpd.conf +1 -1
- data/examples/no_xsl_blog/lib/blog/controller.rb +2 -2
- data/examples/no_xsl_blog/log/apache.error_log +68 -0
- data/examples/no_xsl_blog/root/fcgi.rb +2 -2
- data/examples/no_xsl_blog/run.rb +3 -3
- data/examples/og/run.rb +1 -1
- data/examples/tiny/conf/apache.conf +29 -4
- data/examples/tiny/conf/lhttpd.conf +1 -1
- data/examples/tiny/log/apache.error_log +30 -0
- data/examples/tiny/root/fcgi.rb +2 -2
- data/examples/tiny/root/index.xhtml +1 -1
- data/examples/tiny/run.rb +3 -2
- data/examples/wee_style/run.rb +7 -9
- data/examples/why_wiki/README +5 -0
- data/examples/why_wiki/run.rb +57 -0
- data/examples/why_wiki/wiki.yml +6 -0
- data/examples/wiki.yml +1 -0
- data/lib/glue/array.rb +14 -33
- data/lib/glue/hash.rb +32 -53
- data/lib/glue/pool.rb +9 -12
- data/lib/glue/property.rb +31 -9
- data/lib/nitro.rb +30 -8
- data/lib/nitro/adapters/cgi.rb +23 -3
- data/lib/nitro/adapters/webrick.rb +9 -3
- data/lib/nitro/builders/form.rb +21 -13
- data/lib/nitro/builders/rss.rb +20 -9
- data/lib/nitro/builders/table.rb +69 -10
- data/lib/nitro/builders/xhtml.rb +13 -4
- data/lib/nitro/component.rb +15 -0
- data/lib/nitro/conf.rb +4 -3
- data/lib/nitro/context.rb +22 -14
- data/lib/nitro/controller.rb +63 -5
- data/lib/nitro/dispatcher.rb +11 -6
- data/lib/nitro/output.rb +28 -0
- data/lib/nitro/render.rb +78 -59
- data/lib/nitro/request.rb +5 -1
- data/lib/nitro/runner.rb +20 -6
- data/lib/nitro/session.rb +89 -18
- data/lib/nitro/session/drb.rb +31 -0
- data/lib/nitro/session/drbserver.rb +71 -0
- data/lib/nitro/session/memory.rb +13 -0
- data/lib/nitro/simple.rb +7 -0
- data/lib/nitro/ui/date-select.rb +2 -5
- data/lib/nitro/ui/pager.rb +4 -4
- data/lib/nitro/ui/tabs.rb +2 -4
- data/lib/nitro/uri.rb +7 -4
- data/lib/og.rb +20 -12
- data/lib/og/adapter.rb +40 -13
- data/lib/og/adapters/filesys.rb +121 -0
- data/lib/og/adapters/mysql.rb +10 -5
- data/lib/og/adapters/oracle.rb +374 -0
- data/lib/og/adapters/psql.rb +10 -23
- data/lib/og/adapters/sqlite.rb +3 -3
- data/lib/og/backend.rb +2 -2
- data/lib/og/connection.rb +6 -6
- data/lib/og/database.rb +5 -5
- data/lib/og/enchant.rb +6 -2
- data/lib/og/meta.rb +56 -26
- data/lib/og/mock.rb +1 -1
- data/lib/og/typemacros.rb +23 -0
- data/lib/parts/content.rb +4 -10
- data/test/nitro/adapters/tc_cgi.rb +1 -1
- data/test/nitro/builders/tc_rss.rb +1 -1
- data/test/nitro/builders/tc_table.rb +30 -0
- data/test/nitro/tc_context.rb +4 -0
- data/test/nitro/tc_controller.rb +9 -2
- data/test/og/tc_filesys.rb +83 -0
- data/test/og/tc_meta.rb +55 -0
- data/test/tc_og.rb +115 -36
- data/vendor/README +11 -5
- data/vendor/breakpoint.rb +35 -38
- data/vendor/breakpoint_client.rb +119 -80
- data/vendor/composite_sexp_processor.rb +43 -0
- data/vendor/parse_tree.rb +745 -0
- data/vendor/sexp_processor.rb +453 -0
- metadata +34 -7
- data/examples/no_xsl_blog/conf/app.conf.rb +0 -47
data/lib/glue/hash.rb
CHANGED
@@ -1,22 +1,17 @@
|
|
1
|
-
# code:
|
2
1
|
# * George Moschovitis <gm@navel.gr>
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# $Id: hash.rb 202 2005-01-17 10:44:13Z gmosx $
|
2
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
+
# $Id: hash.rb 263 2005-02-23 13:45:08Z gmosx $
|
6
4
|
|
7
|
-
require
|
5
|
+
require 'sync'
|
8
6
|
|
9
|
-
module N
|
7
|
+
module N
|
10
8
|
|
11
|
-
# == SafeHash
|
12
|
-
#
|
13
9
|
# A thread-safe hash. We use a sync object instead of a mutex,
|
14
|
-
# because it is re-entrant.
|
15
|
-
#
|
16
|
-
# when reading
|
10
|
+
# because it is re-entrant. An exclusive lock is needed when
|
11
|
+
# writing, a shared lock IS NEEDED when reading
|
17
12
|
# uses the delegator pattern to allow for multiple
|
18
13
|
# implementations!
|
19
|
-
|
14
|
+
|
20
15
|
class SafeHash < Hash
|
21
16
|
attr :sync
|
22
17
|
|
@@ -27,63 +22,47 @@ class SafeHash < Hash
|
|
27
22
|
end
|
28
23
|
|
29
24
|
def [](key)
|
30
|
-
|
31
|
-
super
|
32
|
-
}
|
25
|
+
@sync.synchronize(::Sync::SH) { super }
|
33
26
|
end
|
34
27
|
|
35
28
|
def []=(key, value)
|
36
|
-
|
37
|
-
super
|
38
|
-
}
|
29
|
+
@sync.synchronize(::Sync::EX) { super }
|
39
30
|
end
|
40
31
|
|
41
32
|
def delete(key)
|
42
|
-
|
43
|
-
super
|
44
|
-
}
|
33
|
+
@sync.synchronize(::Sync::EX) { super }
|
45
34
|
end
|
46
35
|
|
47
36
|
def clear
|
48
|
-
@sync.synchronize(::Sync::EX) {
|
49
|
-
super
|
50
|
-
}
|
37
|
+
@sync.synchronize(::Sync::EX) { super }
|
51
38
|
end
|
52
39
|
|
53
40
|
def size
|
54
|
-
|
55
|
-
super
|
56
|
-
}
|
41
|
+
@sync.synchronize(::Sync::SH) { super }
|
57
42
|
end
|
58
43
|
|
59
44
|
def values
|
60
|
-
|
61
|
-
super
|
62
|
-
}
|
45
|
+
@sync.synchronize(::Sync::SH) { super }
|
63
46
|
end
|
64
47
|
|
65
48
|
def keys
|
66
|
-
|
67
|
-
super
|
68
|
-
}
|
49
|
+
@sync.synchronize(::Sync::SH) { super }
|
69
50
|
end
|
70
51
|
|
71
|
-
end
|
52
|
+
end
|
72
53
|
|
73
|
-
# == SafeHashDelegator
|
74
|
-
#
|
75
54
|
# A thread-safe hash. We use a sync object instead of a mutex,
|
76
|
-
# because it is re-entrant.
|
77
|
-
#
|
78
|
-
#
|
55
|
+
# because it is re-entrant. An exclusive lock is needed when
|
56
|
+
# writing, a shared lock IS NEEDED when reading.
|
57
|
+
#
|
58
|
+
# === Design
|
79
59
|
#
|
80
|
-
# Design:
|
81
60
|
# This class uses the delegator pattern. However we dont use rubys
|
82
61
|
# delegation facilities, they are more general and powerfull than we
|
83
62
|
# need here (and slower). Instead a custom (but simple) solution is
|
84
63
|
# used.
|
85
64
|
#
|
86
|
-
# Example
|
65
|
+
# === Example
|
87
66
|
#
|
88
67
|
# hash = SafeHashDelegator.new(Hash.new)
|
89
68
|
# hash = SafeHashDelegator.new(Hash.new)
|
@@ -96,20 +75,20 @@ class SafeHashDelegator < Hash
|
|
96
75
|
@sync = ::Sync.new
|
97
76
|
end
|
98
77
|
|
99
|
-
|
100
|
-
|
78
|
+
def [](key)
|
79
|
+
@sync.synchronize(::Sync::SH) {
|
101
80
|
@delegate[key]
|
102
81
|
}
|
103
|
-
|
82
|
+
end
|
104
83
|
|
105
|
-
|
106
|
-
|
84
|
+
def []=(key, value)
|
85
|
+
@sync.synchronize(::Sync::EX) {
|
107
86
|
@delegate[key] = value
|
108
87
|
}
|
109
|
-
|
88
|
+
end
|
110
89
|
|
111
90
|
def delete(key)
|
112
|
-
|
91
|
+
@sync.synchronize(::Sync::EX) {
|
113
92
|
@delegate.delete(key)
|
114
93
|
}
|
115
94
|
end
|
@@ -121,23 +100,23 @@ class SafeHashDelegator < Hash
|
|
121
100
|
end
|
122
101
|
|
123
102
|
def size
|
124
|
-
|
103
|
+
@sync.synchronize(::Sync::SH) {
|
125
104
|
@delegate.size()
|
126
105
|
}
|
127
106
|
end
|
128
107
|
|
129
108
|
def values
|
130
|
-
|
109
|
+
@sync.synchronize(::Sync::SH) {
|
131
110
|
@delegate.values()
|
132
111
|
}
|
133
112
|
end
|
134
113
|
|
135
114
|
def keys
|
136
|
-
|
115
|
+
@sync.synchronize(::Sync::SH) {
|
137
116
|
@delegate.keys()
|
138
117
|
}
|
139
118
|
end
|
140
119
|
|
141
|
-
end
|
120
|
+
end
|
142
121
|
|
143
|
-
end
|
122
|
+
end
|
data/lib/glue/pool.rb
CHANGED
@@ -1,21 +1,17 @@
|
|
1
|
-
# code:
|
2
1
|
# * George Moschovitis <gm@navel.gr>
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# $Id: pool.rb 202 2005-01-17 10:44:13Z gmosx $
|
2
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
+
# $Id: pool.rb 266 2005-02-28 14:50:48Z gmosx $
|
6
4
|
|
7
|
-
require
|
8
|
-
require
|
5
|
+
require 'thread'
|
6
|
+
require 'monitor'
|
9
7
|
|
10
8
|
module N
|
11
9
|
|
12
|
-
# = Pool
|
13
|
-
#
|
14
10
|
# Generalized object pool implementation. Implemented as a thread
|
15
11
|
# safe stack. Exclusive locking is needed both for push and pop.
|
16
12
|
#
|
17
13
|
# INVESTIGATE: Could use the SizedQueue/Queue.
|
18
|
-
|
14
|
+
|
19
15
|
class Pool < Array
|
20
16
|
include MonitorMixin
|
21
17
|
|
@@ -25,7 +21,7 @@ class Pool < Array
|
|
25
21
|
end
|
26
22
|
|
27
23
|
# Add, restore an object to the pool.
|
28
|
-
|
24
|
+
|
29
25
|
def push(obj)
|
30
26
|
synchronize do
|
31
27
|
super
|
@@ -34,7 +30,7 @@ class Pool < Array
|
|
34
30
|
end
|
35
31
|
|
36
32
|
# Obtain an object from the pool.
|
37
|
-
|
33
|
+
|
38
34
|
def pop
|
39
35
|
synchronize do
|
40
36
|
@cv.wait_while { empty? }
|
@@ -44,6 +40,7 @@ class Pool < Array
|
|
44
40
|
|
45
41
|
# Obtains an object, passes it to a block for processing
|
46
42
|
# and restores it to the pool.
|
43
|
+
|
47
44
|
def obtain
|
48
45
|
result = nil
|
49
46
|
|
@@ -60,4 +57,4 @@ class Pool < Array
|
|
60
57
|
|
61
58
|
end
|
62
59
|
|
63
|
-
end
|
60
|
+
end
|
data/lib/glue/property.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# * George Moschovitis <gm@navel.gr>
|
2
2
|
# * Michael Neumann <mneumann@ntecs.de>
|
3
3
|
# (c) 2004-2005 Navel, all rights reserved.
|
4
|
-
# $Id: property.rb
|
4
|
+
# $Id: property.rb 266 2005-02-28 14:50:48Z gmosx $
|
5
5
|
|
6
6
|
require 'glue/attribute'
|
7
7
|
require 'glue/array'
|
@@ -30,22 +30,35 @@ class Property
|
|
30
30
|
|
31
31
|
cattr_accessor :type_checking, false
|
32
32
|
|
33
|
-
#
|
33
|
+
# The symbol of the property.
|
34
34
|
|
35
35
|
attr_accessor :symbol
|
36
36
|
|
37
|
-
#
|
37
|
+
# The string representation of the symbol.
|
38
38
|
|
39
39
|
attr_accessor :name
|
40
40
|
|
41
|
-
#
|
41
|
+
# The class of the property.
|
42
42
|
|
43
43
|
attr_accessor :klass
|
44
|
-
|
45
|
-
#
|
44
|
+
|
45
|
+
# Additional metadata (like sql declaration, sql index, etc)
|
46
|
+
# Here is a list of predefined metadata:
|
47
|
+
#
|
48
|
+
# [+:reader+]
|
49
|
+
# create reader?
|
50
|
+
#
|
51
|
+
# [+:writer+]
|
52
|
+
# create writer?
|
53
|
+
#
|
54
|
+
# [+:sql_index+]
|
55
|
+
# create an sql index for the column this poperty maps to?
|
56
|
+
#
|
57
|
+
# You can use this mechanism to add your own, custom,
|
58
|
+
# metadata.
|
46
59
|
|
47
60
|
attr_accessor :meta
|
48
|
-
|
61
|
+
|
49
62
|
def initialize(symbol, klass, meta = {})
|
50
63
|
@symbol, @klass = symbol, klass
|
51
64
|
@meta = meta
|
@@ -124,6 +137,11 @@ module PropertyUtils
|
|
124
137
|
else
|
125
138
|
target.__props << prop
|
126
139
|
end
|
140
|
+
|
141
|
+
# Store the property in the :props_and_relations
|
142
|
+
# metadata array.
|
143
|
+
|
144
|
+
target.meta :props_and_relations, prop
|
127
145
|
|
128
146
|
# Precompile the property read/write methods
|
129
147
|
|
@@ -366,7 +384,7 @@ class Module
|
|
366
384
|
prop(klass, symbol, meta)
|
367
385
|
end
|
368
386
|
end
|
369
|
-
|
387
|
+
alias_method :property, :prop_accessor
|
370
388
|
|
371
389
|
# Attach metadata.
|
372
390
|
# Guard against duplicates, no need to keep order.
|
@@ -375,7 +393,11 @@ class Module
|
|
375
393
|
# gmosx: crappy implementation, recode.
|
376
394
|
#++
|
377
395
|
|
378
|
-
def meta(key, val)
|
396
|
+
def meta(key, *val)
|
397
|
+
val = val.first if val.size == 1
|
398
|
+
|
399
|
+
N::PropertyUtils.enchant(self)
|
400
|
+
|
379
401
|
self.module_eval %{
|
380
402
|
@@__meta[key] ||= []
|
381
403
|
@@__meta[key].delete_if { |v| val == v }
|
data/lib/nitro.rb
CHANGED
@@ -12,17 +12,11 @@
|
|
12
12
|
#
|
13
13
|
# * George Moschovitis <gm@navel.gr>
|
14
14
|
# (c) 2004-2005 Navel, all rights reserved.
|
15
|
-
# $Id: nitro.rb
|
15
|
+
# $Id: nitro.rb 266 2005-02-28 14:50:48Z gmosx $
|
16
16
|
|
17
17
|
require 'glue'
|
18
18
|
require 'glue/logger'
|
19
19
|
|
20
|
-
require 'nitro/context'
|
21
|
-
require 'nitro/dispatcher'
|
22
|
-
require 'nitro/render'
|
23
|
-
require 'nitro/conf'
|
24
|
-
require 'nitro/runner'
|
25
|
-
|
26
20
|
# Define Nitro namespace.
|
27
21
|
|
28
22
|
module Nitro
|
@@ -33,10 +27,38 @@ module Nitro
|
|
33
27
|
|
34
28
|
# The version.
|
35
29
|
|
36
|
-
Version = '0.
|
30
|
+
Version = '0.11.0'
|
37
31
|
|
38
32
|
# Library path.
|
39
33
|
|
40
34
|
LibPath = File.dirname(__FILE__)
|
41
35
|
|
36
|
+
# If set to true, action methods can have arguments which are
|
37
|
+
# automatically resolved.
|
38
|
+
#
|
39
|
+
# === Example
|
40
|
+
#
|
41
|
+
# def list(username, oid)
|
42
|
+
# ...
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# http://www.mysite.com/list?username=tml;oid=2
|
46
|
+
#
|
47
|
+
# calls list() with the correct parameters, no need to
|
48
|
+
# use request['oid'], just use oid.
|
49
|
+
#
|
50
|
+
# WARNING: this feature requires the ParseTree library which
|
51
|
+
# is not compatible with Windows.
|
52
|
+
|
53
|
+
mattr_accessor :resolve_action_arguments, false
|
54
|
+
|
42
55
|
end
|
56
|
+
|
57
|
+
# gmosx: leave them here.
|
58
|
+
|
59
|
+
require 'nitro/context'
|
60
|
+
require 'nitro/dispatcher'
|
61
|
+
require 'nitro/render'
|
62
|
+
require 'nitro/conf'
|
63
|
+
require 'nitro/runner'
|
64
|
+
require 'nitro/component'
|
data/lib/nitro/adapters/cgi.rb
CHANGED
@@ -140,11 +140,26 @@ class CgiUtils
|
|
140
140
|
end
|
141
141
|
|
142
142
|
# Build the response headers for the context.
|
143
|
+
#
|
144
|
+
# [+context+]
|
145
|
+
# The context of the response.
|
146
|
+
#
|
147
|
+
# [+proto+]
|
148
|
+
# If true emmit the protocol line. Useful for MOD_RUBY.
|
149
|
+
#--
|
150
|
+
# FIXME: return the correct protocol from env.
|
151
|
+
# TODO: Perhaps I can optimize status calc.
|
152
|
+
#++
|
143
153
|
|
144
|
-
def self.response_headers(context)
|
154
|
+
def self.response_headers(context, proto = false)
|
145
155
|
reason = STATUS_STRINGS[context.status]
|
146
|
-
|
147
|
-
|
156
|
+
|
157
|
+
if proto
|
158
|
+
buf = "HTTP/1.1 #{context.status} #{reason}#{EOL}Date: #{CGI::rfc1123_date(Time.now)}#{EOL}"
|
159
|
+
else
|
160
|
+
buf = "Status: #{context.status} #{reason}#{EOL}"
|
161
|
+
end
|
162
|
+
|
148
163
|
context.response_headers.each do |key, value|
|
149
164
|
tmp = key.gsub(/\bwww|^te$|\b\w/) { |s| s.upcase }
|
150
165
|
buf << "#{tmp}: #{value}" << EOL
|
@@ -155,6 +170,8 @@ class CgiUtils
|
|
155
170
|
end if context.response_cookies
|
156
171
|
|
157
172
|
buf << EOL
|
173
|
+
|
174
|
+
return buf
|
158
175
|
end
|
159
176
|
|
160
177
|
# Initialize the request params.
|
@@ -184,6 +201,9 @@ class CgiUtils
|
|
184
201
|
end
|
185
202
|
|
186
203
|
# Parse a multipart request.
|
204
|
+
#--
|
205
|
+
# FIXME: implement me, not working
|
206
|
+
#++
|
187
207
|
|
188
208
|
def self.parse_multipart(context, boundary)
|
189
209
|
io = context.in
|
@@ -33,7 +33,7 @@ class Webrick
|
|
33
33
|
attr_accessor :server
|
34
34
|
|
35
35
|
def start(conf)
|
36
|
-
conf =
|
36
|
+
conf = Conf.new(conf) unless conf.is_a?(Conf)
|
37
37
|
|
38
38
|
# patch for OSX
|
39
39
|
|
@@ -49,7 +49,7 @@ class Webrick
|
|
49
49
|
accesslog = STDERR
|
50
50
|
refererlog = STDERR
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
@server = WEBrick::HTTPServer.new(
|
54
54
|
:BindAddress => conf.host,
|
55
55
|
:Port => conf.port,
|
@@ -70,6 +70,10 @@ class Webrick
|
|
70
70
|
end
|
71
71
|
|
72
72
|
# A Webrick Adapter for Nitro.
|
73
|
+
#--
|
74
|
+
# TODO: optimize the conversion from WEBrick's
|
75
|
+
# parameters to the Nitro parameters.
|
76
|
+
#++
|
73
77
|
|
74
78
|
class WebrickAdapter < WEBrick::HTTPServlet::AbstractServlet
|
75
79
|
|
@@ -107,11 +111,13 @@ class WebrickAdapter < WEBrick::HTTPServlet::AbstractServlet
|
|
107
111
|
req.cookies.each { |c| context.cookies[c.name] = c.value }
|
108
112
|
|
109
113
|
context.render(path)
|
110
|
-
|
114
|
+
|
111
115
|
res.status = context.status
|
112
116
|
res.header = context.response_headers || {}
|
113
117
|
res.cookies = context.response_cookies || {}
|
114
118
|
res.body = context.out
|
119
|
+
|
120
|
+
context.close
|
115
121
|
end
|
116
122
|
ensure
|
117
123
|
# REQUEST_MUTEX.unlock if REQUEST_MUTEX.locked?
|