waw 0.2.2
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/LICENCE.rdoc +25 -0
- data/README.rdoc +32 -0
- data/bin/waw +32 -0
- data/bin/waw-profile +26 -0
- data/bin/waw-start +26 -0
- data/bin/wspec +33 -0
- data/layouts/empty/Rakefile +14 -0
- data/layouts/empty/config.ru +5 -0
- data/layouts/empty/config/commons.cfg +31 -0
- data/layouts/empty/config/devel.cfg +21 -0
- data/layouts/empty/ignore +7 -0
- data/layouts/empty/logs/dontforgetme +0 -0
- data/layouts/empty/resources/messages.rs +1 -0
- data/layouts/empty/test/wspec/site_respond.wspec +3 -0
- data/layouts/empty/test/wspec/test_all.rb +13 -0
- data/layouts/empty/waw.deploy +1 -0
- data/layouts/empty/waw.routing +6 -0
- data/layouts/static/dependencies +1 -0
- data/layouts/static/public/.wawaccess +18 -0
- data/layouts/static/public/css/style.css +0 -0
- data/layouts/static/public/images/dontforgetme +0 -0
- data/layouts/static/public/js/project.js +0 -0
- data/layouts/static/public/pages/.wawaccess +30 -0
- data/layouts/static/public/pages/404.wtpl +1 -0
- data/layouts/static/public/pages/index.wtpl +5 -0
- data/layouts/static/public/templates/.wawaccess +9 -0
- data/layouts/static/public/templates/layout.wtpl +17 -0
- data/layouts/static/test/wspec/static_pages_are_served.wspec +21 -0
- data/layouts/static/waw.routing +8 -0
- data/lib/waw.rb +99 -0
- data/lib/waw/commands/command.rb +115 -0
- data/lib/waw/commands/profile_command.rb +66 -0
- data/lib/waw/commands/start_command.rb +59 -0
- data/lib/waw/config.rb +110 -0
- data/lib/waw/controller.rb +25 -0
- data/lib/waw/controllers/action/action.rb +91 -0
- data/lib/waw/controllers/action/action_utils.rb +30 -0
- data/lib/waw/controllers/action/js_generation.rb +116 -0
- data/lib/waw/controllers/action_controller.rb +133 -0
- data/lib/waw/controllers/error/backtrace.rb +54 -0
- data/lib/waw/controllers/error_handler.rb +62 -0
- data/lib/waw/controllers/json_controller.rb +31 -0
- data/lib/waw/controllers/no_cache.rb +22 -0
- data/lib/waw/controllers/static/match.rb +80 -0
- data/lib/waw/controllers/static/waw_access.rb +235 -0
- data/lib/waw/controllers/static/waw_access_dsl.rb +48 -0
- data/lib/waw/controllers/static_controller.rb +37 -0
- data/lib/waw/default_config.cfg +14 -0
- data/lib/waw/environment_utils.rb +57 -0
- data/lib/waw/errors.rb +4 -0
- data/lib/waw/ext.rb +3 -0
- data/lib/waw/ext/core.rb +4 -0
- data/lib/waw/ext/core/hash.rb +47 -0
- data/lib/waw/ext/core/logger.rb +10 -0
- data/lib/waw/ext/core/module.rb +20 -0
- data/lib/waw/ext/core/object.rb +29 -0
- data/lib/waw/ext/rack.rb +19 -0
- data/lib/waw/ext/rack/builder.rb +43 -0
- data/lib/waw/ext/rack/delegator.rb +51 -0
- data/lib/waw/ext/rack/urlmap.rb +55 -0
- data/lib/waw/ext/wlang.rb +1 -0
- data/lib/waw/ext/wlang/hosted_language.rb +21 -0
- data/lib/waw/fullstate.rb +8 -0
- data/lib/waw/fullstate/on_class.rb +37 -0
- data/lib/waw/fullstate/on_instance.rb +27 -0
- data/lib/waw/fullstate/variable.rb +36 -0
- data/lib/waw/kern.rb +6 -0
- data/lib/waw/kern/app.rb +48 -0
- data/lib/waw/kern/empty/waw.deploy +0 -0
- data/lib/waw/kern/empty/waw.routing +1 -0
- data/lib/waw/kern/freezed_state.rb +32 -0
- data/lib/waw/kern/hooks.rb +53 -0
- data/lib/waw/kern/lifecycle.rb +248 -0
- data/lib/waw/kern/living_state.rb +87 -0
- data/lib/waw/kern/utils.rb +27 -0
- data/lib/waw/resource_collection.rb +100 -0
- data/lib/waw/restart.rb +32 -0
- data/lib/waw/routing.rb +43 -0
- data/lib/waw/routing/action_routing.rb +78 -0
- data/lib/waw/routing/dsl.rb +45 -0
- data/lib/waw/routing/feedback.rb +23 -0
- data/lib/waw/routing/form_validation_feedback.rb +36 -0
- data/lib/waw/routing/javascript.rb +17 -0
- data/lib/waw/routing/redirect.rb +26 -0
- data/lib/waw/routing/refresh.rb +17 -0
- data/lib/waw/routing/routing_rule.rb +16 -0
- data/lib/waw/scope_utils.rb +69 -0
- data/lib/waw/session.rb +51 -0
- data/lib/waw/testing.rb +1 -0
- data/lib/waw/tools/mail.rb +4 -0
- data/lib/waw/tools/mail/mail.rb +119 -0
- data/lib/waw/tools/mail/mail_agent.rb +123 -0
- data/lib/waw/tools/mail/mailbox.rb +62 -0
- data/lib/waw/tools/mail/template.rb +38 -0
- data/lib/waw/utils/dsl_helper.rb +116 -0
- data/lib/waw/validation.rb +175 -0
- data/lib/waw/validation/and_validator.rb +27 -0
- data/lib/waw/validation/array_validations.rb +38 -0
- data/lib/waw/validation/boolean_validator.rb +32 -0
- data/lib/waw/validation/comparison_validations.rb +45 -0
- data/lib/waw/validation/date_validator.rb +31 -0
- data/lib/waw/validation/default_validator.rb +30 -0
- data/lib/waw/validation/dsl_ruby_extensions.rb +11 -0
- data/lib/waw/validation/errors.rb +17 -0
- data/lib/waw/validation/ext.rb +3 -0
- data/lib/waw/validation/file_validator.rb +30 -0
- data/lib/waw/validation/float_validator.rb +19 -0
- data/lib/waw/validation/helpers.rb +67 -0
- data/lib/waw/validation/integer_validator.rb +16 -0
- data/lib/waw/validation/isin_validator.rb +24 -0
- data/lib/waw/validation/mandatory_validator.rb +17 -0
- data/lib/waw/validation/missing_validator.rb +17 -0
- data/lib/waw/validation/not_validator.rb +20 -0
- data/lib/waw/validation/or_validator.rb +34 -0
- data/lib/waw/validation/regexp_validator.rb +29 -0
- data/lib/waw/validation/same_validator.rb +16 -0
- data/lib/waw/validation/signature.rb +157 -0
- data/lib/waw/validation/size_validations.rb +44 -0
- data/lib/waw/validation/string_validator.rb +15 -0
- data/lib/waw/validation/validator.rb +48 -0
- data/lib/waw/wawgen.rb +2 -0
- data/lib/waw/wawgen/create.rb +166 -0
- data/lib/waw/wawgen/project.rb +25 -0
- data/lib/waw/wspec.rb +5 -0
- data/lib/waw/wspec/browser.rb +240 -0
- data/lib/waw/wspec/dsl.rb +201 -0
- data/lib/waw/wspec/html_analysis.rb +136 -0
- data/lib/waw/wspec/html_analysis/tag.rb +56 -0
- data/lib/waw/wspec/runner.rb +70 -0
- data/lib/waw/wspec/scenario.rb +35 -0
- data/lib/waw/wspec/suite.rb +54 -0
- data/test/bricks/error_handler/config/test.cfg +2 -0
- data/test/bricks/error_handler/logs/webapp.log +1411 -0
- data/test/bricks/error_handler/test/error_handler.wspec +16 -0
- data/test/bricks/error_handler/waw.deploy +1 -0
- data/test/bricks/error_handler/waw.routing +27 -0
- data/test/integration/waw_create_integration_test.rb +24 -0
- data/test/spec/assumptions_spec.rb +30 -0
- data/test/spec/controllers/action_controller_spec.rb +14 -0
- data/test/spec/controllers/static/waw_access_spec.rb +112 -0
- data/test/spec/environment_utils_spec.rb +15 -0
- data/test/spec/ext/core/hash_spec.rb +58 -0
- data/test/spec/fixtures.rb +41 -0
- data/test/spec/fixtures/action/config/default.cfg +2 -0
- data/test/spec/fixtures/action/lib/action_controller_test.rb +12 -0
- data/test/spec/fixtures/action/waw.deploy +1 -0
- data/test/spec/fixtures/action/waw.routing +6 -0
- data/test/spec/fixtures/empty/waw.deploy +0 -0
- data/test/spec/fixtures/empty/waw.routing +0 -0
- data/test/spec/fullstate/on_class_spec.rb +59 -0
- data/test/spec/fullstate/on_instance_spec.rb +59 -0
- data/test/spec/fullstate/session_spec.rb +43 -0
- data/test/spec/fullstate/variable_spec.rb +55 -0
- data/test/spec/resource_collection_spec.rb +50 -0
- data/test/spec/test_all.rb +9 -0
- data/test/spec/tools/mail/mail_agent_spec.rb +116 -0
- data/test/spec/tools/mail/mail_spec.rb +56 -0
- data/test/spec/tools/mail/mailbox_spec.rb +57 -0
- data/test/spec/tools/mail/template_spec.rb +47 -0
- data/test/spec/validation/array_validation_spec.rb +63 -0
- data/test/spec/validation/array_validator_spec.rb +17 -0
- data/test/spec/validation/date_validation_spec.rb +35 -0
- data/test/spec/validation/default_validation_spec.rb +37 -0
- data/test/spec/validation/disjuctive_validation_spec.rb +33 -0
- data/test/spec/validation/errors_spec.rb +37 -0
- data/test/spec/validation/file_validator_spec.rb +34 -0
- data/test/spec/validation/mail_validation_spec.rb +51 -0
- data/test/spec/validation/missing_validation_spec.rb +43 -0
- data/test/spec/validation/same_validation_spec.rb +24 -0
- data/test/spec/validation/signature_intuition_spec.rb +37 -0
- data/test/spec/validation/signature_spec.rb +164 -0
- data/test/spec/validation/validation_spec.rb +28 -0
- data/test/spec/wspec/html_analysis/tag_spec.rb +38 -0
- data/test/spec/wspec/html_analysis_spec.rb +170 -0
- data/test/unit/test_all.rb +8 -0
- data/test/unit/waw/app_test.rb +126 -0
- data/test/unit/waw/app_test/config/commons.cfg +2 -0
- data/test/unit/waw/app_test/config/devel.cfg +1 -0
- data/test/unit/waw/config_test.rb +54 -0
- data/test/unit/waw/controllers/action_controller_test.rb +76 -0
- data/test/unit/waw/controllers/action_test.rb +35 -0
- data/test/unit/waw/controllers/example_action_controller_test.rb +24 -0
- data/test/unit/waw/controllers/multiple_action_controller_test.rb +78 -0
- data/test/unit/waw/controllers/static/example/css/example.css +1 -0
- data/test/unit/waw/controllers/static/example/index.html +1 -0
- data/test/unit/waw/controllers/static/example/js/example.js +1 -0
- data/test/unit/waw/controllers/static/example/pages/hello.wtpl +1 -0
- data/test/unit/waw/controllers/static/waw_access_test.rb +76 -0
- data/test/unit/waw/ext/rack_test.rb +74 -0
- data/test/unit/waw/resource_collection_test.rb +49 -0
- data/test/unit/waw/resources.txt +4 -0
- data/test/unit/waw/routing/routing_test.rb +26 -0
- data/test/unit/waw/utils/dsl_helper_test.rb +79 -0
- data/test/unit/waw/utils/dsl_helper_test_extensions1.rb +4 -0
- data/test/unit/waw/validation/signature_test.rb +193 -0
- data/test/unit/waw/validation_test.rb +319 -0
- data/test/unit/waw/wspec/html_analysis_test.html +81 -0
- data/test/unit/waw/wspec/html_analysis_test.rb +26 -0
- metadata +272 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require 'optparse'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
module Waw
|
|
4
|
+
module Commands
|
|
5
|
+
class Command
|
|
6
|
+
|
|
7
|
+
# The verbose level
|
|
8
|
+
attr_accessor :verbose
|
|
9
|
+
|
|
10
|
+
# Show stack traces?
|
|
11
|
+
attr_accessor :trace
|
|
12
|
+
|
|
13
|
+
# Creates an empty command instance
|
|
14
|
+
def initialize
|
|
15
|
+
@verbose = false
|
|
16
|
+
@buffer = STDOUT
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Parses commandline options provided as an array of Strings.
|
|
20
|
+
def options
|
|
21
|
+
@options ||= OptionParser.new do |opt|
|
|
22
|
+
opt.program_name = File.basename $0
|
|
23
|
+
opt.version = Waw::VERSION
|
|
24
|
+
opt.release = nil
|
|
25
|
+
opt.summary_indent = ' ' * 4
|
|
26
|
+
banner = self.banner
|
|
27
|
+
opt.banner = banner.gsub(/^[ \t]+/, "")
|
|
28
|
+
|
|
29
|
+
opt.separator nil
|
|
30
|
+
opt.separator "Options:"
|
|
31
|
+
|
|
32
|
+
add_options(opt)
|
|
33
|
+
|
|
34
|
+
opt.on("--trace", "Display stack trace on error?") do |value|
|
|
35
|
+
@trace = true
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
opt.on("--verbose", "-v", "Display extra progress as we progress") do |value|
|
|
39
|
+
@verbose = true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# No argument, shows at tail. This will print an options summary.
|
|
43
|
+
# Try it and see!
|
|
44
|
+
opt.on_tail("-h", "--help", "Show this message") do
|
|
45
|
+
puts options
|
|
46
|
+
exit
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Another typical switch to print the version.
|
|
50
|
+
opt.on_tail("--version", "Show version") do
|
|
51
|
+
puts opt.program_name << Waw::VERSION << " (c) University of Louvain, Bernard & Louis Lambeau"
|
|
52
|
+
exit
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
opt.separator nil
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Runs the command
|
|
60
|
+
def run(requester_file, argv)
|
|
61
|
+
@requester_file = requester_file
|
|
62
|
+
check_command_policy
|
|
63
|
+
__run(requester_file, options.parse!(argv))
|
|
64
|
+
rescue OptionParser::InvalidOption => ex
|
|
65
|
+
exit ex.message
|
|
66
|
+
rescue SystemExit
|
|
67
|
+
rescue Exception => ex
|
|
68
|
+
error <<-EOF
|
|
69
|
+
A severe error occured. Please report this to the developers.
|
|
70
|
+
Try --trace if the trace does not appear
|
|
71
|
+
|
|
72
|
+
#{ex.class}: #{ex.message}
|
|
73
|
+
EOF
|
|
74
|
+
error ex.backtrace.join("\n") if trace
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def shell_exec(what)
|
|
78
|
+
info "shell: #{what}" if verbose
|
|
79
|
+
info `#{what}`
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Exits with a message, showing options if required
|
|
83
|
+
def exit(msg = nil, show_options=true)
|
|
84
|
+
info msg if msg
|
|
85
|
+
puts options if show_options
|
|
86
|
+
Kernel.exit(-1)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def info(msg)
|
|
90
|
+
@buffer << msg.gsub(/^[ \t]+/, '') << "\n"
|
|
91
|
+
end
|
|
92
|
+
alias :error :info
|
|
93
|
+
|
|
94
|
+
# Contribute to options
|
|
95
|
+
def add_options(opt)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Returns the command banner
|
|
99
|
+
def banner
|
|
100
|
+
raise "Command.banner should be overriden by subclasses"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Checks that the command may be safely executed!
|
|
104
|
+
def check_command_policy
|
|
105
|
+
raise "Command.check_command_policy should be overriden"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Runs the sub-class defined command
|
|
109
|
+
def __run(requester_file, arguments)
|
|
110
|
+
raise "Command._run should be overriden"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'waw/wspec'
|
|
2
|
+
require 'waw/commands/start_command'
|
|
3
|
+
module Waw
|
|
4
|
+
module Commands
|
|
5
|
+
class ProfileCommand < Command
|
|
6
|
+
|
|
7
|
+
def banner
|
|
8
|
+
<<-EOF
|
|
9
|
+
Usage: [waw-]profile [options]
|
|
10
|
+
EOF
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Start command is always safe
|
|
14
|
+
def check_command_policy
|
|
15
|
+
true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Ignores a given location?
|
|
19
|
+
def ignore?(location, visited)
|
|
20
|
+
visited[location] or /\.(gif|zip|pdf|jpg|csv)$/ =~ location
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Recursively visits the whole website
|
|
24
|
+
def visit(browser, location, visited = {})
|
|
25
|
+
return if ignore?(location, visited)
|
|
26
|
+
visited[location] = true
|
|
27
|
+
browser.location = location
|
|
28
|
+
unless browser.is200
|
|
29
|
+
puts "Hohoho, I've found a lost internal link #{location}"
|
|
30
|
+
return
|
|
31
|
+
else
|
|
32
|
+
puts "Visiting #{location}" if verbose
|
|
33
|
+
browser.all_internal_links.each do |link|
|
|
34
|
+
visit(browser, link[:href], visited)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Runs the sub-class defined command
|
|
40
|
+
def __run(requester_file, arguments)
|
|
41
|
+
require 'waw/wspec/browser'
|
|
42
|
+
|
|
43
|
+
# Start the server first
|
|
44
|
+
thread, waw_kernel = ::Waw::Commands::StartCommand.new.waw_start(requester_file, verbose)
|
|
45
|
+
visited, browser, location = {}, ::Waw::WSpec::Browser.new, waw_kernel.config.web_base
|
|
46
|
+
|
|
47
|
+
# Launch the visit
|
|
48
|
+
t1 = Time.now
|
|
49
|
+
visit(browser, location, visited)
|
|
50
|
+
t2 = Time.now
|
|
51
|
+
|
|
52
|
+
# Stop the server now
|
|
53
|
+
thread.exit
|
|
54
|
+
|
|
55
|
+
# Show statistics
|
|
56
|
+
req_by_sec = visited.size.to_f/(t2-t1)
|
|
57
|
+
avg_by_sec = (t2-t1)/visited.size
|
|
58
|
+
|
|
59
|
+
puts "#{visited.size} pages visited in #{t2-t1} seconds (#{req_by_sec} req./sec., #{avg_by_sec} sec./req.)"
|
|
60
|
+
rescue Interrupt => ex
|
|
61
|
+
info "waw-profile stopping now... ciao!" if verbose
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end # module ProfileCommand
|
|
65
|
+
end # module Commands
|
|
66
|
+
end # module Waw
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'uri'
|
|
2
|
+
require 'net/http'
|
|
3
|
+
module Waw
|
|
4
|
+
module Commands
|
|
5
|
+
class StartCommand < Command
|
|
6
|
+
|
|
7
|
+
def banner
|
|
8
|
+
<<-EOF
|
|
9
|
+
Usage: [waw-]start [options]
|
|
10
|
+
EOF
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Start command is always safe
|
|
14
|
+
def check_command_policy
|
|
15
|
+
true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Executes the waw-start command and returns the running thread
|
|
19
|
+
def waw_start(requester_file, verbose = true)
|
|
20
|
+
waw_kernel = Waw.autoload(requester_file)
|
|
21
|
+
t = Thread.new(waw_kernel) do |app|
|
|
22
|
+
begin
|
|
23
|
+
server = Rack::Handler::Mongrel
|
|
24
|
+
rescue LoadError => e
|
|
25
|
+
server = Rack::Handler::WEBrick
|
|
26
|
+
end
|
|
27
|
+
options = {:Port => app.config.web_port, :Host => "0.0.0.0", :AccessLog => []}
|
|
28
|
+
server.run app, options
|
|
29
|
+
end
|
|
30
|
+
try, ok = 0, false
|
|
31
|
+
begin
|
|
32
|
+
info "Attempting to reach the web server..." if verbose
|
|
33
|
+
::Net::HTTP.get(URI.parse(waw_kernel.config.web_base))
|
|
34
|
+
ok = true
|
|
35
|
+
rescue Errno::ECONNREFUSED => ex
|
|
36
|
+
sleep 0.1
|
|
37
|
+
end until (ok or (try += 1)>10)
|
|
38
|
+
if ok
|
|
39
|
+
if verbose
|
|
40
|
+
info "Your web application has been started successfully"
|
|
41
|
+
info "Have a look at #{waw_kernel.config.web_base}"
|
|
42
|
+
info "Enjoy waw!"
|
|
43
|
+
end
|
|
44
|
+
[t, waw_kernel]
|
|
45
|
+
else
|
|
46
|
+
raise Waw::Error, "Unable to reach the web server after having been started"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Runs the sub-class defined command
|
|
51
|
+
def __run(requester_file, arguments)
|
|
52
|
+
waw_start(requester_file)[0].join
|
|
53
|
+
rescue Interrupt => ex
|
|
54
|
+
info "waw-start stopping now... ciao!"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end # class StartCommand
|
|
58
|
+
end # module Commans
|
|
59
|
+
end # module Waw
|
data/lib/waw/config.rb
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
# Implements waw configuration utility
|
|
3
|
+
class Config
|
|
4
|
+
|
|
5
|
+
# Implementation of the config domain specific language
|
|
6
|
+
class DSL
|
|
7
|
+
|
|
8
|
+
# Creates a DSL instance
|
|
9
|
+
def initialize(config)
|
|
10
|
+
@config = config
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# When a method is missing, install config parameter
|
|
14
|
+
def method_missing(name, *args, &block)
|
|
15
|
+
if args.length==0 and block.nil?
|
|
16
|
+
@config.send(name)
|
|
17
|
+
elsif args.length==0
|
|
18
|
+
@config.install_configuration_property(name, block)
|
|
19
|
+
elsif block
|
|
20
|
+
raise WawConfigurationError, "Bad config usage on #{name}"
|
|
21
|
+
else
|
|
22
|
+
@config.install_configuration_property(name, args.size==1 ? args[0] : args)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end # class DSL
|
|
27
|
+
|
|
28
|
+
# Initialize a configuration instance. If merge_default is set to true,
|
|
29
|
+
# the default configuration file is automatically loaded.
|
|
30
|
+
def initialize(app, merge_default = true)
|
|
31
|
+
raise ArgumentError, "Waw application required as first argument" unless app.respond_to?(:root_folder)
|
|
32
|
+
@wawapp = app
|
|
33
|
+
self.merge_file(File.join(File.dirname(__FILE__), 'default_config.cfg')) if merge_default
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Raises a configuration error
|
|
37
|
+
def config_error(name, message)
|
|
38
|
+
raise ConfigurationError, message
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Checks if a configuration property is known
|
|
42
|
+
def knows?(name)
|
|
43
|
+
self.respond_to?(name.to_s.to_sym)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Returns the configuration property under name,
|
|
47
|
+
# or returns default if the config does not know that name
|
|
48
|
+
def ensure(name, default)
|
|
49
|
+
knows?(name) ? self.send(name) : default
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Installs a configuration parameter
|
|
53
|
+
def install_configuration_property(name, value)
|
|
54
|
+
case name
|
|
55
|
+
when :load_path
|
|
56
|
+
value = [value] unless Array===value
|
|
57
|
+
value = value.collect{|val| File.expand_path(File.join(@wawapp.root_folder, val))}
|
|
58
|
+
$LOAD_PATH.unshift(*value)
|
|
59
|
+
when :requires
|
|
60
|
+
value = [value] unless Array===value
|
|
61
|
+
value.each{|f| require(f)}
|
|
62
|
+
when :log_dir
|
|
63
|
+
config_error(name, "log_dir is expected to be a string") unless String===value
|
|
64
|
+
# config_error(name, "Unable to access log_dir #{value}") unless File.exists?(value) and
|
|
65
|
+
# File.directory?(value) and
|
|
66
|
+
# File.writable?(value)
|
|
67
|
+
when :log_file
|
|
68
|
+
config_error(name, "log_file is expected to be a string") unless String===value
|
|
69
|
+
when :log_level
|
|
70
|
+
config_error(name, "Bad log_level #{value}") unless value>=0 and value<=5
|
|
71
|
+
when :log_frequency
|
|
72
|
+
config_error(name, "Bad log_frequency #{value}") unless %w{daily weekly monthly}.include?(value)
|
|
73
|
+
when :web_domain, :web_base
|
|
74
|
+
config_error(name, "web_domain is expected to be a string") unless String===value
|
|
75
|
+
when :rack_session
|
|
76
|
+
config_error(name, "rack_session is expected to be true or false") unless true==value or false==value
|
|
77
|
+
when :rack_session_expire
|
|
78
|
+
config_error(name, "rack_session_expire is expected to be an Integer") unless Integer===value
|
|
79
|
+
end
|
|
80
|
+
instance_eval "@#{name} = value"
|
|
81
|
+
instance_eval <<-EOF
|
|
82
|
+
def #{name}(force_array = false)
|
|
83
|
+
value = @#{name}
|
|
84
|
+
if Proc===value
|
|
85
|
+
self.instance_eval &value
|
|
86
|
+
else
|
|
87
|
+
force_array ? (Array===value ? value : [value]) : value
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
EOF
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Merges the configuration with a given configuration string
|
|
94
|
+
def merge(config_str)
|
|
95
|
+
begin
|
|
96
|
+
DSL.new(self).instance_eval config_str
|
|
97
|
+
rescue ConfigurationError => ex
|
|
98
|
+
raise ex
|
|
99
|
+
end
|
|
100
|
+
self
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Merges the configuration with a given configuration file
|
|
104
|
+
def merge_file(config_file)
|
|
105
|
+
raise ArgumentError, "Config file does not exists" unless File.exists?(config_file)
|
|
106
|
+
merge File.read(config_file)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
end # class Config
|
|
110
|
+
end # module Waw
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Controller of a web application, designing a number of typical services.
|
|
5
|
+
#
|
|
6
|
+
class Controller
|
|
7
|
+
include Waw::EnvironmentUtils
|
|
8
|
+
include ::Rack::Delegator
|
|
9
|
+
|
|
10
|
+
# Handler for Rack calls to the controller
|
|
11
|
+
def call(env)
|
|
12
|
+
result = execute(env, request, response)
|
|
13
|
+
raise WawError, "Controller #{self.class} returned an empty result" unless result
|
|
14
|
+
raise WawError, "Controller #{self.class} returned an invalid result #{result.inspect}" unless Array===result
|
|
15
|
+
result
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Executes the controller on a Rack::Request and Rack::Response pair
|
|
19
|
+
def execute(env, request, response)
|
|
20
|
+
raise "Should be subclassed"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end # class Controller
|
|
24
|
+
|
|
25
|
+
end # module Waw
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
class ActionController < Waw::Controller
|
|
3
|
+
#
|
|
4
|
+
# A Web action, inside an ActionController.
|
|
5
|
+
#
|
|
6
|
+
class Action
|
|
7
|
+
|
|
8
|
+
# Action controller
|
|
9
|
+
attr_reader :controller
|
|
10
|
+
|
|
11
|
+
# Action name
|
|
12
|
+
attr_reader :name
|
|
13
|
+
|
|
14
|
+
# Action signature (pre-conditions and validation)
|
|
15
|
+
attr_reader :signature
|
|
16
|
+
|
|
17
|
+
# Action routing
|
|
18
|
+
attr_reader :routing
|
|
19
|
+
|
|
20
|
+
# Creates an action instance
|
|
21
|
+
def initialize(name, signature, routing, controller, method)
|
|
22
|
+
@name, @signature, @routing = name, signature, routing
|
|
23
|
+
@controller, @method = controller, method
|
|
24
|
+
@routing = ::Waw::Routing::ActionRouting.new unless @routing
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Returns a unique id for this action in the architecture
|
|
28
|
+
def id
|
|
29
|
+
"#{controller.url}/#{name}"[1..-1].gsub('/', '_')
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Builds a href for this action, with optional parameters
|
|
33
|
+
def href(params = nil)
|
|
34
|
+
"#{controller.url}/#{name}" << (params ? "?#{params.to_url_query}" : "")
|
|
35
|
+
end
|
|
36
|
+
alias :url :href
|
|
37
|
+
alias :uri :href
|
|
38
|
+
|
|
39
|
+
# Factors the ajax link for invoking this action in a <a onclick="...">
|
|
40
|
+
def ajax_link(arguments = {})
|
|
41
|
+
buffer = ""
|
|
42
|
+
arguments.each_pair {|k, v| buffer << ", '#{k}' : '#{v}'"}
|
|
43
|
+
"javascript:#{id}({#{buffer[2..-1]}}, '##{id}')"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Factors the ajax code for preparing a formulary
|
|
47
|
+
def ajax_form_preparer(opts = {})
|
|
48
|
+
form_id = opts[:form_id] || id
|
|
49
|
+
<<-EOF
|
|
50
|
+
<script type="text/javascript">
|
|
51
|
+
$(document).ready(function() {
|
|
52
|
+
$("form##{form_id}").submit(function() {
|
|
53
|
+
#{id}($("form##{form_id}").serialize(), "form##{form_id}");
|
|
54
|
+
return false;
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
</script>
|
|
58
|
+
EOF
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Factors a javascript call to the associated action
|
|
62
|
+
def ajax_action_call(opts = {})
|
|
63
|
+
form_id = opts[:form_id] || id
|
|
64
|
+
"#{id}($(\"form##{form_id}\").serialize(), \"form##{form_id}\");"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Factors the ajax code to submit the formulary
|
|
68
|
+
def ajax_form_submit(opts = {})
|
|
69
|
+
form_id = opts[:form_id] || id
|
|
70
|
+
"javascript:$('form##{form_id}').submit()"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Executes the action inside a controller and using parameters
|
|
74
|
+
def execute(params = {})
|
|
75
|
+
ok, values = @signature.apply(params)
|
|
76
|
+
if ok
|
|
77
|
+
# validation is ok, merge params and continue
|
|
78
|
+
[:success, @method.bind(controller.instance).call(params.merge!(values))]
|
|
79
|
+
else
|
|
80
|
+
# validation is ko
|
|
81
|
+
[:"validation-ko", values]
|
|
82
|
+
end
|
|
83
|
+
rescue ::Waw::Validation::KO => ex
|
|
84
|
+
[:"validation-ko", ex.failed]
|
|
85
|
+
rescue ::Waw::Validation::Error => ex
|
|
86
|
+
[:"validation-error", ex.failed]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
end # class Action
|
|
90
|
+
end # class ActionController
|
|
91
|
+
end # module Waw
|