trinidad 1.4.1 → 1.4.3

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.
@@ -1,3 +1,6 @@
1
+ require 'trinidad/lifecycle/base'
2
+ require 'trinidad/lifecycle/web_app/shared'
3
+
1
4
  module Trinidad
2
5
  module Lifecycle
3
6
  module WebApp
@@ -15,7 +18,7 @@ module Trinidad
15
18
  end
16
19
 
17
20
  def configure(context)
18
- super
21
+ super # TODO assuming warbler .war !
19
22
  configure_class_loader(context)
20
23
  end
21
24
 
@@ -32,7 +35,7 @@ module Trinidad
32
35
  def expand_war_app(context)
33
36
  unless File.exist?(context.doc_base)
34
37
  host = context.parent
35
- war_file = java.io.File.new(web_app.web_app_dir)
38
+ war_file = java.io.File.new(web_app.root_dir)
36
39
  war = java.net.URL.new("jar:" + war_file.toURI.toURL.to_s + "!/")
37
40
  path_name = File.basename(context.doc_base)
38
41
 
@@ -42,7 +45,7 @@ module Trinidad
42
45
 
43
46
  def remove_war_app(context)
44
47
  require 'fileutils'
45
- FileUtils.rm_rf web_app.web_app_dir.gsub(/\.war$/, '')
48
+ FileUtils.rm_rf web_app.root_dir.gsub(/\.war$/, '')
46
49
  end
47
50
 
48
51
  end
@@ -1,3 +1,6 @@
1
+ require 'trinidad/configuration'
2
+ require 'trinidad/web_app'
3
+
1
4
  module Trinidad
2
5
  class Server
3
6
  attr_reader :config, :tomcat, :web_apps
@@ -40,15 +43,15 @@ module Trinidad
40
43
  end
41
44
 
42
45
  def ssl_enabled?
43
- @config[:ssl] && !@config[:ssl].empty?
46
+ !! @config[:ssl] && ! @config[:ssl].empty?
44
47
  end
45
48
 
46
49
  def ajp_enabled?
47
- @config[:ajp] && !@config[:ajp].empty?
50
+ !! @config[:ajp] && ! @config[:ajp].empty?
48
51
  end
49
52
 
50
53
  def http_configured?
51
- (@config[:http] && !@config[:http].empty?) || @config[:address] != 'localhost'
54
+ (!! @config[:http] && ! @config[:http].empty?) || @config[:address] != 'localhost'
52
55
  end
53
56
 
54
57
  def add_ajp_connector
@@ -107,10 +110,10 @@ module Trinidad
107
110
 
108
111
  def add_web_app(web_app, host = nil)
109
112
  host ||= web_app.config[:host] || @tomcat.host
110
- app_context = @tomcat.addWebapp(host, web_app.context_path, web_app.web_app_dir)
111
- Trinidad::Extensions.configure_webapp_extensions(web_app.extensions, @tomcat, app_context)
112
- app_context.add_lifecycle_listener(web_app.define_lifecycle)
113
- app_context
113
+ context = @tomcat.addWebapp(host, web_app.context_path, web_app.root_dir)
114
+ Trinidad::Extensions.configure_webapp_extensions(web_app.extensions, @tomcat, context)
115
+ context.add_lifecycle_listener(web_app.define_lifecycle)
116
+ context
114
117
  end
115
118
 
116
119
  def start
@@ -144,9 +147,7 @@ module Trinidad
144
147
 
145
148
  def create_from_web_apps
146
149
  @config[:web_apps].map do |name, app_config|
147
- app_config[:context_path] ||= (name.to_s == 'default' ? '' : "/#{name}")
148
- app_config[:web_app_dir] ||= Dir.pwd
149
-
150
+ app_config[:context_name] ||= name
150
151
  create_web_app(app_config)
151
152
  end if @config[:web_apps]
152
153
  end
@@ -163,11 +164,10 @@ module Trinidad
163
164
 
164
165
  apps_path.map do |path|
165
166
  if File.directory?(path) || path =~ /\.war$/
