waw 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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