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.
Files changed (99) hide show
  1. data/AUTHORS +4 -1
  2. data/ChangeLog +290 -7
  3. data/README +3 -3
  4. data/RELEASES +94 -0
  5. data/Rakefile +7 -7
  6. data/benchmark/og/bench.rb +11 -10
  7. data/{ChangeLog.1 → doc/ChangeLog.1} +0 -0
  8. data/doc/apache.txt +9 -0
  9. data/doc/architecture.txt +1 -27
  10. data/doc/bugs.txt +11 -4
  11. data/doc/config.txt +22 -0
  12. data/doc/og_config.txt +35 -0
  13. data/doc/og_tutorial.txt +595 -0
  14. data/doc/tutorial.txt +22 -0
  15. data/examples/blog/conf/apache.conf +30 -0
  16. data/examples/blog/conf/lhttpd.conf +2 -2
  17. data/examples/blog/lib/blog/controller.rb +11 -2
  18. data/examples/blog/log/apache.error_log +5528 -0
  19. data/examples/blog/root/fcgi.rb +1 -1
  20. data/examples/blog/run.rb +9 -3
  21. data/examples/flash/run.rb +2 -2
  22. data/examples/no_xsl_blog/conf/apache.conf +30 -0
  23. data/examples/no_xsl_blog/conf/lhttpd.conf +1 -1
  24. data/examples/no_xsl_blog/lib/blog/controller.rb +2 -2
  25. data/examples/no_xsl_blog/log/apache.error_log +68 -0
  26. data/examples/no_xsl_blog/root/fcgi.rb +2 -2
  27. data/examples/no_xsl_blog/run.rb +3 -3
  28. data/examples/og/run.rb +1 -1
  29. data/examples/tiny/conf/apache.conf +29 -4
  30. data/examples/tiny/conf/lhttpd.conf +1 -1
  31. data/examples/tiny/log/apache.error_log +30 -0
  32. data/examples/tiny/root/fcgi.rb +2 -2
  33. data/examples/tiny/root/index.xhtml +1 -1
  34. data/examples/tiny/run.rb +3 -2
  35. data/examples/wee_style/run.rb +7 -9
  36. data/examples/why_wiki/README +5 -0
  37. data/examples/why_wiki/run.rb +57 -0
  38. data/examples/why_wiki/wiki.yml +6 -0
  39. data/examples/wiki.yml +1 -0
  40. data/lib/glue/array.rb +14 -33
  41. data/lib/glue/hash.rb +32 -53
  42. data/lib/glue/pool.rb +9 -12
  43. data/lib/glue/property.rb +31 -9
  44. data/lib/nitro.rb +30 -8
  45. data/lib/nitro/adapters/cgi.rb +23 -3
  46. data/lib/nitro/adapters/webrick.rb +9 -3
  47. data/lib/nitro/builders/form.rb +21 -13
  48. data/lib/nitro/builders/rss.rb +20 -9
  49. data/lib/nitro/builders/table.rb +69 -10
  50. data/lib/nitro/builders/xhtml.rb +13 -4
  51. data/lib/nitro/component.rb +15 -0
  52. data/lib/nitro/conf.rb +4 -3
  53. data/lib/nitro/context.rb +22 -14
  54. data/lib/nitro/controller.rb +63 -5
  55. data/lib/nitro/dispatcher.rb +11 -6
  56. data/lib/nitro/output.rb +28 -0
  57. data/lib/nitro/render.rb +78 -59
  58. data/lib/nitro/request.rb +5 -1
  59. data/lib/nitro/runner.rb +20 -6
  60. data/lib/nitro/session.rb +89 -18
  61. data/lib/nitro/session/drb.rb +31 -0
  62. data/lib/nitro/session/drbserver.rb +71 -0
  63. data/lib/nitro/session/memory.rb +13 -0
  64. data/lib/nitro/simple.rb +7 -0
  65. data/lib/nitro/ui/date-select.rb +2 -5
  66. data/lib/nitro/ui/pager.rb +4 -4
  67. data/lib/nitro/ui/tabs.rb +2 -4
  68. data/lib/nitro/uri.rb +7 -4
  69. data/lib/og.rb +20 -12
  70. data/lib/og/adapter.rb +40 -13
  71. data/lib/og/adapters/filesys.rb +121 -0
  72. data/lib/og/adapters/mysql.rb +10 -5
  73. data/lib/og/adapters/oracle.rb +374 -0
  74. data/lib/og/adapters/psql.rb +10 -23
  75. data/lib/og/adapters/sqlite.rb +3 -3
  76. data/lib/og/backend.rb +2 -2
  77. data/lib/og/connection.rb +6 -6
  78. data/lib/og/database.rb +5 -5
  79. data/lib/og/enchant.rb +6 -2
  80. data/lib/og/meta.rb +56 -26
  81. data/lib/og/mock.rb +1 -1
  82. data/lib/og/typemacros.rb +23 -0
  83. data/lib/parts/content.rb +4 -10
  84. data/test/nitro/adapters/tc_cgi.rb +1 -1
  85. data/test/nitro/builders/tc_rss.rb +1 -1
  86. data/test/nitro/builders/tc_table.rb +30 -0
  87. data/test/nitro/tc_context.rb +4 -0
  88. data/test/nitro/tc_controller.rb +9 -2
  89. data/test/og/tc_filesys.rb +83 -0
  90. data/test/og/tc_meta.rb +55 -0
  91. data/test/tc_og.rb +115 -36
  92. data/vendor/README +11 -5
  93. data/vendor/breakpoint.rb +35 -38
  94. data/vendor/breakpoint_client.rb +119 -80
  95. data/vendor/composite_sexp_processor.rb +43 -0
  96. data/vendor/parse_tree.rb +745 -0
  97. data/vendor/sexp_processor.rb +453 -0
  98. metadata +34 -7
  99. data/examples/no_xsl_blog/conf/app.conf.rb +0 -47