166
- name = File.basename(path)
167
167
  create_web_app({
168
- :context_path => (name.to_s == 'default' ? '' : "/#{name}"),
169
- :web_app_dir => File.expand_path(path),
170
- :host => host
168
+ :context_name => File.basename(path),
169
+ :root_dir => File.expand_path(path),
170
+ :host => host
171
171
  })
172
172
  end
173
173
  end
@@ -1,3 +1,3 @@
1
1
  module Trinidad
2
- VERSION = '1.4.1'
2
+ VERSION = '1.4.3'
3
3
  end
@@ -1,6 +1,10 @@
1
+ require 'trinidad/configuration'
2
+
1
3
  module Trinidad
2
4
  class WebApp
3
5
 
6
+ @@defaults = Trinidad::Configuration::DEFAULTS
7
+
4
8
  attr_reader :config, :default_config
5
9
 
6
10
  def self.create(config, default_config = Trinidad.configuration)
@@ -17,22 +21,98 @@ module Trinidad
17
21
 
18
22
  def [](key)
19
23
  key = key.to_sym
20
- config.has_key?(key) ? config[key] : default_config[key]
24
+ config.key?(key) ? config[key] : default_config[key]
25
+ end
26
+
27
+ def key?(key, use_default = true)
28
+ key = key.to_sym
29
+ return true if config.has_key?(key)
30
+ use_default ? default_config.key?(key) : false
21
31
  end
22
32
 
23
- %w{ context_path web_app_dir libs_dir classes_dir async_supported
24
- jruby_min_runtimes jruby_max_runtimes jruby_compat_version rackup log
25
- reload_strategy }.each do |method|
33
+ %w{ root_dir jruby_compat_version
34
+ rackup log async_supported reload_strategy }.each do |method|
26
35
  class_eval "def #{method}; self[:'#{method}']; end"
27
36
  end
37
+ alias_method :web_app_dir, :root_dir # is getting deprecated soon
38
+
39
+ def context_path
40
+ path = self[:context_path] || self[:path]
41
+ path ? path.to_s : path
42
+ end
43
+
44
+ def context_name
45
+ name = self[:context_name] || self[:name]
46
+ name ? name.to_s : name
47
+ end
48
+
49
+ # NOTE: should be set to application root (base) directory thus
50
+ # JRuby-Rack correctly resolves relative paths for the context!
51
+ def doc_base; self[:doc_base] || root_dir; end
28
52
 
53
+ def jruby_min_runtimes
54
+ if min = config[:jruby_min_runtimes]
55
+ return min.to_i # min specified overrides :threadsafe
56
+ else # but :threadsafe takes precendence over default :
57
+ self[:threadsafe] ? 1 : default_config[:jruby_min_runtimes]
58
+ end
59
+ end
60
+
61
+ def jruby_max_runtimes
62
+ if max = config[:jruby_max_runtimes]
63
+ return max.to_i # max specified overrides :threadsafe
64
+ else # but :threadsafe takes precendence over default :
65
+ self[:threadsafe] ? 1 : default_config[:jruby_max_runtimes]
66
+ end
67
+ end
68
+
69
+ def jruby_runtime_acquire_timeout
70
+ self[:jruby_runtime_acquire_timeout] || 5.0 # default 10s seems too high
71
+ end
72
+
73
+ def environment; self[:environment] || @@defaults[:environment]; end # TODO check web.xml
74
+
75
+ def public_dir
76
+ @public_dir ||= expand_path(public_root)
77
+ end
78
+
79
+ # by (a "Rails") convention use '[RAILS_ROOT]/tmp'
80
+ def work_dir
81
+ @work_dir ||= self[:work_dir] || File.join(root_dir, 'tmp')
82
+ end
83
+
84
+ # by a "Rails" convention defaults to '[RAILS_ROOT]/log'
85
+ def log_dir
86
+ @log_dir ||= self[:log_dir] || File.join(root_dir, 'log')
87
+ end
88
+
89
+ def monitor
90
+ File.expand_path(self[:monitor] || 'restart.txt', work_dir)
91
+ end
92
+
93
+ def context_xml; self[:context_xml] || self[:default_context_xml]; end
29
94
  def web_xml; self[:web_xml] || self[:default_web_xml]; end
