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
data/lib/waw/kern/app.rb
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
module Kern
|
|
3
|
+
# Kernel waw application
|
|
4
|
+
class App
|
|
5
|
+
include ::Rack::Delegator
|
|
6
|
+
include ::Waw::Kern::FreezedState
|
|
7
|
+
include ::Waw::Kern::LivingState
|
|
8
|
+
include ::Waw::Kern::Hooks
|
|
9
|
+
include ::Waw::Kern::Utils
|
|
10
|
+
include ::Waw::Kern::Lifecycle
|
|
11
|
+
|
|
12
|
+
# Creates a kernel application instance
|
|
13
|
+
def initialize(identifier = nil, options = {})
|
|
14
|
+
@options = options
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Installs the environment and delegates to the business
|
|
18
|
+
# application
|
|
19
|
+
def call(env)
|
|
20
|
+
install_living_state(env)
|
|
21
|
+
if app=self.app
|
|
22
|
+
app.call(env)
|
|
23
|
+
else
|
|
24
|
+
[503, {'Content-Type' => 'text/plain'}, ['This waw application is unloaded']]
|
|
25
|
+
end
|
|
26
|
+
rescue ::WLang::Error => ex
|
|
27
|
+
# On exception, returns a 500 with a message
|
|
28
|
+
logger.error("Fatal error #{ex.message}")
|
|
29
|
+
logger.error(ex.wlang_backtrace.join("\n"))
|
|
30
|
+
logger.error(ex.backtrace.join("\n"))
|
|
31
|
+
[500, {'Content-Type' => 'text/plain'}, ['500 Internal Server Error']]
|
|
32
|
+
rescue Exception => ex
|
|
33
|
+
# On exception, returns a 500 with a message
|
|
34
|
+
logger.error("Fatal error #{ex.message}")
|
|
35
|
+
logger.error(ex.backtrace.join("\n"))
|
|
36
|
+
[500, {'Content-Type' => 'text/plain'}, ['500 Internal Server Error']]
|
|
37
|
+
ensure
|
|
38
|
+
clean_living_state
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Returns an identifier for this kernel application
|
|
42
|
+
def identifier
|
|
43
|
+
@identifier || "No identifier (#{root_folder}/#{routing})"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end # class App
|
|
47
|
+
end # module Kern
|
|
48
|
+
end # module Waw
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
nil
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
module Kern
|
|
3
|
+
#
|
|
4
|
+
# Contains all attribute accessors for what is considered freezed
|
|
5
|
+
# after application loading.
|
|
6
|
+
#
|
|
7
|
+
module FreezedState
|
|
8
|
+
|
|
9
|
+
# Root application folder
|
|
10
|
+
attr_accessor :root_folder
|
|
11
|
+
|
|
12
|
+
# Deploy words found in waw.deploy
|
|
13
|
+
attr_accessor :deploy_words
|
|
14
|
+
|
|
15
|
+
# ::Waw::Config instance
|
|
16
|
+
attr_accessor :config
|
|
17
|
+
|
|
18
|
+
# Logger instance
|
|
19
|
+
attr_accessor :logger
|
|
20
|
+
|
|
21
|
+
# ::Waw::ResourceCollection instance
|
|
22
|
+
attr_accessor :resources
|
|
23
|
+
|
|
24
|
+
# Routing name
|
|
25
|
+
attr_accessor :routing
|
|
26
|
+
|
|
27
|
+
# Rack user's application
|
|
28
|
+
attr_accessor :app
|
|
29
|
+
|
|
30
|
+
end # module FreezedState
|
|
31
|
+
end # module Kern
|
|
32
|
+
end # module Waw
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
module Kern
|
|
3
|
+
#
|
|
4
|
+
# Provides the hook support to the waw kernel.
|
|
5
|
+
#
|
|
6
|
+
# This module installs a @hooks instance variable (array of hooks by
|
|
7
|
+
# abstract name). It also expects the _root_folder_ and _logger_ instance
|
|
8
|
+
# variables provided by other modules.
|
|
9
|
+
#
|
|
10
|
+
module Hooks
|
|
11
|
+
|
|
12
|
+
# Returns installed hooks for a given abstract name _which_ (:load,
|
|
13
|
+
# :start, :unload,...). This method always returns an array, which
|
|
14
|
+
# can be empty if no hook is currently installed under _which_.
|
|
15
|
+
def hooks(which)
|
|
16
|
+
@hooks = Hash.new{|h,k| h[k] = []} if @hooks.nil?
|
|
17
|
+
@hooks[which]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Adds a start hook.
|
|
21
|
+
def add_start_hook(hook = nil, &block)
|
|
22
|
+
hooks(:start) << (hook || block)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Adds an unload hook.
|
|
26
|
+
def add_unload_hook(hook = nil, &block)
|
|
27
|
+
hooks(:unload) << (hook || block)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Executes all hooks installed under _which_. Hooks installed through
|
|
31
|
+
# the API are executed first. Hooks installed under root_folder/hooks/_which_
|
|
32
|
+
# are executed then.
|
|
33
|
+
def execute_hooks(which)
|
|
34
|
+
# API installed hooks
|
|
35
|
+
hooks(which).each do |hook|
|
|
36
|
+
if hook.respond_to?(:run)
|
|
37
|
+
hook.run(self)
|
|
38
|
+
elsif hook.respond_to?(:call)
|
|
39
|
+
hook.call(self)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# the file ones now
|
|
44
|
+
hooks_dir = File.join(root_folder, 'hooks', which.to_s)
|
|
45
|
+
Dir[File.join(hooks_dir, '*.rb')].sort{|f1, f2| File.basename(f1) <=> File.basename(f2)}.each do |file|
|
|
46
|
+
logger.info("Running waw #{which} hook #{file}...")
|
|
47
|
+
::Kernel.load(file)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end # module Hooks
|
|
52
|
+
end # module Kern
|
|
53
|
+
end # module Waw
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
module Kern
|
|
3
|
+
#
|
|
4
|
+
# Implements waw kernel's lifecycle.
|
|
5
|
+
#
|
|
6
|
+
module Lifecycle
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
# Autoloads waw from a given location. The waw root_folder is found
|
|
10
|
+
# using find_web_root and the application loaded using load_application.
|
|
11
|
+
#
|
|
12
|
+
# This method expects read/write accessors for the instance variables below.
|
|
13
|
+
# All these variables are expected to be initially nil and are affected when
|
|
14
|
+
# the application is loaded (see load_application).
|
|
15
|
+
#
|
|
16
|
+
# * root_folder : the expanded file name of the root folder of the application
|
|
17
|
+
# * deploy_words : an array of deploy words found in waw.deploy
|
|
18
|
+
# * config : Waw::Config instance, merged with configuration files in turn
|
|
19
|
+
# * logger : Logger instance
|
|
20
|
+
# * resources : ResourceCollection instance, filled with resource files
|
|
21
|
+
# * routing : name of the waw.routing file that has been loaded
|
|
22
|
+
# * app : Rack application loaded thanks to the routing file.
|
|
23
|
+
#
|
|
24
|
+
def autoload(file)
|
|
25
|
+
load_application(file)
|
|
26
|
+
rescue ConfigurationError, WawError => ex
|
|
27
|
+
raise ex
|
|
28
|
+
rescue Exception => ex
|
|
29
|
+
if logger
|
|
30
|
+
logger.fatal(ex.class.name.to_s + " : " + ex.message)
|
|
31
|
+
logger.fatal(ex.backtrace.join("\n"))
|
|
32
|
+
end
|
|
33
|
+
raise ex
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
#
|
|
37
|
+
# Loads the entire application from a given root folder, each
|
|
38
|
+
# load stage in turn:
|
|
39
|
+
#
|
|
40
|
+
# -1. find_web_root(from)
|
|
41
|
+
# 0. load_deploy
|
|
42
|
+
# 1. load_config
|
|
43
|
+
# 2. load_logger
|
|
44
|
+
# 3. load_resources
|
|
45
|
+
# 4. load_routing
|
|
46
|
+
# 5. load_hooks
|
|
47
|
+
#
|
|
48
|
+
# Returns self. Raises a ConfigurationError if something fails.
|
|
49
|
+
#
|
|
50
|
+
def load_application(from)
|
|
51
|
+
# 0) Load stage -1: finding web root
|
|
52
|
+
self.root_folder = find_web_root(from)
|
|
53
|
+
|
|
54
|
+
# 0) Load stage 0: waw.deploy
|
|
55
|
+
self.deploy_words = load_deploy(root_folder)
|
|
56
|
+
|
|
57
|
+
# 1) Load stage 1: config
|
|
58
|
+
self.config = load_config(root_folder, deploy_words)
|
|
59
|
+
|
|
60
|
+
# 2) Load stage 2: logger
|
|
61
|
+
self.logger = load_logger(root_folder, deploy_words, config)
|
|
62
|
+
logger.info("#{self.class.name}: load stage 1 sucessfull (#{deploy_words.join(', ')})")
|
|
63
|
+
logger.info("#{self.class.name}: load stage 2 sucessfull")
|
|
64
|
+
|
|
65
|
+
# 3) Load stage 3: resources
|
|
66
|
+
self.resources = load_resources(root_folder, deploy_words, config, logger)
|
|
67
|
+
logger.info("#{self.class.name}: load stage 3 sucessfull (resources)")
|
|
68
|
+
|
|
69
|
+
# 4) Load stage 4: routing
|
|
70
|
+
self.routing, self.app = load_routing(root_folder, deploy_words, config, logger, resources)
|
|
71
|
+
logger.info("#{self.class.name}: load stage 4 sucessfull (using #{routing})")
|
|
72
|
+
|
|
73
|
+
# 5) Load stage 5: load hooks
|
|
74
|
+
execute_hooks(:load)
|
|
75
|
+
execute_hooks(:start)
|
|
76
|
+
logger.info("#{self.class.name}: load stage 5 sucessfull (load hooks executed)")
|
|
77
|
+
|
|
78
|
+
# Hey hey, everything fine if we reach this!
|
|
79
|
+
logger.info("#{self.class.name}: application loaded successfully, enjoy!")
|
|
80
|
+
self
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
#
|
|
84
|
+
# Implements load stage #0: waw.deploy
|
|
85
|
+
#
|
|
86
|
+
# This method loads the waw.deploy file, decodes it and returns an array
|
|
87
|
+
# of deploy words.
|
|
88
|
+
#
|
|
89
|
+
# Raises a ::Waw::ConfigurationError if waw.deploy cannot be found or is
|
|
90
|
+
# corrupted.
|
|
91
|
+
#
|
|
92
|
+
def load_deploy(root_folder)
|
|
93
|
+
# Locates the waw.deploy file
|
|
94
|
+
deploy_file = File.join(root_folder, 'waw.deploy')
|
|
95
|
+
unless File.exists?(deploy_file)
|
|
96
|
+
puts "wawdeploy is deprecated, use waw.deploy instead!"
|
|
97
|
+
deploy_file = File.join(root_folder, 'wawdeploy')
|
|
98
|
+
end
|
|
99
|
+
raise ConfigurationError, "Missing waw.deploy file" unless File.exists?(deploy_file)
|
|
100
|
+
|
|
101
|
+
words = []
|
|
102
|
+
File.readlines(deploy_file).each_with_index do |line, i|
|
|
103
|
+
next if /^#/ =~ (line = line.strip)
|
|
104
|
+
next if line.empty?
|
|
105
|
+
raise ConfigurationError, "Waw deploy file corrupted on line #{i} (#{line})"\
|
|
106
|
+
unless /^[a-z_]+(\s+[a-z_]+)*$/ =~ line
|
|
107
|
+
words += line.split(/\s+/)
|
|
108
|
+
end
|
|
109
|
+
words
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
#
|
|
113
|
+
# Implements load stage #1: waw configuration
|
|
114
|
+
#
|
|
115
|
+
# This method merges all root_folder/config/xxx.cfg files (where xxx denotes
|
|
116
|
+
# a deploy word) inside the default waw configuration, which is then returned.
|
|
117
|
+
#
|
|
118
|
+
# Raises a ConfigurationError if a configuration file is missing or if something
|
|
119
|
+
# fails when loading a configuration file.
|
|
120
|
+
#
|
|
121
|
+
def load_config(root_folder, deploy_words)
|
|
122
|
+
# create a default configuration
|
|
123
|
+
config = Waw::Config.new(self, true)
|
|
124
|
+
config.install_configuration_property(:root_folder, root_folder)
|
|
125
|
+
|
|
126
|
+
# Read it and analyse merged configurations
|
|
127
|
+
conf_file = nil
|
|
128
|
+
deploy_words.each do |conf|
|
|
129
|
+
conf_file = File.join(root_folder, 'config', "#{conf}.cfg")
|
|
130
|
+
raise ConfigurationError, "Missing config file config/#{conf}.cfg" unless File.exists?(conf_file)
|
|
131
|
+
config.merge_file(conf_file)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
config
|
|
135
|
+
rescue ConfigurationError => ex
|
|
136
|
+
raise ex
|
|
137
|
+
rescue Exception => ex
|
|
138
|
+
raise ConfigurationError, "Error occured when loading configuration #{File.basename(conf_file)}\n#{ex.message}", ex.backtrace
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
#
|
|
142
|
+
# Implements load stage #2: logger
|
|
143
|
+
#
|
|
144
|
+
# This method creates a logger instance with the config parameters
|
|
145
|
+
# and returns it.
|
|
146
|
+
#
|
|
147
|
+
# Raises a ConfigurationError if something fails.
|
|
148
|
+
#
|
|
149
|
+
def load_logger(root_folder, deploy_words, config)
|
|
150
|
+
# default parameters
|
|
151
|
+
appname = config.ensure(:application_name, 'webapp')
|
|
152
|
+
log_frequency = config.ensure(:log_frequency, 'weekly')
|
|
153
|
+
|
|
154
|
+
if config.knows?(:log_io)
|
|
155
|
+
# We use a given IO
|
|
156
|
+
logger = Logger.new(config.log_io, log_frequency)
|
|
157
|
+
else
|
|
158
|
+
# We go to a log file
|
|
159
|
+
log_dir = config.ensure(:log_dir, 'logs')
|
|
160
|
+
log_file = config.ensure(:log_file, "#{appname}.log")
|
|
161
|
+
|
|
162
|
+
# Check it now
|
|
163
|
+
FileUtils.mkdir_p(log_dir) unless File.exists?(log_dir)
|
|
164
|
+
raise ConfigurationError, "Unable to use #{log_dir} for logs, it's a file..." unless File.directory?(log_dir)
|
|
165
|
+
raise ConfigurationError, "Unable to use #{log_dir} for logs, not writable" unless File.writable?(log_dir)
|
|
166
|
+
|
|
167
|
+
# The log file now
|
|
168
|
+
log_file = File.join(config.log_dir, config.log_file)
|
|
169
|
+
logger = Logger.new(log_file, log_frequency)
|
|
170
|
+
end
|
|
171
|
+
logger.level = config.ensure(:log_level, Logger::DEBUG)
|
|
172
|
+
logger
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
#
|
|
176
|
+
# Implements load stage #3: resources
|
|
177
|
+
#
|
|
178
|
+
# This method creates an empty ResourceCollection and fill it with
|
|
179
|
+
# child collections, one for each resource files (.rs) found in
|
|
180
|
+
# root_folder/resources. Returns the parent collection.
|
|
181
|
+
#
|
|
182
|
+
# Riases a ConfigurationError if something fails.
|
|
183
|
+
#
|
|
184
|
+
def load_resources(root_folder, deploy_words, config, logger)
|
|
185
|
+
resources = ResourceCollection.new
|
|
186
|
+
resource_dir = File.join(root_folder, 'resources')
|
|
187
|
+
if File.directory?(resource_dir) and File.readable?(resource_dir)
|
|
188
|
+
Dir[File.join(resource_dir, '*.rs')].each do |file|
|
|
189
|
+
name = File.basename(file, '.rs')
|
|
190
|
+
resources.send(:add_resource, name, ResourceCollection.parse_resource_file(file))
|
|
191
|
+
logger.debug("Resources #{name} loaded successfully")
|
|
192
|
+
end
|
|
193
|
+
elsif not(File.readable?(resource_dir))
|
|
194
|
+
logger.warn("Ignoring the resources folder (not readable)... something will probably fail later!")
|
|
195
|
+
end
|
|
196
|
+
resources
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
#
|
|
200
|
+
# Implements load stage #4: routing
|
|
201
|
+
#
|
|
202
|
+
# This method locates the more specific waw.xxx.routing file, using deploy
|
|
203
|
+
# words in reverse order, and turning back to 'waw.routing' if no one can
|
|
204
|
+
# be found. The corresponding routing file is then decoded and the Rack
|
|
205
|
+
# application built that way.
|
|
206
|
+
#
|
|
207
|
+
# This method returns a pair [routing_file_name, rack_app].
|
|
208
|
+
#
|
|
209
|
+
# Raises a ConfigurationError if something fails (if the waw.routing file
|
|
210
|
+
# cannot be found, in particular).
|
|
211
|
+
#
|
|
212
|
+
def load_routing(root_folder, deploy_words, config, logger, resources)
|
|
213
|
+
deploy_words.reverse.each do |word|
|
|
214
|
+
file = File.join(root_folder, "waw.#{word}.routing")
|
|
215
|
+
return [File.basename(file), ::Kernel.eval(File.read(file))] if File.exists?(file)
|
|
216
|
+
end
|
|
217
|
+
file = File.join(root_folder, 'waw.routing')
|
|
218
|
+
return ['waw.routing', ::Kernel.eval(File.read(file))] if File.exists?(file)
|
|
219
|
+
raise ConfigurationError, "Unable to find waw.routing file in #{root_folder}"
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
################################################################# About unloading
|
|
223
|
+
|
|
224
|
+
# Unloads the entire application
|
|
225
|
+
def unload()
|
|
226
|
+
execute_hooks(:unload)
|
|
227
|
+
self.root_folder = nil
|
|
228
|
+
self.deploy_words = nil
|
|
229
|
+
self.config = nil
|
|
230
|
+
self.resources = nil
|
|
231
|
+
self.routing = nil
|
|
232
|
+
self.app = nil
|
|
233
|
+
logger.info("#{self.class.name}: application unloaded successfully, ciao!")
|
|
234
|
+
self.logger = nil
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
################################################################# About reloading
|
|
238
|
+
|
|
239
|
+
# Unloads and directly reloads the whole application
|
|
240
|
+
def reload
|
|
241
|
+
folder = self.root_folder
|
|
242
|
+
unload
|
|
243
|
+
autoload(folder)
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
end # module Loading
|
|
247
|
+
end # module Kern
|
|
248
|
+
end # module Waw
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
module Kern
|
|
3
|
+
# Variables that are living during a web request.
|
|
4
|
+
module LivingState
|
|
5
|
+
|
|
6
|
+
# The living state object itself
|
|
7
|
+
class Saved
|
|
8
|
+
|
|
9
|
+
# Rack environment
|
|
10
|
+
attr_reader :rack_env
|
|
11
|
+
|
|
12
|
+
# Creates a saved instance
|
|
13
|
+
def initialize(rack_env)
|
|
14
|
+
@rack_env = rack_env
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Current request
|
|
18
|
+
def rack_request
|
|
19
|
+
@rack_request ||= Rack::Request.new(rack_env)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Current response
|
|
23
|
+
def rack_response
|
|
24
|
+
@rack_response ||= Rack::Response.new(rack_env)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Rack session object
|
|
28
|
+
def rack_session
|
|
29
|
+
@rack_session ||= (rack_env['rack.session'] ||= {})
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Waw session
|
|
33
|
+
def waw_session
|
|
34
|
+
@session ||= ::Waw::Session.new(rack_session)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end # class Saved
|
|
38
|
+
|
|
39
|
+
# Handler called to install everything required for the living
|
|
40
|
+
# state to work properly, based on a Rack env variable.
|
|
41
|
+
def install_living_state(env)
|
|
42
|
+
Thread.current[:waw_state] = Saved.new(env)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Cleans the living state when a request is done.
|
|
46
|
+
def clean_living_state
|
|
47
|
+
Thread.current[:waw_state] = nil
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Returns the current waw_state object
|
|
51
|
+
def waw_state
|
|
52
|
+
Thread.current[:waw_state] ||= Saved.new({})
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Returns the current Rack env instance
|
|
56
|
+
def rack_env
|
|
57
|
+
waw_state.rack_env
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Returns the current Rack request instance
|
|
61
|
+
def request
|
|
62
|
+
waw_state.rack_request
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Returns the current Rack request instance
|
|
66
|
+
def response
|
|
67
|
+
waw_state.rack_response
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Request parameters
|
|
71
|
+
def params
|
|
72
|
+
request && request.params
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Returns the current Rack session
|
|
76
|
+
def real_session
|
|
77
|
+
waw_state.rack_session
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Returns the waw session decorator
|
|
81
|
+
def session
|
|
82
|
+
waw_state.waw_session
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
end # module LivingState
|
|
86
|
+
end # module Kern
|
|
87
|
+
end # module Waw
|