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,30 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
class ActionController < Waw::Controller
|
|
3
|
+
#
|
|
4
|
+
# Common utilities about actions.
|
|
5
|
+
#
|
|
6
|
+
module ActionUtils
|
|
7
|
+
|
|
8
|
+
# Extracts the action name from a given path
|
|
9
|
+
def extract_action_name(path)
|
|
10
|
+
return $1.to_sym if path =~ /([a-zA-Z_]+)$/
|
|
11
|
+
nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Checks if an action exists
|
|
15
|
+
def has_action?(name)
|
|
16
|
+
name = extract_action_name(name) unless Symbol===name
|
|
17
|
+
return false unless name
|
|
18
|
+
actions.has_key?(name)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def find_action(name)
|
|
22
|
+
name = extract_action_name(name) unless Symbol===name
|
|
23
|
+
return nil unless name
|
|
24
|
+
actions[name]
|
|
25
|
+
end
|
|
26
|
+
alias :[] :find_action
|
|
27
|
+
|
|
28
|
+
end # module ActionUtils
|
|
29
|
+
end # class ActionController
|
|
30
|
+
end # module Waw
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
class ActionController < ::Waw::Controller
|
|
3
|
+
class JSGeneration
|
|
4
|
+
|
|
5
|
+
# Header of the generated javascript file
|
|
6
|
+
HEADER = <<-EOF
|
|
7
|
+
/* This file is automatically generated by Waw. Any edit will probably be lost
|
|
8
|
+
* next time the application is started. */
|
|
9
|
+
EOF
|
|
10
|
+
|
|
11
|
+
# Strip n spaces at the begining of a string
|
|
12
|
+
def strip(str, n)
|
|
13
|
+
str.gsub(/\t/, " ").gsub(/^\s{#{n}}/, '')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Raises a ConfigurationError
|
|
17
|
+
def error(msg)
|
|
18
|
+
raise ConfigurationError, msg
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Start hook start callback required by Waw. Generates the javascript code
|
|
22
|
+
# if the configuration variable 'code_at_startup' is true.
|
|
23
|
+
def run(waw_kernel)
|
|
24
|
+
return unless waw_kernel.config.code_at_startup
|
|
25
|
+
|
|
26
|
+
# Now, find the StaticController, that should be installed
|
|
27
|
+
static = waw_kernel.find_rack_app {|app| ::Waw::StaticController===app}
|
|
28
|
+
error("Code generation expects a ::Waw::StaticController being installed.") if static.nil?
|
|
29
|
+
|
|
30
|
+
# Find the folder now
|
|
31
|
+
folder = File.join(waw_kernel.root_folder, static.public_folder, 'js')
|
|
32
|
+
error("Code generation expects #{folder} to be an existing directory.") unless File.directory?(folder)
|
|
33
|
+
|
|
34
|
+
# Look for the application name
|
|
35
|
+
appname = waw_kernel.config.knows?(:application_name) ? waw_kernel.config.application_name : 'waw'
|
|
36
|
+
|
|
37
|
+
# And let's go now!
|
|
38
|
+
file = File.join(folder, "#{appname}_generated.js")
|
|
39
|
+
File.open(file, 'w') do |buffer|
|
|
40
|
+
generate_js(waw_kernel, buffer)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Generate the javascript code for installed action controllers.
|
|
45
|
+
def generate_js(waw_kernel, buffer)
|
|
46
|
+
# 1) header first
|
|
47
|
+
buffer << strip(HEADER, 8) << "\n"
|
|
48
|
+
|
|
49
|
+
# 2) messages
|
|
50
|
+
generate_js_messages(waw_kernel, buffer)
|
|
51
|
+
|
|
52
|
+
# 3) controllers
|
|
53
|
+
generate_js_controllers(waw_kernel, buffer)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Generates the javascript code for message resources.
|
|
57
|
+
def generate_js_messages(waw_kernel, buffer)
|
|
58
|
+
if waw_kernel.resources.has_resource?(:messages)
|
|
59
|
+
buffer << "/* Messages, from waw.resources.messages */\n"
|
|
60
|
+
messages = {}
|
|
61
|
+
waw_kernel.resources.messages.each do |name, value|
|
|
62
|
+
messages[name] = value
|
|
63
|
+
end
|
|
64
|
+
buffer << "var messages = new Array();\n"
|
|
65
|
+
messages.keys.sort{|k1, k2| k1.to_s <=> k2.to_s}.each do |name|
|
|
66
|
+
value = messages[name]
|
|
67
|
+
buffer << "messages['#{name}'] = \"#{value}\";\n"
|
|
68
|
+
end
|
|
69
|
+
buffer << "\n"
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Generates the js controllers
|
|
74
|
+
def generate_js_controllers(waw_kernel, buffer)
|
|
75
|
+
ActionController.controllers.sort{|c1, c2| c1.class.name <=> c2.class.name}.each do |controller|
|
|
76
|
+
# Let find the URL for this controller
|
|
77
|
+
app = waw_kernel.find_rack_app{|a| controller===a}
|
|
78
|
+
url = app ? app.find_url_of(app) : nil
|
|
79
|
+
unless url
|
|
80
|
+
waw_kernel.logger.warn("Skipping #{controller}, which does not seem to be mapped to an URL")
|
|
81
|
+
else
|
|
82
|
+
header = <<-EOF
|
|
83
|
+
/* Actions contributed by #{controller}, mapped to #{url} */
|
|
84
|
+
EOF
|
|
85
|
+
buffer << strip(header, 14)
|
|
86
|
+
controller.actions.keys.sort{|k1, k2| k1.to_s <=> k2.to_s}.each do |name|
|
|
87
|
+
action = controller.actions[name]
|
|
88
|
+
generate_js_for_action(waw_kernel, action, buffer)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Generates the javascript code for a given action
|
|
95
|
+
def generate_js_for_action(waw_kernel, action, buffer)
|
|
96
|
+
action_js = <<-THEEND
|
|
97
|
+
function #{action.id}(request_data, form) {
|
|
98
|
+
$.ajax({type: "POST", url: "#{action.url}", data: request_data, dataType: "json",
|
|
99
|
+
error: function(data) {
|
|
100
|
+
window.location = '/feedback?mkey=server_error';
|
|
101
|
+
},
|
|
102
|
+
success: function(data) {
|
|
103
|
+
THEEND
|
|
104
|
+
action_js << action.routing.generate_js_routing(action, 0).gsub(/^/, " "*16) << "\n"
|
|
105
|
+
action_js << <<-THEEND
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
THEEND
|
|
111
|
+
buffer << strip(action_js, 10)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
end # class JSGeneration
|
|
115
|
+
end # class ActionController
|
|
116
|
+
end # module Waw
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
require 'waw/controllers/action/action_utils'
|
|
2
|
+
require 'waw/controllers/action/action'
|
|
3
|
+
require 'waw/controllers/action/js_generation'
|
|
4
|
+
module Waw
|
|
5
|
+
|
|
6
|
+
#
|
|
7
|
+
# Defines a specific application controller for executing actions.
|
|
8
|
+
#
|
|
9
|
+
class ActionController < Waw::Controller
|
|
10
|
+
include ActionUtils
|
|
11
|
+
extend FullState::OnClass
|
|
12
|
+
extend FullState::OnInstance
|
|
13
|
+
|
|
14
|
+
# All subclasses
|
|
15
|
+
@@controllers = []
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
|
|
19
|
+
# Returns known controllers
|
|
20
|
+
def controllers
|
|
21
|
+
@@controllers
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# When this class is inherited we track the new controller, it becomes a
|
|
25
|
+
# Singleton and we install code generation as start hook if not already done.
|
|
26
|
+
def inherited(child)
|
|
27
|
+
super(child)
|
|
28
|
+
# Adds the controller as a child
|
|
29
|
+
controllers << child
|
|
30
|
+
|
|
31
|
+
# Let it become a singleton
|
|
32
|
+
child.instance_eval { include Singleton }
|
|
33
|
+
|
|
34
|
+
# And install start hook for code generation
|
|
35
|
+
if controllers.size==1 && (k = Waw.kernel)
|
|
36
|
+
k.add_start_hook(JSGeneration.new)
|
|
37
|
+
k.add_unload_hook ::Kernel.lambda { @@controllers = [] }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# This is all about actions
|
|
44
|
+
class << self
|
|
45
|
+
include ActionUtils
|
|
46
|
+
|
|
47
|
+
# Returns the url on which this controller is mapped
|
|
48
|
+
def url
|
|
49
|
+
self.instance.url
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Returns installed actions
|
|
53
|
+
def actions
|
|
54
|
+
@actions ||= {}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Fired when a signature will be next installed
|
|
58
|
+
def signature(signature=nil, &block)
|
|
59
|
+
signature = (signature.nil? ? Waw::Validation::Signature.new : signature)
|
|
60
|
+
signature = signature.merge(&block) if block
|
|
61
|
+
@signature = signature
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Installs a routing block for the next action
|
|
65
|
+
def routing(&block)
|
|
66
|
+
@routing = Waw::Routing::ActionRouting.new(&block)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# If a signature has been installed, let the next added method
|
|
70
|
+
# become an action
|
|
71
|
+
def method_added(name)
|
|
72
|
+
if @signature and not(@critical)
|
|
73
|
+
@critical = true
|
|
74
|
+
|
|
75
|
+
# Create the action instance
|
|
76
|
+
action = Waw::ActionController::Action.new(name, @signature, @routing, self, instance_method(name))
|
|
77
|
+
actions[name] = action
|
|
78
|
+
|
|
79
|
+
# Installs the class method that returns the action
|
|
80
|
+
instance_eval <<-EOF
|
|
81
|
+
class << self
|
|
82
|
+
def #{name}
|
|
83
|
+
actions[:#{name}]
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
EOF
|
|
87
|
+
|
|
88
|
+
# Installs the instance method that execute the action
|
|
89
|
+
define_method name do |params|
|
|
90
|
+
action.execute(params)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
@signature, @routing, @critical = nil, nil, false
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
end # end of class methods
|
|
97
|
+
|
|
98
|
+
# Returns the url on which this controller is mapped
|
|
99
|
+
def url
|
|
100
|
+
find_kernel_context.find_url_of(self)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Returns the actions installed on this controller
|
|
104
|
+
def actions
|
|
105
|
+
self.class.actions
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Ensapsules the action call
|
|
109
|
+
def encapsulate(action, actual_params, &block)
|
|
110
|
+
yield
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Executes the controller
|
|
114
|
+
def execute(env, request, response)
|
|
115
|
+
action_name = request.respond_to?(:path) ? request.path : request[:action]
|
|
116
|
+
logger.debug("Executing the action whose name is #{action_name}")
|
|
117
|
+
action = find_action(action_name)
|
|
118
|
+
if action
|
|
119
|
+
actual_params = request.params.symbolize_keys
|
|
120
|
+
result = encapsulate(action, actual_params) do
|
|
121
|
+
action.execute(actual_params)
|
|
122
|
+
end
|
|
123
|
+
logger.debug("ActionResult is #{result.inspect}")
|
|
124
|
+
[200, {}, result]
|
|
125
|
+
else
|
|
126
|
+
logger.warn("Action #{action_name} has not been found")
|
|
127
|
+
[200, {}, [:error, :action_not_found]]
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
end # class ActionController
|
|
132
|
+
|
|
133
|
+
end # module Waw
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'cgi'
|
|
2
|
+
module Waw
|
|
3
|
+
class ErrorHandler < ::Waw::Controller
|
|
4
|
+
class Backtrace
|
|
5
|
+
|
|
6
|
+
# Converts a back-trace to a friendly HTML chunck
|
|
7
|
+
def ex_backtrace_to_html(backtrace)
|
|
8
|
+
"<div>" + backtrace.collect{|s| CGI.escapeHTML(s)}.join('</div><div>') + "</div>"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Converts an exception to a friendly HTML chunck
|
|
12
|
+
def ex_to_html(ex, backtrace)
|
|
13
|
+
<<-EOF
|
|
14
|
+
<html>
|
|
15
|
+
<head>
|
|
16
|
+
<style type="text/css">
|
|
17
|
+
body {
|
|
18
|
+
font-size: 14px;
|
|
19
|
+
font-family: "Courier", "Arial", sans-serif;
|
|
20
|
+
}
|
|
21
|
+
p.message {
|
|
22
|
+
font-size: 16px;
|
|
23
|
+
font-weight: bold;
|
|
24
|
+
}
|
|
25
|
+
</style>
|
|
26
|
+
</head>
|
|
27
|
+
<body>
|
|
28
|
+
<h1>Internal server error (ruby exception)</h1>
|
|
29
|
+
<p class="message"><code>#{CGI.escapeHTML(ex.message)}</code></p>
|
|
30
|
+
<div style="margin-left:50px;">
|
|
31
|
+
#{ex_backtrace_to_html(backtrace)}
|
|
32
|
+
</div>
|
|
33
|
+
</body>
|
|
34
|
+
</html>
|
|
35
|
+
EOF
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Shows a page with a friendly presented backtrace for the error
|
|
39
|
+
# that occured
|
|
40
|
+
def call(kernel, ex)
|
|
41
|
+
backtrace = case ex
|
|
42
|
+
when ::WLang::Error
|
|
43
|
+
ex.wlang_backtrace
|
|
44
|
+
when ::Exception
|
|
45
|
+
ex.backtrace
|
|
46
|
+
else
|
|
47
|
+
[]
|
|
48
|
+
end
|
|
49
|
+
[500, {'Content-Type' => 'text/html'}, ex_to_html(ex, backtrace)]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end # class Backtrace
|
|
53
|
+
end # module ErrorHandler
|
|
54
|
+
end # module Waw
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require 'waw/controllers/error/backtrace'
|
|
2
|
+
module Waw
|
|
3
|
+
class ErrorHandler < ::Waw::Controller
|
|
4
|
+
|
|
5
|
+
# Creates an error handler rack application
|
|
6
|
+
def initialize(app)
|
|
7
|
+
@app = app
|
|
8
|
+
@validators, @handlers = [], []
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Handles arguments of push and unshift
|
|
12
|
+
def handle_args(args, &block)
|
|
13
|
+
validator, handler = args
|
|
14
|
+
handler = block if handler.nil?
|
|
15
|
+
validator, handler = nil, validator if handler.nil?
|
|
16
|
+
[validator, handler]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Adds an error handler. The method accepts the following
|
|
20
|
+
# argument variants:
|
|
21
|
+
#
|
|
22
|
+
# add_error_handler{|k,ex| ... }
|
|
23
|
+
# add_error_handler(SomeValidator){|k,ex| ... }
|
|
24
|
+
# add_error_handler(SomeHandler)
|
|
25
|
+
# add_error_handler(SomeValidator, SomeHandler)
|
|
26
|
+
#
|
|
27
|
+
def add_error_handler(*args, &block)
|
|
28
|
+
validator, handler = handle_args(args, &block)
|
|
29
|
+
@validators << validator
|
|
30
|
+
@handlers << handler
|
|
31
|
+
end
|
|
32
|
+
alias :push :add_error_handler
|
|
33
|
+
|
|
34
|
+
# Same as add_error_handler but adds it at the begining of the
|
|
35
|
+
# chain
|
|
36
|
+
def unshift(*args, &block)
|
|
37
|
+
validator, handler = handle_args(args, &block)
|
|
38
|
+
@validators.unshift(validator)
|
|
39
|
+
@handlers.unshift(handler)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Checks if a result seems a valid rack application result
|
|
43
|
+
def seems_valid_result?(result)
|
|
44
|
+
not(result.nil?) and Array===result and result.size==3
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Handles a call
|
|
48
|
+
def call(env)
|
|
49
|
+
@app.call(env)
|
|
50
|
+
rescue Exception => ex
|
|
51
|
+
kernel = find_kernel_context
|
|
52
|
+
@validators.each_with_index do |validator, i|
|
|
53
|
+
if (validator.nil? or (validator===ex))
|
|
54
|
+
result = @handlers[i].call(kernel, ex)
|
|
55
|
+
return result if seems_valid_result?(result)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
raise ex
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end # class ErrorHandler
|
|
62
|
+
end # module Waw
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
module Waw
|
|
3
|
+
#
|
|
4
|
+
# Decorates a given controller and convert result as JSON unless stated
|
|
5
|
+
# otherwise.
|
|
6
|
+
#
|
|
7
|
+
class JSONController
|
|
8
|
+
include ::Rack::Delegator
|
|
9
|
+
|
|
10
|
+
# Creates a controller instance
|
|
11
|
+
def initialize(app)
|
|
12
|
+
raise WAWError, "JSONController expects a delegation controller" if app.nil?
|
|
13
|
+
@app = app
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Calls the delegation controller and encode its result in JSON
|
|
17
|
+
def call(env)
|
|
18
|
+
status, headers, body = @app.call(env)
|
|
19
|
+
header = {} if headers.nil?
|
|
20
|
+
headers['Content-Type'] = 'application/json' if headers['Content-Type'].nil?
|
|
21
|
+
body = ::JSON.generate(body) if json_response?(headers)
|
|
22
|
+
[status, headers, body]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Do i need to encode as JSON?
|
|
26
|
+
def json_response?(headers)
|
|
27
|
+
(headers['Content-Type'] == 'application/json')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end # class JSONController
|
|
31
|
+
end # module Waw
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'time'
|
|
2
|
+
module Waw
|
|
3
|
+
class NoCache < ::Waw::Controller
|
|
4
|
+
|
|
5
|
+
# What is sent to the headers
|
|
6
|
+
NO_CACHE_HEADERS = {'Cache-control' => "no-store, no-cache, must-revalidate",
|
|
7
|
+
'Pragma' => "no-cache"}
|
|
8
|
+
|
|
9
|
+
# Creates a application instance
|
|
10
|
+
def initialize(app)
|
|
11
|
+
@app = app
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Manage calls
|
|
15
|
+
def call(env)
|
|
16
|
+
status, headers, body = @app.call(env)
|
|
17
|
+
headers = NO_CACHE_HEADERS.merge('Expires' => Time.now.rfc2822).merge(headers)
|
|
18
|
+
[status, headers, body]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end # class NoCache
|
|
22
|
+
end # module Waw
|