30
95
  def default_web_xml; self[:default_web_xml]; end
31
96
 
32
- def public_root; self[:public] || 'public'; end
33
- def environment; self[:environment] || 'development'; end
34
- def work_dir; self[:work_dir] || web_app_dir; end
35
- def log_dir; self[:log_dir] || File.join(work_dir, 'log'); end
97
+ def java_lib
98
+ # accepts #deprecated :libs_dir syntax
99
+ self[:java_lib] || self[:libs_dir] || @@defaults[:java_lib]
100
+ end
101
+
102
+ def java_classes
103
+ # accepts #deprecated :classes_dir syntax
104
+ self[:java_classes] || self[:classes_dir] || File.join(java_lib, 'classes')
105
+ end
106
+
107
+ def java_lib_dir
108
+ @java_lib_dir ||= self[:java_lib_dir] || expand_path(java_lib)
109
+ end
110
+ alias_method :libs_dir, :java_lib_dir # #deprecated
111
+
112
+ def java_classes_dir
113
+ @java_classes_dir ||= self[:java_classes_dir] || expand_path(java_classes)
114
+ end
115
+ alias_method :classes_dir, :java_classes_dir # #deprecated
36
116
 
37
117
  def extensions
38
118
  @extensions ||= begin
@@ -40,16 +120,13 @@ module Trinidad
40
120
  extensions.merge(config[:extensions] || {})
41
121
  end
42
122
  end
43
-
44
- def monitor
45
- File.expand_path(self[:monitor] || 'tmp/restart.txt', work_dir)
46
- end
47
123
 
48
124
  def context_params
49
125
  @context_params ||= {}
50
126
  add_context_param 'jruby.min.runtimes', jruby_min_runtimes
51
127
  add_context_param 'jruby.max.runtimes', jruby_max_runtimes
52
128
  add_context_param 'jruby.initial.runtimes', jruby_min_runtimes
129
+ add_context_param 'jruby.runtime.acquire.timeout', jruby_runtime_acquire_timeout
53
130
  add_context_param 'jruby.compat.version', jruby_compat_version || RUBY_VERSION
54
131
  add_context_param 'public.root', File.join('/', public_root)
55
132
  @context_params
@@ -65,22 +142,80 @@ module Trinidad
65
142
  end
66
143
 
67
144
  def deployment_descriptor
68
- @deployment_descriptor ||= if web_xml
69
- file = File.expand_path(File.join(work_dir, web_xml))
70
- File.exist?(file) ? file : nil
71
- end
145
+ return nil if @deployment_descriptor == false
146
+ @deployment_descriptor ||= expand_path(web_xml) || false
72
147
  end
73
148
 
74
149
  # @deprecated use {#deployment_descriptor}
75
150
  def default_deployment_descriptor
76
- @default_deployment_descriptor ||= if default_web_xml
77
- file = File.expand_path(File.join(work_dir, default_web_xml))
78
- File.exist?(file) ? file : nil
151
+ return nil if @default_deployment_descriptor == false
152
+ @default_deployment_descriptor ||= expand_path(default_web_xml) || false
153
+ end
154
+
155
+ def public_root
156
+ @public_root ||= ( public_config[:root] || @@defaults[:public] )
157
+ end
158
+ alias_method :public, :public_root
159
+
160
+ # we do support nested :public configuration e.g. :
161
+ # public:
162
+ # root: /assets
163
+ # cache: true
164
+ # cache_ttl: 60000
165
+ def public_config
166
+ @public_config ||=
167
+ self[:public].is_a?(String) ?
168
+ { :root => self[:public] } :
169
+ ( self[:public] || {} )
170
+ end
171
+
172
+ def aliases # :public => { :aliases => ... }
173
+ return nil unless aliases = ( self[:aliases] || public_config[:aliases] )
174
+ return aliases if aliases.is_a?(String)
175
+ # "/aliasPath1=docBase1,/aliasPath2=docBase2"
176
+ @aliases ||= aliases.map do |path, base|
177
+ path = path.to_s
178
+ if (root = '/') != path[0, 1]
179
+ path = (root << path)
180
+ end
181
+ "#{path}=#{File.expand_path(base, root_dir)}"
182
+ end.join(',')
183
+ end
184
+
185
+ def caching_allowed? # :public => { :cached => ... }
186
+ # ((BaseDirContext) resources).setCached(isCachingAllowed())
187
+ return @caching_allowed unless @caching_allowed.nil?
188
+ @caching_allowed = self[:caching_allowed]
189
+ if @caching_allowed.nil?
190
+ @caching_allowed = public_config[:cached]
191
+ if @caching_allowed.nil?
192
+ @caching_allowed = environment != 'development'
193
+ end
79
194
  end
