hayabusa 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +20 -0
- data/Gemfile.lock +59 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/bin/check_running.rb +69 -0
- data/bin/hayabusa_benchmark.rb +82 -0
- data/bin/hayabusa_cgi.rb +84 -0
- data/bin/hayabusa_fcgi.fcgi +159 -0
- data/bin/hayabusa_fcgi.rb +159 -0
- data/bin/knjappserver_start.rb +42 -0
- data/conf/apache2_cgi_rhtml_conf.conf +10 -0
- data/conf/apache2_fcgi_rhtml_conf.conf +22 -0
- data/hayabusa.gemspec +151 -0
- data/lib/hayabusa.rb +518 -0
- data/lib/hayabusa_cgi_session.rb +128 -0
- data/lib/hayabusa_cgi_tools.rb +102 -0
- data/lib/hayabusa_custom_io.rb +22 -0
- data/lib/hayabusa_database.rb +125 -0
- data/lib/hayabusa_erb_handler.rb +27 -0
- data/lib/hayabusa_ext/cleaner.rb +140 -0
- data/lib/hayabusa_ext/cmdline.rb +52 -0
- data/lib/hayabusa_ext/errors.rb +135 -0
- data/lib/hayabusa_ext/logging.rb +404 -0
- data/lib/hayabusa_ext/mailing.rb +158 -0
- data/lib/hayabusa_ext/sessions.rb +71 -0
- data/lib/hayabusa_ext/threadding.rb +96 -0
- data/lib/hayabusa_ext/threadding_timeout.rb +101 -0
- data/lib/hayabusa_ext/translations.rb +43 -0
- data/lib/hayabusa_ext/web.rb +190 -0
- data/lib/hayabusa_http_server.rb +102 -0
- data/lib/hayabusa_http_session.rb +361 -0
- data/lib/hayabusa_http_session_contentgroup.rb +176 -0
- data/lib/hayabusa_http_session_page_environment.rb +66 -0
- data/lib/hayabusa_http_session_post_multipart.rb +135 -0
- data/lib/hayabusa_http_session_request.rb +219 -0
- data/lib/hayabusa_http_session_response.rb +144 -0
- data/lib/hayabusa_models.rb +8 -0
- data/lib/kernel_ext/gettext_methods.rb +22 -0
- data/lib/kernel_ext/magic_methods.rb +61 -0
- data/lib/models/log.rb +130 -0
- data/lib/models/log_access.rb +88 -0
- data/lib/models/log_data.rb +27 -0
- data/lib/models/log_data_link.rb +3 -0
- data/lib/models/log_data_value.rb +21 -0
- data/lib/models/log_link.rb +65 -0
- data/lib/models/session.rb +35 -0
- data/pages/benchmark.rhtml +0 -0
- data/pages/benchmark_print.rhtml +14 -0
- data/pages/benchmark_simple.rhtml +3 -0
- data/pages/benchmark_threadded_content.rhtml +21 -0
- data/pages/debug_database_connections.rhtml +46 -0
- data/pages/debug_http_sessions.rhtml +40 -0
- data/pages/debug_memory_usage.rhtml +16 -0
- data/pages/error_notfound.rhtml +12 -0
- data/pages/logs_latest.rhtml +57 -0
- data/pages/logs_show.rhtml +32 -0
- data/pages/spec.rhtml +41 -0
- data/pages/spec_post.rhtml +3 -0
- data/pages/spec_test_multiple_clients.rhtml +3 -0
- data/pages/spec_thread_joins.rhtml +21 -0
- data/pages/spec_threadded_content.rhtml +40 -0
- data/pages/tests.rhtml +14 -0
- data/spec/cgi_spec.rb +47 -0
- data/spec/custom_urls_spec.rb +35 -0
- data/spec/fcgi_multiple_processes_spec.rb +32 -0
- data/spec/fcgi_spec.rb +69 -0
- data/spec/hayabusa_spec.rb +194 -0
- data/spec/spec_helper.rb +12 -0
- data/tests/cgi_test/config_cgi.rb +6 -0
- data/tests/cgi_test/threadded_content_test.rhtml +23 -0
- data/tests/cgi_test/vars_get_test.rhtml +4 -0
- data/tests/cgi_test/vars_header_test.rhtml +3 -0
- data/tests/cgi_test/vars_post_test.rhtml +4 -0
- data/tests/fcgi_test/config_fcgi.rb +6 -0
- data/tests/fcgi_test/index.rhtml +3 -0
- data/tests/fcgi_test/sleeper.rhtml +4 -0
- data/tests/fcgi_test/threadded_content_test.rhtml +23 -0
- data/tests/fcgi_test/vars_get_test.rhtml +4 -0
- data/tests/fcgi_test/vars_header_test.rhtml +3 -0
- data/tests/fcgi_test/vars_post_test.rhtml +4 -0
- metadata +257 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
#This scripts start an appserver, executes a HTTP-request for every FCGI-request and terminates when FCGI terminates.
|
4
|
+
#Good for programming appserver-supported projects that doesnt need threadding without running an appserver all the time.
|
5
|
+
|
6
|
+
#It doesnt support shared threadding or objects because multiple instances in form of processes will be executed.
|
7
|
+
|
8
|
+
#Its a bit slower because it needs to flush writes to the database at end of every request and re-read them on spawn, because multiple instances might be present.
|
9
|
+
|
10
|
+
error_log_file = "/tmp/hayabusa_fcgi.log"
|
11
|
+
|
12
|
+
begin
|
13
|
+
File.unlink(error_log_file) if File.exists?(error_log_file)
|
14
|
+
rescue Errno::ENOENT
|
15
|
+
#ignore.
|
16
|
+
end
|
17
|
+
|
18
|
+
begin
|
19
|
+
require "rubygems"
|
20
|
+
require "knjrbfw"
|
21
|
+
require "fcgi"
|
22
|
+
require "fileutils"
|
23
|
+
require "#{File.dirname(Knj::Os.realpath(__FILE__))}/../lib/hayabusa.rb"
|
24
|
+
|
25
|
+
#Spawn CGI-variable to emulate FCGI part.
|
26
|
+
cgi_tools = Hayabusa::Cgi_tools.new
|
27
|
+
|
28
|
+
#We cant define the Hayabusa-server untuil we receive the first headers, so wait for the first request.
|
29
|
+
hayabusa = nil
|
30
|
+
fcgi_proxy = nil
|
31
|
+
|
32
|
+
FCGI.each_cgi do |cgi|
|
33
|
+
begin
|
34
|
+
#cgi.print "Content-Type: text/html\r\n"
|
35
|
+
#cgi.print "\r\n"
|
36
|
+
|
37
|
+
cgi_tools.cgi = cgi
|
38
|
+
|
39
|
+
if !hayabusa
|
40
|
+
raise "No HTTP_HAYABUSA_FCGI_CONFIG-header was given." if !cgi.env_table["HTTP_HAYABUSA_FCGI_CONFIG"]
|
41
|
+
require cgi.env_table["HTTP_HAYABUSA_FCGI_CONFIG"]
|
42
|
+
|
43
|
+
begin
|
44
|
+
conf = Hayabusa::FCGI_CONF
|
45
|
+
rescue NameError
|
46
|
+
raise "No 'Hayabusa::FCGI_CONF'-constant was spawned by '#{cgi.env_table["HTTP_HAYABUSA_FCGI_CONFIG"]}'."
|
47
|
+
end
|
48
|
+
|
49
|
+
hayabusa_conf = Hayabusa::FCGI_CONF[:hayabusa]
|
50
|
+
hayabusa_conf.merge!(
|
51
|
+
:cmdline => false,
|
52
|
+
:port => 0 #Ruby picks random port and we get the actual port after starting the appserver.
|
53
|
+
)
|
54
|
+
|
55
|
+
#Figure out if this should be a host-FCGI-process or a proxy-FCGI-process.
|
56
|
+
fcgi_config_fp = "#{Knj::Os.tmpdir}/hayabusa_fcgi_#{hayabusa_conf[:title]}_fcgi.conf"
|
57
|
+
FileUtils.touch(fcgi_config_fp) if !File.exists?(fcgi_config_fp)
|
58
|
+
|
59
|
+
begin
|
60
|
+
File.open(fcgi_config_fp) do |fp|
|
61
|
+
fp.flock(File::LOCK_EX)
|
62
|
+
|
63
|
+
fcgi_config_cont = File.read(fcgi_config_fp)
|
64
|
+
|
65
|
+
if !fcgi_config_cont.empty?
|
66
|
+
fcgi_config = Marshal.load(File.read(fcgi_config_fp))
|
67
|
+
pid = fcgi_config[:pid]
|
68
|
+
|
69
|
+
if Knj::Unix_proc.pid_running?(pid)
|
70
|
+
fcgi_proxy = fcgi_config
|
71
|
+
|
72
|
+
require "http2"
|
73
|
+
http = Http2.new(:host => "localhost", :port => fcgi_proxy[:port].to_i)
|
74
|
+
fcgi_proxy[:http] = http
|
75
|
+
end
|
76
|
+
else
|
77
|
+
fcgi_config = nil
|
78
|
+
end
|
79
|
+
|
80
|
+
if !fcgi_proxy
|
81
|
+
File.open(fcgi_config_fp, "w") do |fp|
|
82
|
+
hayabusa = Hayabusa.new(hayabusa_conf)
|
83
|
+
|
84
|
+
#Start web-server for proxy-requests.
|
85
|
+
hayabusa.start
|
86
|
+
|
87
|
+
fp.write(Marshal.dump(
|
88
|
+
:pid => Process.pid,
|
89
|
+
:port => hayabusa.port
|
90
|
+
))
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
ensure
|
95
|
+
File.open(fcgi_config_fp).flock(File::LOCK_UN)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
if fcgi_proxy
|
102
|
+
#Proxy request to the host-FCGI-process.
|
103
|
+
cgi_tools.proxy_request_to(:cgi => cgi, :http => fcgi_proxy[:http])
|
104
|
+
else
|
105
|
+
#Host the FCGI-process.
|
106
|
+
|
107
|
+
#Enforce $stdout variable.
|
108
|
+
$stdout = hayabusa.cio
|
109
|
+
|
110
|
+
#The rest is copied from the FCGI-part.
|
111
|
+
headers = {}
|
112
|
+
cgi.env_table.each do |key, val|
|
113
|
+
if key[0, 5] == "HTTP_" and key != "HTTP_HAYABUSA_FCGI_CONFIG"
|
114
|
+
key = key[5, key.length].gsub("_", " ").gsub(" ", "-")
|
115
|
+
headers[key] = val
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
meta = cgi.env_table.to_hash
|
120
|
+
|
121
|
+
uri = Knj::Web.parse_uri(meta["REQUEST_URI"])
|
122
|
+
meta["PATH_TRANSLATED"] = File.basename(uri[:path])
|
123
|
+
|
124
|
+
cgi_data = {
|
125
|
+
:cgi => cgi,
|
126
|
+
:headers => headers,
|
127
|
+
:get => Knj::Web.parse_urlquery(cgi.env_table["QUERY_STRING"], :urldecode => true, :force_utf8 => true),
|
128
|
+
:meta => meta
|
129
|
+
}
|
130
|
+
if cgi.request_method == "POST"
|
131
|
+
cgi_data[:post] = cgi_tools.convert_fcgi_post(cgi.params)
|
132
|
+
else
|
133
|
+
cgi_data[:post] = {}
|
134
|
+
end
|
135
|
+
|
136
|
+
hayabusa.config[:cgi] = cgi_data
|
137
|
+
|
138
|
+
|
139
|
+
#Handle request.
|
140
|
+
hayabusa.start_cgi_request
|
141
|
+
end
|
142
|
+
rescue Exception => e
|
143
|
+
cgi.print "Content-Type: text/html\r\n"
|
144
|
+
cgi.print "\r\n"
|
145
|
+
cgi.print Knj::Errors.error_str(e, :html => true)
|
146
|
+
cgi.print Knj.p(cgi_data, true) if cgi_data
|
147
|
+
end
|
148
|
+
end
|
149
|
+
rescue Exception => e
|
150
|
+
if !e.is_a?(Interrupt)
|
151
|
+
File.open(error_log_file, "w") do |fp|
|
152
|
+
fp.puts e.inspect
|
153
|
+
fp.puts e.backtrace
|
154
|
+
fp.puts ""
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
raise e
|
159
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "#{File.dirname(__FILE__)}/../lib/hayabusa.rb"
|
4
|
+
|
5
|
+
knjrbfw_path = ""
|
6
|
+
|
7
|
+
ARGV.each do |arg|
|
8
|
+
if arg == "--active_support"
|
9
|
+
ARGV.delete(arg)
|
10
|
+
require "active_support"
|
11
|
+
require "active_support/core_ext"
|
12
|
+
elsif match = arg.match(/--knjrbfw_path=(.+)/)
|
13
|
+
knjrbfw_path = match[1]
|
14
|
+
ARGV.delete(arg)
|
15
|
+
else
|
16
|
+
print "Unknown argument: '#{arg}'.\n"
|
17
|
+
exit
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
require "#{knjrbfw_path}knjrbfw"
|
22
|
+
|
23
|
+
filepath = File.dirname(__FILE__) + "/../lib/"
|
24
|
+
|
25
|
+
if File.exists?($0)
|
26
|
+
conf_path = File.dirname($0) + "/../"
|
27
|
+
else
|
28
|
+
conf_path = File.dirname(__FILE__) + "/../"
|
29
|
+
end
|
30
|
+
|
31
|
+
require "#{conf_path}conf/conf_vars"
|
32
|
+
require "#{$hayabusa_config["knjrbfw"]}knj/autoload"
|
33
|
+
|
34
|
+
$hayabusa = {
|
35
|
+
:path => File.realpath(File.dirname(__FILE__))
|
36
|
+
}
|
37
|
+
|
38
|
+
Knj::Os.chdir_file(File.realpath(__FILE__))
|
39
|
+
require "#{filepath}include/class_hayabusa.rb"
|
40
|
+
|
41
|
+
print "Starting knjAppServer.\n"
|
42
|
+
require "#{conf_path}conf/conf"
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Alias /hayabusa_cgi_test "/path/to/hayabusa/tests/cgi_test"
|
2
|
+
ScriptAlias /hayabusa/ "/path/to/hayabusa/bin/"
|
3
|
+
|
4
|
+
<Directory "/path/to/hayabusa/tests/cgi_test">
|
5
|
+
Options +FollowSymLinks +ExecCGI
|
6
|
+
RequestHeader set HAYABUSA_CGI_CONFIG "/path/to/hayabusa/tests/cgi_test/config_cgi.rb"
|
7
|
+
AddHandler application/x-hayabusa-cgi .rhtml
|
8
|
+
Action application/x-hayabusa-cgi /hayabusa/hayabusa_cgi.rb
|
9
|
+
DirectoryIndex index.cgi
|
10
|
+
</Directory>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Alias /hayabusa_fcgi_test "/path/to/hayabusa/tests/fcgi_test"
|
2
|
+
Alias /hayabusa_fcgi_bin "/path/to/hayabusa/bin"
|
3
|
+
|
4
|
+
<IfModule mod_fcgid.c>
|
5
|
+
SocketPath /tmp/fcgi_socket
|
6
|
+
FcgidIdleTimeout 30
|
7
|
+
FcgidMinProcessesPerClass 0
|
8
|
+
FcgidIdleScanInterval 15
|
9
|
+
</IfModule>
|
10
|
+
|
11
|
+
<Directory "/path/to/hayabusa/tests/fcgi_test">
|
12
|
+
RewriteEngine On
|
13
|
+
RewriteRule ^(.*)\.rhtml$ /hayabusa_fcgi_bin/hayabusa_fcgi.fcgi
|
14
|
+
|
15
|
+
Options +FollowSymLinks
|
16
|
+
|
17
|
+
RequestHeader set HAYABUSA_FCGI_CONFIG "/path/to/hayabusa/tests/fcgi_test/config_fcgi.rb"
|
18
|
+
|
19
|
+
AddHandler fcgid-script .fgci
|
20
|
+
|
21
|
+
DirectoryIndex index.rhtml
|
22
|
+
</Directory>
|
data/hayabusa.gemspec
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{hayabusa}
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Kasper Johansen"]
|
12
|
+
s.date = %q{2012-08-16}
|
13
|
+
s.description = %q{A threadded web/app-server that focuses on threadding, shared ressources, speed and more.}
|
14
|
+
s.email = %q{k@spernj.org}
|
15
|
+
s.executables = ["check_running.rb", "hayabusa_benchmark.rb", "hayabusa_cgi.rb", "hayabusa_fcgi.fcgi", "hayabusa_fcgi.rb", "knjappserver_start.rb"]
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"LICENSE.txt",
|
18
|
+
"README.rdoc"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".document",
|
22
|
+
".rspec",
|
23
|
+
"Gemfile",
|
24
|
+
"Gemfile.lock",
|
25
|
+
"LICENSE.txt",
|
26
|
+
"README.rdoc",
|
27
|
+
"Rakefile",
|
28
|
+
"VERSION",
|
29
|
+
"bin/check_running.rb",
|
30
|
+
"bin/hayabusa_benchmark.rb",
|
31
|
+
"bin/hayabusa_cgi.rb",
|
32
|
+
"bin/hayabusa_fcgi.fcgi",
|
33
|
+
"bin/hayabusa_fcgi.rb",
|
34
|
+
"bin/knjappserver_start.rb",
|
35
|
+
"conf/apache2_cgi_rhtml_conf.conf",
|
36
|
+
"conf/apache2_fcgi_rhtml_conf.conf",
|
37
|
+
"hayabusa.gemspec",
|
38
|
+
"lib/hayabusa.rb",
|
39
|
+
"lib/hayabusa_cgi_session.rb",
|
40
|
+
"lib/hayabusa_cgi_tools.rb",
|
41
|
+
"lib/hayabusa_custom_io.rb",
|
42
|
+
"lib/hayabusa_database.rb",
|
43
|
+
"lib/hayabusa_erb_handler.rb",
|
44
|
+
"lib/hayabusa_ext/cleaner.rb",
|
45
|
+
"lib/hayabusa_ext/cmdline.rb",
|
46
|
+
"lib/hayabusa_ext/errors.rb",
|
47
|
+
"lib/hayabusa_ext/logging.rb",
|
48
|
+
"lib/hayabusa_ext/mailing.rb",
|
49
|
+
"lib/hayabusa_ext/sessions.rb",
|
50
|
+
"lib/hayabusa_ext/threadding.rb",
|
51
|
+
"lib/hayabusa_ext/threadding_timeout.rb",
|
52
|
+
"lib/hayabusa_ext/translations.rb",
|
53
|
+
"lib/hayabusa_ext/web.rb",
|
54
|
+
"lib/hayabusa_http_server.rb",
|
55
|
+
"lib/hayabusa_http_session.rb",
|
56
|
+
"lib/hayabusa_http_session_contentgroup.rb",
|
57
|
+
"lib/hayabusa_http_session_page_environment.rb",
|
58
|
+
"lib/hayabusa_http_session_post_multipart.rb",
|
59
|
+
"lib/hayabusa_http_session_request.rb",
|
60
|
+
"lib/hayabusa_http_session_response.rb",
|
61
|
+
"lib/hayabusa_models.rb",
|
62
|
+
"lib/kernel_ext/gettext_methods.rb",
|
63
|
+
"lib/kernel_ext/magic_methods.rb",
|
64
|
+
"lib/models/log.rb",
|
65
|
+
"lib/models/log_access.rb",
|
66
|
+
"lib/models/log_data.rb",
|
67
|
+
"lib/models/log_data_link.rb",
|
68
|
+
"lib/models/log_data_value.rb",
|
69
|
+
"lib/models/log_link.rb",
|
70
|
+
"lib/models/session.rb",
|
71
|
+
"pages/benchmark.rhtml",
|
72
|
+
"pages/benchmark_print.rhtml",
|
73
|
+
"pages/benchmark_simple.rhtml",
|
74
|
+
"pages/benchmark_threadded_content.rhtml",
|
75
|
+
"pages/debug_database_connections.rhtml",
|
76
|
+
"pages/debug_http_sessions.rhtml",
|
77
|
+
"pages/debug_memory_usage.rhtml",
|
78
|
+
"pages/error_notfound.rhtml",
|
79
|
+
"pages/logs_latest.rhtml",
|
80
|
+
"pages/logs_show.rhtml",
|
81
|
+
"pages/spec.rhtml",
|
82
|
+
"pages/spec_post.rhtml",
|
83
|
+
"pages/spec_test_multiple_clients.rhtml",
|
84
|
+
"pages/spec_thread_joins.rhtml",
|
85
|
+
"pages/spec_threadded_content.rhtml",
|
86
|
+
"pages/tests.rhtml",
|
87
|
+
"spec/cgi_spec.rb",
|
88
|
+
"spec/custom_urls_spec.rb",
|
89
|
+
"spec/fcgi_multiple_processes_spec.rb",
|
90
|
+
"spec/fcgi_spec.rb",
|
91
|
+
"spec/hayabusa_spec.rb",
|
92
|
+
"spec/spec_helper.rb",
|
93
|
+
"tests/cgi_test/config_cgi.rb",
|
94
|
+
"tests/cgi_test/threadded_content_test.rhtml",
|
95
|
+
"tests/cgi_test/vars_get_test.rhtml",
|
96
|
+
"tests/cgi_test/vars_header_test.rhtml",
|
97
|
+
"tests/cgi_test/vars_post_test.rhtml",
|
98
|
+
"tests/fcgi_test/config_fcgi.rb",
|
99
|
+
"tests/fcgi_test/index.rhtml",
|
100
|
+
"tests/fcgi_test/sleeper.rhtml",
|
101
|
+
"tests/fcgi_test/threadded_content_test.rhtml",
|
102
|
+
"tests/fcgi_test/vars_get_test.rhtml",
|
103
|
+
"tests/fcgi_test/vars_header_test.rhtml",
|
104
|
+
"tests/fcgi_test/vars_post_test.rhtml"
|
105
|
+
]
|
106
|
+
s.homepage = %q{http://github.com/kaspernj/hayabusa}
|
107
|
+
s.licenses = ["MIT"]
|
108
|
+
s.require_paths = ["lib"]
|
109
|
+
s.rubygems_version = %q{1.6.2}
|
110
|
+
s.summary = %q{A threadded web/app-server that supports stand-alone, CGI and FCGI-modes.}
|
111
|
+
|
112
|
+
if s.respond_to? :specification_version then
|
113
|
+
s.specification_version = 3
|
114
|
+
|
115
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
116
|
+
s.add_runtime_dependency(%q<knjrbfw>, [">= 0"])
|
117
|
+
s.add_runtime_dependency(%q<erubis>, [">= 0"])
|
118
|
+
s.add_runtime_dependency(%q<mail>, [">= 0"])
|
119
|
+
s.add_runtime_dependency(%q<datet>, [">= 0"])
|
120
|
+
s.add_runtime_dependency(%q<http2>, [">= 0"])
|
121
|
+
s.add_development_dependency(%q<json>, [">= 0"])
|
122
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
123
|
+
s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
|
124
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.3"])
|
125
|
+
s.add_development_dependency(%q<sqlite3>, [">= 0"])
|
126
|
+
else
|
127
|
+
s.add_dependency(%q<knjrbfw>, [">= 0"])
|
128
|
+
s.add_dependency(%q<erubis>, [">= 0"])
|
129
|
+
s.add_dependency(%q<mail>, [">= 0"])
|
130
|
+
s.add_dependency(%q<datet>, [">= 0"])
|
131
|
+
s.add_dependency(%q<http2>, [">= 0"])
|
132
|
+
s.add_dependency(%q<json>, [">= 0"])
|
133
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
134
|
+
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
135
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.3"])
|
136
|
+
s.add_dependency(%q<sqlite3>, [">= 0"])
|
137
|
+
end
|
138
|
+
else
|
139
|
+
s.add_dependency(%q<knjrbfw>, [">= 0"])
|
140
|
+
s.add_dependency(%q<erubis>, [">= 0"])
|
141
|
+
s.add_dependency(%q<mail>, [">= 0"])
|
142
|
+
s.add_dependency(%q<datet>, [">= 0"])
|
143
|
+
s.add_dependency(%q<http2>, [">= 0"])
|
144
|
+
s.add_dependency(%q<json>, [">= 0"])
|
145
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
146
|
+
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
147
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.3"])
|
148
|
+
s.add_dependency(%q<sqlite3>, [">= 0"])
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
data/lib/hayabusa.rb
ADDED
@@ -0,0 +1,518 @@
|
|
1
|
+
require "base64"
|
2
|
+
require "digest"
|
3
|
+
require "stringio"
|
4
|
+
require "timeout"
|
5
|
+
|
6
|
+
#The class that stands for the whole appserver / webserver.
|
7
|
+
#===Examples
|
8
|
+
# appsrv = Hayabusa.new(
|
9
|
+
# :locales_root => "/some/path/locales",
|
10
|
+
# :locales_gettext_funcs => true,
|
11
|
+
# :magic_methods => true
|
12
|
+
# )
|
13
|
+
# appsrv.start
|
14
|
+
# appsrv.join
|
15
|
+
class Hayabusa
|
16
|
+
@@path = File.dirname(__FILE__)
|
17
|
+
|
18
|
+
attr_reader :cio, :config, :httpserv, :debug, :db, :db_handler, :ob, :translations, :paused, :should_restart, :events, :mod_event, :db_handler, :gettext, :sessions, :logs_access_pending, :threadpool, :vars, :magic_procs, :magic_vars, :types, :eruby_cache, :httpsessions_ids
|
19
|
+
attr_accessor :served, :should_restart, :should_restart_done
|
20
|
+
|
21
|
+
#Autoloader for subclasses.
|
22
|
+
def self.const_missing(name)
|
23
|
+
require "#{File.dirname(__FILE__)}/hayabusa_#{name.to_s.downcase}.rb"
|
24
|
+
return Hayabusa.const_get(name)
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(config)
|
28
|
+
raise "No arguments given." if !config.is_a?(Hash)
|
29
|
+
|
30
|
+
@config = {
|
31
|
+
:host => "0.0.0.0",
|
32
|
+
:timeout => 30,
|
33
|
+
:default_page => "index.rhtml",
|
34
|
+
:default_filetype => "text/html",
|
35
|
+
:max_requests_working => 20,
|
36
|
+
:size_send => 1024,
|
37
|
+
:cleaner_timeout => 300
|
38
|
+
}.merge(config)
|
39
|
+
|
40
|
+
@config[:smtp_args] = {"smtp_host" => "localhost", "smtp_port" => 25} if !@config[:smtp_args]
|
41
|
+
@config[:timeout] = 30 if !@config.has_key?(:timeout)
|
42
|
+
raise "No ':doc_root' was given in arguments." if !@config.has_key?(:doc_root)
|
43
|
+
|
44
|
+
|
45
|
+
#Require gems.
|
46
|
+
require "rubygems"
|
47
|
+
gems = [
|
48
|
+
[:Erubis, "erubis"],
|
49
|
+
[:Knj, "knjrbfw"],
|
50
|
+
[:Tsafe, "tsafe"]
|
51
|
+
]
|
52
|
+
|
53
|
+
gems.each do |gem|
|
54
|
+
if Kernel.const_defined?(gem[0])
|
55
|
+
puts "Gem already loaded: '#{gem[1]}'." if @debug
|
56
|
+
next
|
57
|
+
end
|
58
|
+
|
59
|
+
fpath = "#{@@path}/../../#{gem[1]}/lib/#{gem[1]}.rb"
|
60
|
+
|
61
|
+
if File.exists?(fpath)
|
62
|
+
puts "Loading custom gem-path: '#{fpath}'." if @debug
|
63
|
+
require fpath
|
64
|
+
else
|
65
|
+
puts "Loading gem: '#{gem[1]}'." if @debug
|
66
|
+
require gem[1]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
#Setup default handlers if none are given.
|
72
|
+
if !@config.has_key?(:handlers)
|
73
|
+
@erb_handler = Hayabusa::Erb_handler.new
|
74
|
+
@config[:handlers] = [
|
75
|
+
{
|
76
|
+
:file_ext => "rhtml",
|
77
|
+
:callback => @erb_handler.method(:erb_handler)
|
78
|
+
},{
|
79
|
+
:path => "/fckeditor",
|
80
|
+
:mount => "/usr/share/fckeditor"
|
81
|
+
}
|
82
|
+
]
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
#Add extra handlers if given.
|
87
|
+
@config[:handlers] += @config[:handlers_extra] if @config[:handlers_extra]
|
88
|
+
|
89
|
+
|
90
|
+
#Setup cache to make .rhtml-calls faster.
|
91
|
+
@config[:handlers_cache] = {}
|
92
|
+
@config[:handlers].each do |handler_info|
|
93
|
+
next if !handler_info[:file_ext] or !handler_info[:callback]
|
94
|
+
@config[:handlers_cache][handler_info[:file_ext]] = handler_info[:callback]
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
@debug = @config[:debug]
|
99
|
+
@paused = 0
|
100
|
+
@paused_mutex = Mutex.new
|
101
|
+
@should_restart = false
|
102
|
+
@mod_events = {}
|
103
|
+
@served = 0
|
104
|
+
@mod_files = {}
|
105
|
+
@sessions = {}
|
106
|
+
@eruby_cache = {}
|
107
|
+
@httpsessions_ids = {}
|
108
|
+
|
109
|
+
@path_hayabusa = File.dirname(__FILE__)
|
110
|
+
|
111
|
+
|
112
|
+
#If auto-restarting is enabled - start the modified events-module.
|
113
|
+
if @config[:autorestart]
|
114
|
+
paths = [
|
115
|
+
"#{@path_hayabusa}/class_customio.rb"
|
116
|
+
]
|
117
|
+
|
118
|
+
print "Auto restarting.\n" if @debug
|
119
|
+
@mod_event = Knj::Event_filemod.new(:wait => 2, :paths => paths, &self.method(:on_event_filemod))
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
#Set up default file-types and merge given filetypes into it.
|
124
|
+
@types = {
|
125
|
+
:ico => "image/x-icon",
|
126
|
+
:jpeg => "image/jpeg",
|
127
|
+
:jpg => "image/jpeg",
|
128
|
+
:gif => "image/gif",
|
129
|
+
:png => "image/png",
|
130
|
+
:html => "text/html",
|
131
|
+
:htm => "text/html",
|
132
|
+
:rhtml => "text/html",
|
133
|
+
:css => "text/css",
|
134
|
+
:xml => "text/xml",
|
135
|
+
:js => "text/javascript"
|
136
|
+
}
|
137
|
+
@types.merge!(@config[:filetypes]) if @config.key?(:filetypes)
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
#Load various required files in the hayabusa-framework.
|
142
|
+
files = [
|
143
|
+
"#{@path_hayabusa}/hayabusa_ext/errors.rb",
|
144
|
+
"#{@path_hayabusa}/hayabusa_ext/logging.rb",
|
145
|
+
"#{@path_hayabusa}/hayabusa_ext/mailing.rb",
|
146
|
+
"#{@path_hayabusa}/hayabusa_ext/sessions.rb",
|
147
|
+
"#{@path_hayabusa}/hayabusa_ext/translations.rb",
|
148
|
+
"#{@path_hayabusa}/hayabusa_ext/web.rb"
|
149
|
+
]
|
150
|
+
|
151
|
+
files.each do |file|
|
152
|
+
STDOUT.print "Loading: '#{file}'.\n" if @debug
|
153
|
+
self.loadfile(file)
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
print "Setting up database.\n" if @debug
|
158
|
+
if @config[:db].is_a?(Knj::Db)
|
159
|
+
@db = @config[:db]
|
160
|
+
elsif @config[:db].is_a?(Hash)
|
161
|
+
@db = Knj::Db.new(@config[:db])
|
162
|
+
elsif !@config[:db] and @config[:db_args]
|
163
|
+
@db = Knj::Db.new(@config[:db_args])
|
164
|
+
else
|
165
|
+
if @config[:title]
|
166
|
+
db_title = @config[:title]
|
167
|
+
else
|
168
|
+
db_title = Time.now.to_f.to_s.hash
|
169
|
+
end
|
170
|
+
|
171
|
+
db_path = "#{Knj::Os.tmpdir}/hayabusa_fallback_db_#{db_title}.sqlite3"
|
172
|
+
@config[:dbrev] = true
|
173
|
+
|
174
|
+
require "sqlite3" if RUBY_ENGINE != "jruby"
|
175
|
+
@db = Knj::Db.new(
|
176
|
+
:type => "sqlite3",
|
177
|
+
:path => db_path,
|
178
|
+
:return_keys => "symbols",
|
179
|
+
:index_append_table_name => true
|
180
|
+
)
|
181
|
+
end
|
182
|
+
|
183
|
+
|
184
|
+
if !@config.key?(:dbrev) or @config[:dbrev]
|
185
|
+
print "Updating database.\n" if @debug
|
186
|
+
dbrev_args = {"schema" => Hayabusa::Database::SCHEMA, "db" => @db}
|
187
|
+
dbrev_args.merge!(@config[:dbrev_args]) if @config.key?(:dbrev_args)
|
188
|
+
Knj::Db::Revision.new.init_db(dbrev_args)
|
189
|
+
dbrev_args = nil
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
print "Spawning objects.\n" if @debug
|
194
|
+
@ob = Knj::Objects.new(
|
195
|
+
:db => db,
|
196
|
+
:class_path => @path_hayabusa,
|
197
|
+
:module => Hayabusa::Models,
|
198
|
+
:datarow => true,
|
199
|
+
:hayabusa => self,
|
200
|
+
:require => false
|
201
|
+
)
|
202
|
+
@ob.events.connect(:no_date, &self.method(:no_date))
|
203
|
+
|
204
|
+
|
205
|
+
if @config[:httpsession_db_args]
|
206
|
+
@db_handler = Knj::Db.new(@config[:httpsession_db_args])
|
207
|
+
else
|
208
|
+
@db_handler = @db
|
209
|
+
end
|
210
|
+
|
211
|
+
|
212
|
+
if @config[:locales_root]
|
213
|
+
@gettext = Knj::Gettext_threadded.new("dir" => config[:locales_root])
|
214
|
+
end
|
215
|
+
|
216
|
+
require "#{@path_hayabusa}/kernel_ext/gettext_methods" if @config[:locales_gettext_funcs]
|
217
|
+
|
218
|
+
if @config[:magic_methods] or !@config.has_key?(:magic_methods)
|
219
|
+
print "Loading magic-methods.\n" if @debug
|
220
|
+
require "#{@path_hayabusa}/kernel_ext/magic_methods"
|
221
|
+
end
|
222
|
+
|
223
|
+
if @config[:customio] or !@config.has_key?(:customio)
|
224
|
+
print "Loading custom-io.\n" if @debug
|
225
|
+
|
226
|
+
if $stdout.class.name != "Hayabusa::Custom_io"
|
227
|
+
@cio = Hayabusa::Custom_io.new
|
228
|
+
$stdout = @cio
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
#Save the PID to the run-file.
|
234
|
+
print "Setting run-file.\n" if @debug
|
235
|
+
tmpdir = "#{Knj::Os.tmpdir}/hayabusa"
|
236
|
+
tmppath = "#{tmpdir}/run_#{@config[:title]}"
|
237
|
+
|
238
|
+
if !File.exists?(tmpdir)
|
239
|
+
Dir.mkdir(tmpdir)
|
240
|
+
File.chmod(0777, tmpdir)
|
241
|
+
end
|
242
|
+
|
243
|
+
File.open(tmppath, "w") do |fp|
|
244
|
+
fp.write(Process.pid)
|
245
|
+
end
|
246
|
+
File.chmod(0777, tmppath)
|
247
|
+
|
248
|
+
|
249
|
+
#Set up various events for the appserver.
|
250
|
+
if !@config.key?(:events) or @config[:events]
|
251
|
+
print "Loading events.\n" if @debug
|
252
|
+
@events = Knj::Event_handler.new
|
253
|
+
@events.add_event(
|
254
|
+
:name => :check_page_access,
|
255
|
+
:connections_max => 1
|
256
|
+
)
|
257
|
+
@events.add_event(
|
258
|
+
:name => :ob,
|
259
|
+
:connections_max => 1
|
260
|
+
)
|
261
|
+
@events.add_event(
|
262
|
+
:name => :trans_no_str,
|
263
|
+
:connections_max => 1
|
264
|
+
)
|
265
|
+
@events.add_event(
|
266
|
+
:name => :request_done,
|
267
|
+
:connections_max => 1
|
268
|
+
)
|
269
|
+
@events.add_event(
|
270
|
+
:name => :request_begin,
|
271
|
+
:connections_max => 1
|
272
|
+
)
|
273
|
+
|
274
|
+
#This event is used if the user himself wants stuff to be cleaned up when the appserver is cleaning up stuff.
|
275
|
+
@events.add_event(
|
276
|
+
:name => :on_clean
|
277
|
+
)
|
278
|
+
end
|
279
|
+
|
280
|
+
#Set up the 'vars'-variable that can be used to set custom global variables for web-requests.
|
281
|
+
@vars = Knj::Hash_methods.new
|
282
|
+
@magic_vars = {}
|
283
|
+
@magic_procs = {}
|
284
|
+
|
285
|
+
|
286
|
+
#Initialize the various feature-modules.
|
287
|
+
print "Init sessions.\n" if @debug
|
288
|
+
self.initialize_sessions
|
289
|
+
|
290
|
+
if !@config.key?(:threadding) or @config[:threadding]
|
291
|
+
self.loadfile("#{@path_hayabusa}/hayabusa_ext/threadding.rb")
|
292
|
+
self.loadfile("#{@path_hayabusa}/hayabusa_ext/threadding_timeout.rb")
|
293
|
+
print "Init threadding.\n" if @debug
|
294
|
+
self.initialize_threadding
|
295
|
+
end
|
296
|
+
|
297
|
+
print "Init mailing.\n" if @debug
|
298
|
+
self.initialize_mailing
|
299
|
+
|
300
|
+
print "Init errors.\n" if @debug
|
301
|
+
self.initialize_errors
|
302
|
+
|
303
|
+
print "Init logging.\n" if @debug
|
304
|
+
self.initialize_logging
|
305
|
+
|
306
|
+
if !@config.key?(:cleaner) or @config[:cleaner]
|
307
|
+
self.loadfile("#{@path_hayabusa}/hayabusa_ext/cleaner.rb")
|
308
|
+
print "Init cleaner.\n" if @debug
|
309
|
+
self.initialize_cleaner
|
310
|
+
end
|
311
|
+
|
312
|
+
if !@config.key?(:cmdline) or @config[:cmdline]
|
313
|
+
self.loadfile("#{@path_hayabusa}/hayabusa_ext/cmdline.rb")
|
314
|
+
print "Init cmdline.\n" if @debug
|
315
|
+
self.initialize_cmdline
|
316
|
+
end
|
317
|
+
|
318
|
+
|
319
|
+
#Clear memory at exit.
|
320
|
+
Kernel.at_exit(&self.method(:stop))
|
321
|
+
|
322
|
+
|
323
|
+
print "Appserver spawned.\n" if @debug
|
324
|
+
end
|
325
|
+
|
326
|
+
def no_date(event, classname)
|
327
|
+
return "[no date]"
|
328
|
+
end
|
329
|
+
|
330
|
+
def on_event_filemod(event, path)
|
331
|
+
print "File changed - restart server: #{path}\n"
|
332
|
+
@should_restart = true
|
333
|
+
@mod_event.destroy if @mod_event
|
334
|
+
end
|
335
|
+
|
336
|
+
#If you want to use auto-restart, every file reloaded through loadfile will be watched for changes. When changed the server will do a restart to reflect that.
|
337
|
+
def loadfile(fpath)
|
338
|
+
if !@config[:autorestart]
|
339
|
+
require fpath
|
340
|
+
return nil
|
341
|
+
end
|
342
|
+
|
343
|
+
rpath = File.realpath(fpath)
|
344
|
+
raise "No such filepath: #{fpath}" if !rpath or !File.exists?(rpath)
|
345
|
+
|
346
|
+
return true if @mod_files[rpath]
|
347
|
+
|
348
|
+
@mod_event.args[:paths] << rpath
|
349
|
+
@mod_files = rpath
|
350
|
+
|
351
|
+
require rpath
|
352
|
+
return false
|
353
|
+
end
|
354
|
+
|
355
|
+
#Start a new CGI-request.
|
356
|
+
def start_cgi_request
|
357
|
+
@cgi_http_session = Hayabusa::Cgi_session.new(:hb => self)
|
358
|
+
end
|
359
|
+
|
360
|
+
#Starts the HTTP-server and threadpool.
|
361
|
+
def start
|
362
|
+
#Start the appserver.
|
363
|
+
print "Spawning appserver.\n" if @debug
|
364
|
+
@httpserv = Hayabusa::Http_server.new(self)
|
365
|
+
|
366
|
+
|
367
|
+
STDOUT.print "Starting appserver.\n" if @debug
|
368
|
+
Thread.current[:hayabusa] = {:hb => self} if !Thread.current[:hayabusa]
|
369
|
+
|
370
|
+
if @config[:autoload]
|
371
|
+
STDOUT.print "Autoloading #{@config[:autoload]}\n" if @debug
|
372
|
+
require @config[:autoload]
|
373
|
+
end
|
374
|
+
|
375
|
+
begin
|
376
|
+
@threadpool.start if @threadpool
|
377
|
+
STDOUT.print "Threadpool startet.\n" if @debug
|
378
|
+
@httpserv.start
|
379
|
+
STDOUT.print "Appserver startet.\n" if @debug
|
380
|
+
rescue Interrupt => e
|
381
|
+
STDOUT.print "Got interrupt - trying to stop appserver.\n" if @debug
|
382
|
+
self.stop
|
383
|
+
raise e
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
#Stops the entire app and releases join.
|
388
|
+
def stop
|
389
|
+
return nil if @stop_called
|
390
|
+
@stop_called = true
|
391
|
+
|
392
|
+
proc_stop = proc{
|
393
|
+
STDOUT.print "Stopping appserver.\n" if @debug
|
394
|
+
@httpserv.stop if @httpserv and @httpserv.respond_to?(:stop)
|
395
|
+
|
396
|
+
STDOUT.print "Stopping threadpool.\n" if @debug
|
397
|
+
@threadpool.stop if @threadpool
|
398
|
+
|
399
|
+
#This should be done first to be sure it finishes (else we have a serious bug).
|
400
|
+
STDOUT.print "Flush out loaded sessions.\n" if @debug
|
401
|
+
self.sessions_flush
|
402
|
+
|
403
|
+
STDOUT.print "Stopping done...\n" if @debug
|
404
|
+
}
|
405
|
+
|
406
|
+
#If we cant get a paused-execution in 5 secs - we just force the stop.
|
407
|
+
begin
|
408
|
+
Timeout.timeout(5) do
|
409
|
+
self.paused_exec(&proc_stop)
|
410
|
+
end
|
411
|
+
rescue Timeout::Error, SystemExit, Interrupt
|
412
|
+
STDOUT.print "Forcing stop-appserver - couldnt get timing window.\n" if @debug
|
413
|
+
proc_stop.call
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
#Stop running any more HTTP-requests - make them wait.
|
418
|
+
def pause
|
419
|
+
@paused += 1
|
420
|
+
end
|
421
|
+
|
422
|
+
#Unpause - start handeling HTTP-requests again.
|
423
|
+
def unpause
|
424
|
+
@paused -= 1
|
425
|
+
end
|
426
|
+
|
427
|
+
#Returns true if paued - otherwise false.
|
428
|
+
def paused?
|
429
|
+
return true if @paused > 0
|
430
|
+
return false
|
431
|
+
end
|
432
|
+
|
433
|
+
#Will stop handeling any more HTTP-requests, run the proc given and return handeling HTTP-requests.
|
434
|
+
def paused_exec
|
435
|
+
raise "No block given." if !block_given?
|
436
|
+
self.pause
|
437
|
+
|
438
|
+
begin
|
439
|
+
sleep 0.2 while @httpserv and @httpserv.working_count and @httpserv.working_count > 0
|
440
|
+
@paused_mutex.synchronize do
|
441
|
+
Timeout.timeout(15) do
|
442
|
+
yield
|
443
|
+
end
|
444
|
+
end
|
445
|
+
ensure
|
446
|
+
self.unpause
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
#Returns true if a HTTP-request is working. Otherwise false.
|
451
|
+
def working?
|
452
|
+
return true if @httpserv and @httpserv.working_count > 0
|
453
|
+
return false
|
454
|
+
end
|
455
|
+
|
456
|
+
def self.data
|
457
|
+
raise "Could not register current thread." if !Thread.current[:hayabusa]
|
458
|
+
return Thread.current[:hayabusa]
|
459
|
+
end
|
460
|
+
|
461
|
+
#Sleeps until the server is stopped.
|
462
|
+
def join
|
463
|
+
raise "No http-server or http-server not running." if !@httpserv or !@httpserv.thread_accept
|
464
|
+
|
465
|
+
begin
|
466
|
+
@httpserv.thread_accept.join
|
467
|
+
@httpserv.thread_restart.join if @httpserv and @httpserv.thread_restart
|
468
|
+
rescue Interrupt => e
|
469
|
+
self.stop
|
470
|
+
end
|
471
|
+
|
472
|
+
if @should_restart
|
473
|
+
loop do
|
474
|
+
if @should_restart_done
|
475
|
+
STDOUT.print "Ending join because the restart is done.\n"
|
476
|
+
break
|
477
|
+
end
|
478
|
+
|
479
|
+
sleep 1
|
480
|
+
end
|
481
|
+
end
|
482
|
+
end
|
483
|
+
|
484
|
+
#Defines a variable as a method bound to the threads spawned by this instance of Hayabusa.
|
485
|
+
def define_magic_var(method_name, var)
|
486
|
+
@magic_vars[method_name] = var
|
487
|
+
|
488
|
+
if !Object.respond_to?(method_name)
|
489
|
+
Object.send(:define_method, method_name) do
|
490
|
+
return Thread.current[:hayabusa][:hb].magic_vars[method_name] if Thread.current[:hayabusa] and Thread.current[:hayabusa][:hb]
|
491
|
+
raise "Could not figure out the object: '#{method_name}'."
|
492
|
+
end
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
def define_magic_proc(method_name, &block)
|
497
|
+
raise "No block given." if !block_given?
|
498
|
+
@magic_procs[method_name] = block
|
499
|
+
|
500
|
+
if !Object.respond_to?(method_name)
|
501
|
+
Object.send(:define_method, method_name) do
|
502
|
+
return Thread.current[:hayabusa][:hb].magic_procs[method_name].call(:hb => self) if Thread.current[:hayabusa] and Thread.current[:hayabusa][:hb]
|
503
|
+
raise "Could not figure out the object: '#{method_name}'."
|
504
|
+
end
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
def translations
|
509
|
+
if !@translations
|
510
|
+
#Start the Knj::Gettext_threadded- and Knj::Translations modules for translations.
|
511
|
+
print "Loading Gettext and translations.\n" if @debug
|
512
|
+
@translations = Knj::Translations.new(:db => @db)
|
513
|
+
@ob.requireclass(:Translation, :require => false, :class => Knj::Translations::Translation)
|
514
|
+
end
|
515
|
+
|
516
|
+
return @translations
|
517
|
+
end
|
518
|
+
end
|