nitro 0.10.0 → 0.11.0
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.
- 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?
|