195
+ @caching_allowed = !! @caching_allowed
196
+ end
197
+
198
+ # The cache max size in kB
199
+ def cache_max_size # :public => { :cache_max_size => ... }
200
+ # ((BaseDirContext) resources).setCacheMaxSize
201
+ self[:cache_max_size] || public_config[:cache_max_size]
202
+ end
203
+
204
+ # The max size for a cached object in kB
205
+ def cache_object_max_size # :public => { :cache_object_max_size => ... }
206
+ # ((BaseDirContext) resources).setCacheObjectMaxSize
207
+ self[:cache_object_max_size] || public_config[:cache_object_max_size]
208
+ end
209
+
210
+ # Cache entry time-to-live in millis
211
+ def cache_ttl # :public => { :cache_ttl => ... }
212
+ # ((BaseDirContext) resources).setCacheTTL
213
+ self[:cache_ttl] || public_config[:cache_ttl]
80
214
  end
81
215
 
82
216
  def class_loader
83
- @class_loader ||= org.jruby.util.JRubyClassLoader.new(JRuby.runtime.jruby_class_loader)
217
+ @class_loader ||=
218
+ org.jruby.util.JRubyClassLoader.new(JRuby.runtime.jruby_class_loader)
84
219
  end
85
220
 
86
221
  def class_loader!
@@ -94,29 +229,108 @@ module Trinidad
94
229
  end
95
230
 
96
231
  # Reset the hold web application state so it gets re-initialized.
97
- # Please note that the received configuration object are not cleared.
232
+ # Please note that the configuration objects are not cleared.
98
233
  def reset!
99
234
  vars = instance_variables.map(&:to_sym)
100
235
  vars = vars - [ :'@config', :'@default_config' ]
101
236
  vars.each { |var| instance_variable_set(var, nil) }
102
237
  end
103
238
 