@@ -0,0 +1,28 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: output.rb 267 2005-02-28 14:52:41Z gmosx $
4
+
5
+ require 'nitro/builders/xml'
6
+ require 'nitro/builders/xhtml'
7
+ require 'nitro/builders/rss'
8
+ require 'nitro/builders/form'
9
+ require 'nitro/builders/table'
10
+
11
+ module N
12
+
13
+ # The output buffer string. This buffer integrates
14
+ # the programmatic rendering support (XhtmlBuilder)
15
+ # and the various builders required by the application.
16
+ #--
17
+ # TODO: Implement a FAST string (maybe in C)
18
+ #++
19
+
20
+ class OutputBuffer < String
21
+ include XmlBuilderMixin
22
+ include XhtmlBuilderMixin
23
+ include RssBuilderMixin
24
+ include FormBuilderMixin
25
+ include TableBuilderMixin
26
+ end
27
+
28
+ end
@@ -2,6 +2,10 @@
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
3
  # $Id$
4
4
 
5
+ require 'sync'
6
+
7
+ require 'nitro'
8
+
5
9
  require 'glue/attribute'
6
10
  require 'glue/misc'
7
11
  require 'glue/object'
@@ -19,6 +23,8 @@ class RenderExit < Exception; end
19
23
 
20
24
  module Rendering
21
25
 
26
+ @@sync = Sync.new
27
+
22
28
  # The default template name (no extension).
23
29
 
24
30
  mattr_accessor :default_template, 'index'
@@ -84,80 +90,85 @@ module Rendering
84
90
  # Compile a controller action.
85
91
 
86
92
  def self.compile_action(klass, action, base)
87
- dummy, api, action = action.to_s.split('__')
93
+ @@sync.synchronize do
94
+ dummy, api, action = action.to_s.split('__')
88
95
 
89
- # This is not a controller action.
96
+ # This is not a controller action.
90
97
 
91
- return false unless action
98
+ return false unless action
92
99
 
93
- Logger.debug "Compiling action '#{base}/#{action}'" if $DBG
100
+ Logger.debug "Compiling action '#{base}/#{action}'" if $DBG
94
101
 
