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.
Files changed (199) hide show
  1. data/LICENCE.rdoc +25 -0
  2. data/README.rdoc +32 -0
  3. data/bin/waw +32 -0
  4. data/bin/waw-profile +26 -0
  5. data/bin/waw-start +26 -0
  6. data/bin/wspec +33 -0
  7. data/layouts/empty/Rakefile +14 -0
  8. data/layouts/empty/config.ru +5 -0
  9. data/layouts/empty/config/commons.cfg +31 -0
  10. data/layouts/empty/config/devel.cfg +21 -0
  11. data/layouts/empty/ignore +7 -0
  12. data/layouts/empty/logs/dontforgetme +0 -0
  13. data/layouts/empty/resources/messages.rs +1 -0
  14. data/layouts/empty/test/wspec/site_respond.wspec +3 -0
  15. data/layouts/empty/test/wspec/test_all.rb +13 -0
  16. data/layouts/empty/waw.deploy +1 -0
  17. data/layouts/empty/waw.routing +6 -0
  18. data/layouts/static/dependencies +1 -0
  19. data/layouts/static/public/.wawaccess +18 -0
  20. data/layouts/static/public/css/style.css +0 -0
  21. data/layouts/static/public/images/dontforgetme +0 -0
  22. data/layouts/static/public/js/project.js +0 -0
  23. data/layouts/static/public/pages/.wawaccess +30 -0
  24. data/layouts/static/public/pages/404.wtpl +1 -0
  25. data/layouts/static/public/pages/index.wtpl +5 -0
  26. data/layouts/static/public/templates/.wawaccess +9 -0
  27. data/layouts/static/public/templates/layout.wtpl +17 -0
  28. data/layouts/static/test/wspec/static_pages_are_served.wspec +21 -0
  29. data/layouts/static/waw.routing +8 -0
  30. data/lib/waw.rb +99 -0
  31. data/lib/waw/commands/command.rb +115 -0
  32. data/lib/waw/commands/profile_command.rb +66 -0
  33. data/lib/waw/commands/start_command.rb +59 -0
  34. data/lib/waw/config.rb +110 -0
  35. data/lib/waw/controller.rb +25 -0
  36. data/lib/waw/controllers/action/action.rb +91 -0
  37. data/lib/waw/controllers/action/action_utils.rb +30 -0
  38. data/lib/waw/controllers/action/js_generation.rb +116 -0
  39. data/lib/waw/controllers/action_controller.rb +133 -0
  40. data/lib/waw/controllers/error/backtrace.rb +54 -0
  41. data/lib/waw/controllers/error_handler.rb +62 -0
  42. data/lib/waw/controllers/json_controller.rb +31 -0
  43. data/lib/waw/controllers/no_cache.rb +22 -0
  44. data/lib/waw/controllers/static/match.rb +80 -0
  45. data/lib/waw/controllers/static/waw_access.rb +235 -0
  46. data/lib/waw/controllers/static/waw_access_dsl.rb +48 -0
  47. data/lib/waw/controllers/static_controller.rb +37 -0
  48. data/lib/waw/default_config.cfg +14 -0
  49. data/lib/waw/environment_utils.rb +57 -0
  50. data/lib/waw/errors.rb +4 -0
  51. data/lib/waw/ext.rb +3 -0
  52. data/lib/waw/ext/core.rb +4 -0
  53. data/lib/waw/ext/core/hash.rb +47 -0
  54. data/lib/waw/ext/core/logger.rb +10 -0
  55. data/lib/waw/ext/core/module.rb +20 -0
  56. data/lib/waw/ext/core/object.rb +29 -0
  57. data/lib/waw/ext/rack.rb +19 -0
  58. data/lib/waw/ext/rack/builder.rb +43 -0
  59. data/lib/waw/ext/rack/delegator.rb +51 -0
  60. data/lib/waw/ext/rack/urlmap.rb +55 -0
  61. data/lib/waw/ext/wlang.rb +1 -0
  62. data/lib/waw/ext/wlang/hosted_language.rb +21 -0
  63. data/lib/waw/fullstate.rb +8 -0
  64. data/lib/waw/fullstate/on_class.rb +37 -0
  65. data/lib/waw/fullstate/on_instance.rb +27 -0
  66. data/lib/waw/fullstate/variable.rb +36 -0
  67. data/lib/waw/kern.rb +6 -0
  68. data/lib/waw/kern/app.rb +48 -0
  69. data/lib/waw/kern/empty/waw.deploy +0 -0
  70. data/lib/waw/kern/empty/waw.routing +1 -0
  71. data/lib/waw/kern/freezed_state.rb +32 -0
  72. data/lib/waw/kern/hooks.rb +53 -0
  73. data/lib/waw/kern/lifecycle.rb +248 -0
  74. data/lib/waw/kern/living_state.rb +87 -0
  75. data/lib/waw/kern/utils.rb +27 -0
  76. data/lib/waw/resource_collection.rb +100 -0
  77. data/lib/waw/restart.rb +32 -0
  78. data/lib/waw/routing.rb +43 -0
  79. data/lib/waw/routing/action_routing.rb +78 -0
  80. data/lib/waw/routing/dsl.rb +45 -0
  81. data/lib/waw/routing/feedback.rb +23 -0
  82. data/lib/waw/routing/form_validation_feedback.rb +36 -0
  83. data/lib/waw/routing/javascript.rb +17 -0
  84. data/lib/waw/routing/redirect.rb +26 -0
  85. data/lib/waw/routing/refresh.rb +17 -0
  86. data/lib/waw/routing/routing_rule.rb +16 -0
  87. data/lib/waw/scope_utils.rb +69 -0
  88. data/lib/waw/session.rb +51 -0
  89. data/lib/waw/testing.rb +1 -0
  90. data/lib/waw/tools/mail.rb +4 -0
  91. data/lib/waw/tools/mail/mail.rb +119 -0
  92. data/lib/waw/tools/mail/mail_agent.rb +123 -0
  93. data/lib/waw/tools/mail/mailbox.rb +62 -0
  94. data/lib/waw/tools/mail/template.rb +38 -0
  95. data/lib/waw/utils/dsl_helper.rb +116 -0
  96. data/lib/waw/validation.rb +175 -0
  97. data/lib/waw/validation/and_validator.rb +27 -0
  98. data/lib/waw/validation/array_validations.rb +38 -0
  99. data/lib/waw/validation/boolean_validator.rb +32 -0
  100. data/lib/waw/validation/comparison_validations.rb +45 -0
  101. data/lib/waw/validation/date_validator.rb +31 -0
  102. data/lib/waw/validation/default_validator.rb +30 -0
  103. data/lib/waw/validation/dsl_ruby_extensions.rb +11 -0
  104. data/lib/waw/validation/errors.rb +17 -0
  105. data/lib/waw/validation/ext.rb +3 -0
  106. data/lib/waw/validation/file_validator.rb +30 -0
  107. data/lib/waw/validation/float_validator.rb +19 -0
  108. data/lib/waw/validation/helpers.rb +67 -0
  109. data/lib/waw/validation/integer_validator.rb +16 -0
  110. data/lib/waw/validation/isin_validator.rb +24 -0
  111. data/lib/waw/validation/mandatory_validator.rb +17 -0
  112. data/lib/waw/validation/missing_validator.rb +17 -0
  113. data/lib/waw/validation/not_validator.rb +20 -0
  114. data/lib/waw/validation/or_validator.rb +34 -0
  115. data/lib/waw/validation/regexp_validator.rb +29 -0
  116. data/lib/waw/validation/same_validator.rb +16 -0
  117. data/lib/waw/validation/signature.rb +157 -0
  118. data/lib/waw/validation/size_validations.rb +44 -0
  119. data/lib/waw/validation/string_validator.rb +15 -0
  120. data/lib/waw/validation/validator.rb +48 -0
  121. data/lib/waw/wawgen.rb +2 -0
  122. data/lib/waw/wawgen/create.rb +166 -0
  123. data/lib/waw/wawgen/project.rb +25 -0
  124. data/lib/waw/wspec.rb +5 -0
  125. data/lib/waw/wspec/browser.rb +240 -0
  126. data/lib/waw/wspec/dsl.rb +201 -0
  127. data/lib/waw/wspec/html_analysis.rb +136 -0
  128. data/lib/waw/wspec/html_analysis/tag.rb +56 -0
  129. data/lib/waw/wspec/runner.rb +70 -0
  130. data/lib/waw/wspec/scenario.rb +35 -0
  131. data/lib/waw/wspec/suite.rb +54 -0
  132. data/test/bricks/error_handler/config/test.cfg +2 -0
  133. data/test/bricks/error_handler/logs/webapp.log +1411 -0
  134. data/test/bricks/error_handler/test/error_handler.wspec +16 -0
  135. data/test/bricks/error_handler/waw.deploy +1 -0
  136. data/test/bricks/error_handler/waw.routing +27 -0
  137. data/test/integration/waw_create_integration_test.rb +24 -0
  138. data/test/spec/assumptions_spec.rb +30 -0
  139. data/test/spec/controllers/action_controller_spec.rb +14 -0
  140. data/test/spec/controllers/static/waw_access_spec.rb +112 -0
  141. data/test/spec/environment_utils_spec.rb +15 -0
  142. data/test/spec/ext/core/hash_spec.rb +58 -0
  143. data/test/spec/fixtures.rb +41 -0
  144. data/test/spec/fixtures/action/config/default.cfg +2 -0
  145. data/test/spec/fixtures/action/lib/action_controller_test.rb +12 -0
  146. data/test/spec/fixtures/action/waw.deploy +1 -0
  147. data/test/spec/fixtures/action/waw.routing +6 -0
  148. data/test/spec/fixtures/empty/waw.deploy +0 -0
  149. data/test/spec/fixtures/empty/waw.routing +0 -0
  150. data/test/spec/fullstate/on_class_spec.rb +59 -0
  151. data/test/spec/fullstate/on_instance_spec.rb +59 -0
  152. data/test/spec/fullstate/session_spec.rb +43 -0
  153. data/test/spec/fullstate/variable_spec.rb +55 -0
  154. data/test/spec/resource_collection_spec.rb +50 -0
  155. data/test/spec/test_all.rb +9 -0
  156. data/test/spec/tools/mail/mail_agent_spec.rb +116 -0
  157. data/test/spec/tools/mail/mail_spec.rb +56 -0
  158. data/test/spec/tools/mail/mailbox_spec.rb +57 -0
  159. data/test/spec/tools/mail/template_spec.rb +47 -0
  160. data/test/spec/validation/array_validation_spec.rb +63 -0
  161. data/test/spec/validation/array_validator_spec.rb +17 -0
  162. data/test/spec/validation/date_validation_spec.rb +35 -0
  163. data/test/spec/validation/default_validation_spec.rb +37 -0
  164. data/test/spec/validation/disjuctive_validation_spec.rb +33 -0
  165. data/test/spec/validation/errors_spec.rb +37 -0
  166. data/test/spec/validation/file_validator_spec.rb +34 -0
  167. data/test/spec/validation/mail_validation_spec.rb +51 -0
  168. data/test/spec/validation/missing_validation_spec.rb +43 -0
  169. data/test/spec/validation/same_validation_spec.rb +24 -0
  170. data/test/spec/validation/signature_intuition_spec.rb +37 -0
  171. data/test/spec/validation/signature_spec.rb +164 -0
  172. data/test/spec/validation/validation_spec.rb +28 -0
  173. data/test/spec/wspec/html_analysis/tag_spec.rb +38 -0
  174. data/test/spec/wspec/html_analysis_spec.rb +170 -0
  175. data/test/unit/test_all.rb +8 -0
  176. data/test/unit/waw/app_test.rb +126 -0
  177. data/test/unit/waw/app_test/config/commons.cfg +2 -0
  178. data/test/unit/waw/app_test/config/devel.cfg +1 -0
  179. data/test/unit/waw/config_test.rb +54 -0
  180. data/test/unit/waw/controllers/action_controller_test.rb +76 -0
  181. data/test/unit/waw/controllers/action_test.rb +35 -0
  182. data/test/unit/waw/controllers/example_action_controller_test.rb +24 -0
  183. data/test/unit/waw/controllers/multiple_action_controller_test.rb +78 -0
  184. data/test/unit/waw/controllers/static/example/css/example.css +1 -0
  185. data/test/unit/waw/controllers/static/example/index.html +1 -0
  186. data/test/unit/waw/controllers/static/example/js/example.js +1 -0
  187. data/test/unit/waw/controllers/static/example/pages/hello.wtpl +1 -0
  188. data/test/unit/waw/controllers/static/waw_access_test.rb +76 -0
  189. data/test/unit/waw/ext/rack_test.rb +74 -0
  190. data/test/unit/waw/resource_collection_test.rb +49 -0
  191. data/test/unit/waw/resources.txt +4 -0
  192. data/test/unit/waw/routing/routing_test.rb +26 -0
  193. data/test/unit/waw/utils/dsl_helper_test.rb +79 -0
  194. data/test/unit/waw/utils/dsl_helper_test_extensions1.rb +4 -0
  195. data/test/unit/waw/validation/signature_test.rb +193 -0
  196. data/test/unit/waw/validation_test.rb +319 -0
  197. data/test/unit/waw/wspec/html_analysis_test.html +81 -0
  198. data/test/unit/waw/wspec/html_analysis_test.rb +26 -0
  199. metadata +272 -0
@@ -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