239
+ DEFAULT_SERVLET_CLASS = nil # by default we resolve by it's name
240
+ DEFAULT_SERVLET_NAME = 'default'
241
+
242
+ # Returns a servlet config for the DefaultServlet.
243
+ # This servlet is setup for each and every Tomcat context and is named
244
+ # 'default' and mapped to '/' we allow fine tunning of this servlet.
245
+ # Return values should be interpreted as follows :
246
+ # true - do nothing leave the servlet as set-up (by default)
247
+ # false - remove the set-up default (e.g. configured in web.xml)
248
+ def default_servlet
249
+ return @default_servlet unless @default_servlet.nil?
250
+ @default_servlet ||= begin
251
+ if ! web_xml_servlet?(DEFAULT_SERVLET_CLASS, DEFAULT_SERVLET_NAME)
252
+ default_servlet = self[:default_servlet]
253
+ if default_servlet.is_a?(javax.servlet.Servlet)
254
+ { :instance => default_servlet }
255
+ elsif default_servlet == false
256
+ false # forced by user to remove
257
+ elsif default_servlet == true
258
+ true # forced by user to leave as is
259
+ else
260
+ default_servlet = {} if default_servlet.nil?
261
+ unless default_servlet.key?(:class)
262
+ # we use a custom class by default to server /public assets :
263
+ default_servlet[:class] = 'rb.trinidad.servlets.DefaultServlet'
264
+ end
265
+ default_servlet
266
+ end
267
+ else
268
+ false # configured in web.xml thus remove the (default) "default"
269
+ end
270
+ end
271
+ end
272
+
273
+ JSP_SERVLET_CLASS = nil # by default we resolve by it's name
274
+ JSP_SERVLET_NAME = 'jsp'
275
+
276
+ # Returns a servlet config for the JspServlet.
277
+ # This servlet is setup by default for every Tomcat context and is named
278
+ # 'jsp' with '*.jsp' and '*.jspx' mappings.
279
+ # Return values should be interpreted as follows :
280
+ # true - do nothing leave the servlet as set-up (by default)
281
+ # false - remove the set-up servlet (by default we do not need jsp support)
282
+ def jsp_servlet
283
+ return @jsp_servlet unless @jsp_servlet.nil?
284
+ @jsp_servlet ||= begin
285
+ if ! web_xml_servlet?(JSP_SERVLET_CLASS, JSP_SERVLET_NAME)
286
+ jsp_servlet = self[:jsp_servlet]
287
+ if jsp_servlet.is_a?(javax.servlet.Servlet)
288
+ { :instance => jsp_servlet }
289
+ else
290
+ jsp_servlet || false # remove jsp support unless specified
291
+ end
292
+ else
293
+ false # configured in web.xml thus remove the default "jsp"
294
+ end
295
+ end
296
+ end
297
+
298
+ RACK_SERVLET_CLASS = 'org.jruby.rack.RackServlet'
299
+ RACK_SERVLET_NAME = 'rack' # in-case of a "custom" rack servlet class
300
+ RACK_FILTER_CLASS = 'org.jruby.rack.RackFilter'
301
+ RACK_FILTER_NAME = 'rack'
302
+
303
+ # Returns a config for the RackServlet or nil if no need to set-up one.
304
+ # (to be used for dispatching to this Rack / Rails web application)
104
305
  def rack_servlet
105
306
  return nil if @rack_servlet == false
106
307
  @rack_servlet ||= begin
107
- servlet_config = self[:servlet] || {}
108
- servlet_class = servlet_config[:class] || 'org.jruby.rack.RackServlet'
109
- servlet_name = servlet_config[:name] || 'RackServlet'
110
-
111
- if ! web_xml_servlet?(servlet_class, servlet_name) &&
112
- ! web_xml_filter?('org.jruby.rack.RackFilter')
113
- {
114
- :class => servlet_class, :name => servlet_name,
115
- :async_supported => !! servlet_config[:async_supported],
116
- :instance => servlet_config[:instance]
117
- }
308
+ rack_servlet = self[:rack_servlet] || self[:servlet] || {}
309
+
310
+ if rack_servlet.is_a?(javax.servlet.Servlet)
311
+ { :instance => rack_servlet, :name => RACK_SERVLET_NAME, :mapping => '/*' }
118
312
  else
119
- false # no need to setup a rack servlet
313
+ servlet_class = rack_servlet[:class] || RACK_SERVLET_CLASS
314
+ servlet_name = rack_servlet[:name] || RACK_SERVLET_NAME
315
+
316
+ if ! web_xml_servlet?(servlet_class, servlet_name) &&
317
+ ! web_xml_filter?(RACK_FILTER_CLASS, RACK_FILTER_NAME)
318
+ {
319
+ :instance => rack_servlet[:instance],
320
+ :class => servlet_class, :name => servlet_name,
321
+ :init_params => rack_servlet[:init_params],
322
+ :async_supported => !! ( rack_servlet.has_key?(:async_supported) ?
323
+ rack_servlet[:async_supported] : async_supported ),
324
+ :load_on_startup => ( rack_servlet[:load_on_startup] || 2 ).to_i,
325
+ :mapping => rack_servlet[:mapping] || '/*'
326
+ }
327
+ else
328
+ if ! rack_servlet.empty?
329
+ logger.info "ignoring :rack_servlet configuration for " +
330
+ "#{context_path} due #{deployment_descriptor}"
331
+ end
332
+ false # no need to setup a rack servlet
333
+ end
120
334
  end