95
- valid = false
96
-
97
- code = %{
98
- def __#{api}__#{action}
99
- }
100
-
101
- # call 'before' filter chain.
102
-
103
- if klass.respond_to?(:before_filters)
104
- code << %{
105
- #{klass.gen_filters_call_code(klass.before_filters)}
102
+ valid = false
103
+
104
+ code = %{
105
+ def __#{api}__#{action}
106
106
  }
107
- end
107
+
108
+ # call 'before' filter chain.
109
+
110
+ if klass.respond_to?(:before_filters)
111
+ code << %{
112
+ #{klass.gen_filters_call_code(klass.before_filters)}
113
+ }
114
+ end
108
115
 
109
- # call the action
110
-
111
- if klass.instance_methods.include?(action)
112
- valid = true
113
- code << %{
114
- #{action}();
115
- }
116
- end
116
+ # call the action
117
+
118
+ if klass.action_methods.include?(action)
119
+ valid = true
120
+
121
+ args = klass.action_method_arguments(action).map { |a| "@#{a} = @context['#{a}']" }
122
+
123
+ code << %{
124
+ #{action}(#{args.join(',')});
125
+ }
126
+ end
117
127
 
118
- # call the programmatically generated template if exists.
128
+ # call the programmatically generated template if exists.
119
129
 
120
- if klass.instance_methods.include?("#{action}__#{api}")
121
- valid = true
122
- code << %{
123
- return unless #{action}__#{api}();
124
- }
125
- end
126
-
127
- # call the template if exists.
128
-
129
- if template = template_for_action(base, action)
130
- valid = true
131
- code << %{
132
- return unless __#{api}__#{action}__template();
133
- }
134
- end
130
+ if klass.action_methods.include?("#{action}__#{api}")
131
+ valid = true
132
+ code << %{
133
+ return unless #{action}__#{api}();
134
+ }
135
+ end
136
+
137
+ # call the template if exists.
138
+
139
+ if template = template_for_action(base, action)
140
+ valid = true
141
+ code << %{
142
+ return unless __#{api}__#{action}__template();
143
+ }
144
+ end
135
145
 
136
- # raise "Invalid action '#{action}' for '#{klass}'!" unless valid
137
- return false unless valid
146
+ # raise "Invalid action '#{action}' for '#{klass}'!" unless valid
147
+ return false unless valid
138
148
 
139
- # call 'after' filter chain.
149
+ # call 'after' filter chain.
140
150
 
141
- if klass.respond_to?(:after_filters)
142
- code << %{
143
- #{klass.gen_filters_call_code(klass.after_filters)}
144
- }
145
- end
146
-
147
- code << %{
148
- redirect_referer if @out.empty?
151
+ if klass.respond_to?(:after_filters)
152
+ code << %{
153
+ #{klass.gen_filters_call_code(klass.after_filters)}
154
+ }
149
155
  end
150
- }
151
-
152
- if template
156
+
153
157
  code << %{
154
- def __#{api}__#{action}__template
155
- #{transform_template(template, Rendering.shader)}
158
+ redirect_referer if @out.empty?
156
159
  end
157
160
  }
158
- end
161
+
162
+ if template
163
+ code << %{
164
+ def __#{api}__#{action}__template
165
+ #{transform_template(template, Rendering.shader)}
166
+ end
167
+ }
168
+ end
159
169
 
160
- klass.class_eval(code)
170
+ klass.class_eval(code)
171
+ end
161
172
 
162
173
  return true
163
174
  end
@@ -198,7 +209,7 @@ module Render
198
209
  @out = context.out
199
210
  @base = base
200
211
  end
201
-
212
+
202
213
  # Renders the action denoted by path. The path
203
214
  # is resolved by the dispatcher to get the correct
204
215
  # controller.
@@ -233,6 +244,8 @@ module Render
233
244
  @out << '(error)'
234
245
  end
235
246
 
247
+ private
248
+
236
249
  # Send a redirect response.
237
250
 
238
251
  def redirect(url, status = 303)
@@ -267,6 +280,12 @@ module Render
267
280
  @context.session
268
281
  end
269
282
 
283
+ # Convenience method to access the output buffer.
284
+
285
+ def o
286
+ @out
287
+ end
288
+
270
289
  end
271
290
 
272
291
  end
@@ -55,6 +55,10 @@ module Request
55
55
  uri ? uri.split('?').first : ''
56
56
  end
57
57
 
58
+ def path_info
59
+ @headers['PATH_INFO']
60
+ end
61
+
58
62
  # The request query string.
59
63
 
60
64
  def query_string
@@ -71,7 +75,7 @@ module Request
71
75
  # clickstream there is no referer, set "/" by default.
72
76
 
73
77
  def referer
74
- return @headers['REFERER'] || '/'
78
+ return @headers['HTTP_REFERER'] || '/'
75
79
  end
76
80
 
77
81
  # The remote IP address. REMOTE_ADDR is the standard
@@ -110,6 +110,11 @@ class Runner
110
110
  Logger.set(Logger.new('log/app.log'))
111
111
  end
112
112
 
113
+ opts.on('-a', '--apache', 'Use an apache server.') do
114
+ @server = :apache
115
+ Logger.set(Logger.new('log/app.log'))
116
+ end
117
+
113
118
  opts.on('-C', '--console', 'Start a console attached to an instance of the application.') do
114
119
  if RUBY_PLATFORM =~ /mswin32/
115
120
  irb_name = 'irb.bat'
@@ -122,11 +127,6 @@ class Runner
122
127
  exit
123
128
  end
124
129
 
125
- opts.on('-l', '--lhttpd', 'Use a lighttpd server.') do
126
- @server = :lhttpd
127
- Logger.set(Logger.new('log/app.log'))
128
- end
129
-
130
130
  opts.on_tail('-v', '--version', 'Show version.') do
131
131
  puts "Nitro #{Nitro::Version}"
132
132
  exit
@@ -205,8 +205,9 @@ class Runner
205
205
  case @action
206
206
  when :start
207
207
 
208
- case @server
208
+ puts "\n==> Application listening at #{conf.host}:#{conf.port}.\n\n"
209
209
 
210
+ case @server
210
211
  when :webrick
211
212
  require 'nitro/adapters/webrick'
212
213
  Webrick.start(conf)
@@ -214,10 +215,23 @@ class Runner
214
215
  when :lhttpd
215
216
  require 'nitro/adapters/fastcgi'
216
217
  `lighttpd -f conf/lhttpd.conf`
218
+
219
+ when :apache
220
+ require 'nitro/adapters/fastcgi'
221
+ `apachectl -d #{Dir.pwd} -f conf/apache.conf -k start`
217
222
  end
218
223
 
219
224
  when :stop
220
225
 
226
+ case @server
227
+ when :webrick
228
+
229
+ when :lhttpd
230
+
231
+ when :apache
232
+ `apachectl -d #{Dir.pwd} -f conf/apache.conf -k stop`
233
+ end
234
+
221
235
  end
222
236
  end
223
237
 
@@ -5,19 +5,19 @@
5
5
  require 'md5'
6
6
  require 'webrick'
7
7
 
8
+ require 'glue/hash'
8
9
  require 'glue/attribute'
9
-
10
10
  require 'nitro/cookie'
11
11
 
12
12
  module N
13
13
 
14
14
  # A web application session.
15
15
  #
16
- # State is a neccessary evil but session variables should
17
- # be avoided as much as possible. Session state is typically
18
- # distributed to many servers so avoid storing complete
19
- # objects in session variables, only store oids and small
20
- # integer/strings.
16
+ # State is a neccessary evil but session variables
17
+ # should be avoided as much as possible. Session state
18
+ # is typically distributed to many servers so avoid
19
+ # storing complete objects in session variables, only
20
+ # store oids and small integer/strings.
21
21
  #
22
22
  # The session should be persistable to survive server
23
23
  # shutdowns.
@@ -32,42 +32,99 @@ class Session < Hash
32
32
 
33
33
  cattr_accessor :cookie_name, 'nsid'
34
34
 
35
- # The sessions
36
-
37
- cattr_accessor :manager; @@manager = {}
35
+ # The sessions store. By default sessions are
36
+ # stored in memory.
38
37
 
39
- # The unique id of this session.
38
+ cattr_accessor :store; @@store = N::SafeHash.new
40
39
 
41
- attr_reader :session_id
40
+ # Set the session store. The following options are
41
+ # available:
42
+ #
43
+ # * :memory [default]
44
+ # * :drb
45
+ # * :memcached (not available yet)
46
+ # * :og (not available yet)
47
+ # * :file (not available yet)
48
+
49
+ def self.store_type=(store_type)
50
+ require "nitro/session/#{store_type}"
51
+ end
42
52
 
53
+ # Lookup the session in the store by using the session
54
+ # cookie value as a key. If the session does not exist
55
+ # creates a new session, inserts it in the store and
56
+ # appends a new session cookie in the response.
57
+
43
58
  def self.lookup(context)
44
- if cookie = context.cookies[Session.cookie_name]
45
- session = context.sessions[cookie]
59
+ if session_id = context.cookies[Session.cookie_name]
60
+ session = Session.store[session_id]
46
61
  end
47
62
 
48
63
  unless session
64
+ # Create new session.
49
65
  session = Session.new(context)
50
- context.add_cookie(Cookie.new(Session.cookie_name, session.session_id))
51
- context.sessions[session.session_id] = session
66
+ context.add_cookie(
67
+ Cookie.new(Session.cookie_name, session.session_id)
68
+ )
69
+ Session.store[session.session_id] = session
70
+ else
71
+ # Access ('touch') the existing session.
72
+ session.touch!
52
73
  end
53
74
 
54
75
  return session
55
76
  end
56
77
 
78
+ # The unique id of this session.
79
+
80
+ attr_reader :session_id
81
+
82
+ # The time this session was created.
83
+
84
+ attr_reader :ctime
85
+ alias_method :create_time, :ctime
86
+
87
+ # The time this session was last modified.
88
+
89
+ attr_accessor :mtime
90
+ alias_method :modify_time, :mtime
91
+
92
+ # The time this session was last accessed.
93
+
94
+ attr_accessor :atime
95
+ alias_method :access_time, :mtime
96
+
57
97
  # Create the session for the given context.
58
98
 
59
99
  def initialize(context = nil)
60
100
  @session_id = create_id
101
+ @ctime = @mtime = @atime = Time.now
102
+ end
103
+
104
+ # Like the unix touch command, upadtes
105
+ # the atime to now.
106
+
107
+ def touch!
108
+ @atime = Time.now
61
109
  end
62
110
 
111
+ # Synchronize the session store, by
112
+ # restoring this session. Especially useful
113
+ # in distributed and/or multiprocess setups.
114
+
115
+ def sync
116
+ Session.store[@session_id] = self
117
+ end
118
+ alias_method :restore, :sync
119
+
63
120
  protected
64
121
 
65
122
  # Calculates a unique id.
66
123
  #
67
124
  # The session id must be unique, a monotonically
68
- # increasing function like time is appropriate. Random
69
- # may produce equal ids? add a prefix (SALT) to stop
70
- # hackers from creating session_ids.
125
+ # increasing function like time is appropriate.
126
+ # Random may produce equal ids? add a prefix
127
+ # (SALT) to stop hackers from creating session_ids.
71
128
 
72
129
  def create_id
73
130
  now = Time.now
@@ -81,4 +138,18 @@ protected
81
138
 
82
139
  end
83
140
 
141
+ # Abstract class for a session store manager.
142
+
143
+ class SessionStore
144
+ def []=(sid, session)
145
+ end
146
+
147
+ def [](sid)
148
+ end
149
+
150
+ def delete(sid)
151
+ end
152
+
153
+ end
154
+
84
155
  end