121
335
  end || nil
122
336
  end
@@ -132,9 +346,9 @@ module Trinidad
132
346
  def solo?
133
347
  ! is_a?(WarWebApp) && config[:solo]
134
348
  end
135
-
349
+
136
350
  def threadsafe?
137
- jruby_min_runtimes.to_i == 1 && jruby_max_runtimes.to_i == 1
351
+ jruby_min_runtimes == 1 && jruby_max_runtimes == 1
138
352
  end
139
353
 
140
354
  protected
@@ -144,34 +358,56 @@ module Trinidad
144
358
  end
145
359
 
146
360
  def complete_config!
147
- config[:web_app_dir] ||= default_config[:web_app_dir] || Dir.pwd
361
+ config[:root_dir] ||= self.class.root_dir(config, default_config)
362
+ config[:context_path] = self.class.context_path(config, default_config)
148
363
  end
149
364
 
150
365
  public
151
366
 
367
+ # Returns true if there's a servlet with the given servlet-class name
368
+ # configured or if the optional name second argument is given it also
369
+ # checks for a servlet with the given name.
152
370
  def web_xml_servlet?(servlet_class, servlet_name = nil)
153
- !!( web_xml_doc && (
154
- web_xml_doc.root.elements["/web-app/servlet[servlet-class = '#{servlet_class}']"]
155
- )
156
- )
371
+ return nil unless web_xml_doc
372
+ if servlet_class
373
+ servlet_xpath = "/web-app/servlet[servlet-class = '#{servlet_class}']"
374
+ return true if web_xml_doc.root.elements[servlet_xpath] # else try name
375
+ end
376
+ if servlet_name
377
+ servlet_xpath = "/web-app/servlet[servlet-name = '#{servlet_name}']"
378
+ return !! web_xml_doc.root.elements[servlet_xpath]
379
+ end
380
+
381
+ return false if servlet_class || servlet_name
382
+ raise ArgumentError, "nor servlet_class nor servlet_name given"
157
383
  end
158
384
 
159
- def web_xml_filter?(filter_class)
160
- !!( web_xml_doc && (
161
- web_xml_doc.root.elements["/web-app/filter[filter-class = '#{filter_class}']"]
162
- )
163
- )
385
+ # Returns true if a filter definition with a given filter-class is found.
386
+ def web_xml_filter?(filter_class, filter_name = nil)
387
+ return nil unless web_xml_doc
388
+ if filter_class
389
+ filter_xpath = "/web-app/filter[filter-class = '#{filter_class}']"
390
+ return true if web_xml_doc.root.elements[filter_xpath] # else try name
391
+ end
392
+ if filter_name
393
+ filter_xpath = "/web-app/filter[filter-name = '#{filter_name}']"
394
+ return !! web_xml_doc.root.elements[filter_xpath]
395
+ end
396
+
397
+ return false if filter_class || filter_name
398
+ raise ArgumentError, "nor filter_class nor filter_name given"
164
399
  end
165
400
 
401
+ # Returns true if a listener definition with a given listener-class is found.
166
402
  def web_xml_listener?(listener_class)
167
- !!( web_xml_doc &&
168
- web_xml_doc.root.elements["/web-app/listener[listener-class = '#{listener_class}']"]
169
- )
403
+ return nil unless web_xml_doc
404
+ !! web_xml_doc.root.elements["/web-app/listener[listener-class = '#{listener_class}']"]
170
405
  end
171
406
 
407
+ # Returns a param-value for a context-param with a given param-name.
172
408
  def web_xml_context_param(name)
173
- if web_xml_doc &&
174
- param = web_xml_doc.root.elements["/web-app/context-param[param-name = '#{name}']"]
409
+ return nil unless web_xml_doc
410
+ if param = web_xml_doc.root.elements["/web-app/context-param[param-name = '#{name}']"]
175
411
  param.elements['param-value'].text
176
412
  end
177
413
  end
@@ -180,54 +416,99 @@ module Trinidad
180
416
 
181
417
  def web_xml_doc
182
418
  return @web_xml_doc || nil unless @web_xml_doc.nil?
183
- if deployment_descriptor
419
+ descriptor = deployment_descriptor
420
+ if descriptor && File.exist?(descriptor)
184
421
  begin
185
422
  require 'rexml/document'
186
- @web_xml_doc = REXML::Document.new(File.read(deployment_descriptor))
423
+ @web_xml_doc = REXML::Document.new(File.read(descriptor))
187
424
  rescue REXML::ParseException => e
188
- log = Trinidad::Logging::LogFactory.getLog('')
189
- log.warn "invalid deployment descriptor:[#{deployment_descriptor}]\n #{e.message}"
425
+ logger.warn "invalid deployment descriptor:[#{descriptor}]\n #{e.message}"
190
426
  @web_xml_doc = false
191
427
  end
192
428
  @web_xml_doc || nil
193
429
  end
194
430
  end
195
431
 
432
+ def expand_path(path)
433
+ if path
434
+ path_file = java.io.File.new(path)
435
+ if path_file.absolute?
436
+ path_file.absolute_path
437
+ else
438
+ File.expand_path(path, root_dir)
439
+ end
440
+ end
441
+ end
442
+
443
+ def logger
444
+ @logger ||= Trinidad::Logging::LogFactory.getLog('')
445
+ end
446
+
196
447
  protected
197
448
 
198
449
  def self.rackup?(config, default_config = nil)
199
450
  return true if config.has_key?(:rackup)
200
- web_app_dir = config[:web_app_dir] ||
201
- (default_config && default_config[:web_app_dir]) || Dir.pwd
451
+ root_dir = root_dir(config, default_config)
202
452
  config_ru = (default_config && default_config[:rackup]) || 'config.ru'
203
453
  # check for rackup (but still use config/environment.rb for rails 3)
204
- if File.exists?(File.join(web_app_dir, config_ru)) &&
454
+ if File.exists?(File.join(root_dir, config_ru)) &&
205
455
  ! rails?(config, default_config) # do not :rackup a rails app
206
456
  config[:rackup] = config_ru
207
457
  end
208
- config[:rackup] || ! Dir[File.join(web_app_dir, 'WEB-INF/**/config.ru')].empty?
458
+ config[:rackup] || ! Dir[File.join(root_dir, 'WEB-INF/**/config.ru')].empty?
209
459
  end
210
460
 
211
461
  def self.rails?(config, default_config = nil)
212
- web_app_dir = config[:web_app_dir] ||
213
- (default_config && default_config[:web_app_dir]) || Dir.pwd
462
+ root_dir = root_dir(config, default_config)
214
463
  # standart Rails 3.x `class Application < Rails::Application`
215
- if File.exists?(application = File.join(web_app_dir, 'config/application.rb'))
216
- application_rb = File.read(application)
217
- return true if application_rb =~ /^[^#]*Rails::Application/
464
+ if File.exists?(application = File.join(root_dir, 'config/application.rb'))
465
+ return true if file_line_match?(application, /^[^#]*Rails::Application/)
218
466
  end
219
- if File.exists?(environment = File.join(web_app_dir, 'config/environment.rb'))
220
- environment_rb = File.read(environment)
221
- # customized Rails 3.x, expect a `Rails::Application` subclass
222
- return true if environment_rb =~ /^[^#]*Rails::Application/
223
- # plain-old Rails 2.3 `RAILS_GEM_VERSION = '2.3.14'` ...
224
- return true if environment_rb =~ /^[^#]*RAILS_GEM_VERSION/
467
+ if File.exists?(environment = File.join(root_dir, 'config/environment.rb'))
468
+ return true if file_line_match?(environment) do |line|
469
+ # customized Rails 3.x, expects a `Rails::Application` subclass
470
+ # or a plain-old Rails 2.3 with `RAILS_GEM_VERSION = '2.3.14'`
471
+ line =~ /^[^#]*Rails::Application/ || line =~ /^[^#]*RAILS_GEM_VERSION/
472
+ end
225
473
  end
226
474
  false
227
475
  end
228
476
 
229
477
  def self.war?(config, default_config = nil)
230
- config[:context_path] && config[:context_path][-4..-1] == '.war'
478
+ config[:context_path] && config[:context_path].to_s[-4..-1] == '.war'
479
+ end
480
+
481
+ private
482
+
483
+ def self.root_dir(config, default_config)
484
+ # for backwards compatibility accepts the :web_app_dir "alias"
485
+ config[:root_dir] || config[:web_app_dir] ||
486
+ ( default_config &&
487
+ ( default_config[:root_dir] || default_config[:web_app_dir] ) ) ||
488
+ Dir.pwd
489
+ end
490
+
491
+ def self.context_path(config, default_config = nil)
492
+ path = config[:context_path] ||
493
+ ( default_config && default_config[:context_path] )
494
+ unless path
495
+ name = config[:context_name] ||
496
+ ( default_config && default_config[:context_name] )
497
+ path = name.to_s == 'default' ? '/' : "/#{name}"
498
+ end
499
+ path = "/#{path}" if path.to_s[0, 1] != '/'
500
+ path.to_s
501
+ end
502
+
503
+ def self.file_line_match?(path, pattern = nil)
504
+ File.open(path) do |file|
505
+ if block_given?
506
+ file.each_line { |line| return true if yield(line) }
507
+ else
508
+ file.each_line { |line| return true if line =~ pattern }
509
+ end
510
+ end
511
+ false
231
512
  end
232
513
 
233
514
  class Holder
@@ -251,7 +532,7 @@ module Trinidad
251
532
  def lock; @lock = true; end
252
533
  def unlock; @lock = false; end
253
534
 
254
- # @deprecated behaves Hash like for (<= 1.3.5) compatibility
535
+ # #deprecated behaves Hash like for (<= 1.3.5) compatibility
255
536
  def [](key)
256
537
  case key.to_sym
257
538
  when :app then
@@ -268,7 +549,7 @@ module Trinidad
268
549
  end
269
550
  end
270
551
 
271
- # @deprecated behaves Hash like for (<= 1.3.5) compatibility
552
+ # #deprecated behaves Hash like for (<= 1.3.5) compatibility
272
553
  def []=(key, val)
273
554
  case key.to_sym
274
555
  when :context then
@@ -317,9 +598,9 @@ module Trinidad
317
598
  def complete_config!
318
599
  super
319
600
  # detect threadsafe! in config/environments/environment.rb :
320
- if self.class.threadsafe?(web_app_dir, environment)
321
- config[:jruby_min_runtimes] = 1
322
- config[:jruby_max_runtimes] = 1
601
+ if ! key?(:threadsafe) && self.class.threadsafe?(root_dir, environment)
602
+ config[:jruby_min_runtimes] = 1 unless key?(:jruby_min_runtimes, false)
603
+ config[:jruby_max_runtimes] = 1 unless key?(:jruby_max_runtimes, false)
323
604
  end
324
605
  end
325
606
 
@@ -331,7 +612,7 @@ module Trinidad
331
612
  end
332
613
 
333
614
  def self.threadsafe_match?(file)
334
- File.exist?(file) && File.readlines(file).any? { |l| l =~ /^[^#]*threadsafe!/ }
615
+ File.exist?(file) && file_line_match?(file, /^[^#]*threadsafe!/)
335
616
  end
336
617
 
337
618
  end
@@ -343,12 +624,16 @@ module Trinidad
343
624
  super.gsub(/\.war$/, '')
344
625
  end
345
626
 
627
+ def log_dir
628
+ @log_dir ||= self[:log_dir] || File.join(work_dir, 'log')
629
+ end
630
+
346
631
  def work_dir
347
- File.join(web_app_dir.gsub(/\.war$/, ''), 'WEB-INF')
632
+ @work_dir ||= File.join(root_dir.gsub(/\.war$/, ''), 'WEB-INF')
348
633
  end
349
634
 
350
635
  def monitor
351
- File.expand_path(web_app_dir)
636
+ File.expand_path(root_dir)
352
637
  end
353
638
 
354
639
  def define_lifecycle