trinidad 1.3.5 → 1.4.0.RC

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
1
  module Trinidad
2
- VERSION = '1.3.5'
2
+ VERSION = '1.4.0.RC'
3
3
  end
@@ -1,162 +1,311 @@
1
1
  module Trinidad
2
2
  class WebApp
3
- attr_reader :config, :app_config, :class_loader, :servlet
4
-
5
- def self.create(config, app_config)
6
- autodetect_configuration(config, app_config)
3
+
4
+ attr_reader :config, :default_config
7
5
 
8
- war?(app_config) ? WarWebApp.new(config, app_config) :
9
- rackup?(app_config) ? RackupWebApp.new(config, app_config) : RailsWebApp.new(config, app_config)
6
+ def self.create(config, default_config = Trinidad.configuration)
7
+ war?(config, default_config) ? WarWebApp.new(config, default_config) :
8
+ rackup?(config, default_config) ? RackupWebApp.new(config, default_config) :
9
+ RailsWebApp.new(config, default_config)
10
10
  end
11
11
 
12
- def self.rackup?(app_config)
13
- app_config.has_key?(:rackup) || !Dir['WEB-INF/**/config.ru'].empty?
12
+ def initialize(config, default_config)
13
+ @config, @default_config = config, default_config || {}
14
+ complete_config!
15
+ # NOTE: we should maybe @config.freeze here ?!
14
16
  end
15
17
 
16
- def self.war?(app_config)
17
- app_config[:context_path] =~ /\.war$/
18
+ def [](key)
19
+ key = key.to_sym
20
+ config.has_key?(key) ? config[key] : default_config[key]
18
21
  end
19
-
20
- def initialize(config, app_config, servlet_class = 'org.jruby.rack.RackServlet', servlet_name = 'RackServlet')
21
- @config = config
22
- @app_config = app_config
23
-
24
- generate_class_loader
25
-
26
- configure_rack_servlet(servlet_class, servlet_name) unless rack_servlet_configured?
22
+
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|
26
+ class_eval "def #{method}; self[:'#{method}']; end"
27
+ end
28
+
29
+ def web_xml; self[:web_xml] || self[:default_web_xml]; end
30
+ def default_web_xml; self[:default_web_xml]; end
31
+
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
36
+
37
+ def extensions
38
+ @extensions ||= begin
39
+ extensions = default_config[:extensions] || {}
40
+ extensions.merge(config[:extensions] || {})
41
+ end
42
+ end
43
+
44
+ def monitor
45
+ File.expand_path(self[:monitor] || 'tmp/restart.txt', work_dir)
27
46
  end
28
47
 
29
- def rack_listener
30
- context_listener unless rack_listener_configured?
48
+ def context_params
49
+ @context_params ||= {}
50
+ add_context_param 'jruby.min.runtimes', jruby_min_runtimes
51
+ add_context_param 'jruby.max.runtimes', jruby_max_runtimes
52
+ add_context_param 'jruby.initial.runtimes', jruby_min_runtimes
53
+ add_context_param 'jruby.compat.version', jruby_compat_version || RUBY_VERSION
54
+ add_context_param 'public.root', File.join('/', public_root)
55
+ @context_params
31
56
  end
57
+ # @deprecated replaced with {#context_params}
58
+ def init_params; context_params; end
32
59
 
33
- def init_params
34
- @params ||= {}
35
- add_parameter_unless_exist 'jruby.min.runtimes', jruby_min_runtimes.to_s
36
- add_parameter_unless_exist 'jruby.max.runtimes', jruby_max_runtimes.to_s
37
- add_parameter_unless_exist 'jruby.initial.runtimes', jruby_min_runtimes.to_s
38
- add_parameter_unless_exist 'public.root', File.join('/', public_root)
39
- add_parameter_unless_exist 'jruby.compat.version', RUBY_VERSION
40
- @params
60
+ def add_context_param(param_name, param_value)
61
+ @context_params ||= {}
62
+ if ! param_value.nil? && ! web_xml_context_param(param_name)
63
+ @context_params[param_name] = param_value.to_s
64
+ end
41
65
  end
42
66
 
67
+ 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
72
+ end
73
+
74
+ # @deprecated use {#deployment_descriptor}
43
75
  def default_deployment_descriptor
44
- @deployment_descriptor ||= if default_web_xml
76
+ @default_deployment_descriptor ||= if default_web_xml
45
77
  file = File.expand_path(File.join(work_dir, default_web_xml))
46
78
  File.exist?(file) ? file : nil
47
79
  end
48
80
  end
49
-
50
- def rack_servlet_configured?
51
- !!( web_xml && (
52
- web_xml.root.elements["/web-app/servlet[contains(servlet-class, 'org.jruby.rack.RackServlet')]"] ||
53
- web_xml.root.elements["/web-app/filter[contains(filter-class, 'org.jruby.rack.RackFilter')]"]
54
- )
55
- )
81
+
82
+ def class_loader
83
+ @class_loader ||= org.jruby.util.JRubyClassLoader.new(JRuby.runtime.jruby_class_loader)
56
84
  end
57
-
58
- def rack_listener_configured?
59
- !!( web_xml &&
60
- web_xml.root.elements["/web-app/listener[contains(listener-class, '#{context_listener}')]"]
61
- )
85
+
86
+ def class_loader!
87
+ ( @class_loader = nil ) || class_loader
88
+ end
89
+ # @deprecated replaced with {#class_loader!}
90
+ def generate_class_loader; class_loader!; end
91
+
92
+ def define_lifecycle
93
+ Trinidad::Lifecycle::WebApp::Default.new(self)
62
94
  end
63
95
 
64
- %w{ context_path web_app_dir libs_dir classes_dir default_web_xml
65
- jruby_min_runtimes jruby_max_runtimes rackup log }.each do |method_name|
66
- define_method method_name do
67
- sym = method_name.to_sym
68
- @app_config[sym] || @config[sym]
69
- end
96
+ # Reset the hold web application state so it gets re-initialized.
97
+ # Please note that the received configuration object are not cleared.
98
+ def reset!
99
+ vars = instance_variables.map(&:to_sym)
100
+ vars = vars - [ :'@config', :'@default_config' ]
101
+ vars.each { |var| instance_variable_set(var, nil) }
70
102
  end
103
+
104
+ def rack_servlet
105
+ return nil if @rack_servlet == false
106
+ @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'
71
110
 
72
- def public_root; @app_config[:public] || @config[:public] || 'public'; end
73
- def environment; @app_config[:environment] || @config[:environment] || 'development'; end
74
- def work_dir; @app_config[:work_dir] || @config[:work_dir] || web_app_dir; end
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
+ }
118
+ else
119
+ false # no need to setup a rack servlet
120
+ end
121
+ end || nil
122
+ end
123
+ # @deprecated use {#rack_servlet} instead
124
+ def servlet; rack_servlet; end
75
125
 
76
- def extensions
77
- @extensions ||= begin
78
- extensions = @config[:extensions] || {}
79
- extensions.merge!(@app_config[:extensions]) if @app_config[:extensions]
80
- extensions
81
- end
126
+ def rack_listener
127
+ context_listener unless web_xml_listener?(context_listener)
82
128
  end
83
-
84
- def war?; WebApp.war?(app_config); end
129
+
130
+ def war?; self.class.war?(config); end
85
131
 
86
132
  def solo?
87
- !self.is_a?(WarWebApp) && @app_config[:solo]
133
+ ! is_a?(WarWebApp) && config[:solo]
88
134
  end
89
135
 
90
136
  def threadsafe?
91
137
  jruby_min_runtimes.to_i == 1 && jruby_max_runtimes.to_i == 1
92
138
  end
93
-
94
- def monitor
95
- m_file = @app_config[:monitor] || @config[:monitor] || 'tmp/restart.txt'
96
- File.expand_path(m_file, work_dir)
139
+
140
+ protected
141
+
142
+ def context_listener
143
+ raise NotImplementedError.new "context_listener expected to be redefined"
97
144
  end
98
-
99
- def define_lifecycle
100
- Trinidad::Lifecycle::Default.new(self)
145
+
146
+ def complete_config!
147
+ config[:web_app_dir] ||= default_config[:web_app_dir] || Dir.pwd
101
148
  end
102
-
103
- def generate_class_loader
104
- @class_loader = org.jruby.util.JRubyClassLoader.new(JRuby.runtime.jruby_class_loader)
149
+
150
+ def web_xml_servlet?(servlet_class, servlet_name = nil)
151
+ !!( web_xml_doc && (
152
+ web_xml_doc.root.elements["/web-app/servlet[contains(servlet-class, '#{servlet_class}')]"]
153
+ )
154
+ )
105
155
  end
106
156
 
107
- protected
108
- def add_parameter_unless_exist(param_name, param_value)
109
- @params[param_name] = param_value unless web_context_param(param_name)
157
+ def web_xml_filter?(filter_class)
158
+ !!( web_xml_doc && (
159
+ web_xml_doc.root.elements["/web-app/filter[contains(filter-class, '#{filter_class}')]"]
160
+ )
161
+ )
110
162
  end
111
-
163
+
164
+ def web_xml_listener?(listener_class)
165
+ !!( web_xml_doc &&
166
+ web_xml_doc.root.elements["/web-app/listener[contains(listener-class, '#{listener_class}')]"]
167
+ )
168
+ end
169
+
170
+ def web_xml_context_param(name)
171
+ if web_xml_doc &&
172
+ param = web_xml_doc.root.elements["/web-app/context-param[contains(param-name, '#{name}')]"]
173
+ param.elements['param-value'].text
174
+ end
175
+ end
176
+
112
177
  private
113
- def web_xml
114
- return nil if @web_xml == false
115
- @web_xml ||=
178
+
179
+ def web_xml_doc
180
+ return @web_xml_doc || nil if ! @web_xml_doc.nil?
181
+ if deployment_descriptor
116
182
  begin
117
183
  require 'rexml/document'
118
- REXML::Document.new(File.read(default_deployment_descriptor))
184
+ @web_xml_doc = REXML::Document.new(File.read(deployment_descriptor))
119
185
  rescue REXML::ParseException => e
120
- puts "WARNING: invalid deployment descriptor:[#{default_deployment_descriptor}]"
121
- puts e.message
122
- false
123
- end unless default_deployment_descriptor.nil?
186
+ log = Trinidad::Logging::LogFactory.getLog('')
187
+ log.warn "invalid deployment descriptor:[#{deployment_descriptor}]\n #{e.message}"
188
+ @web_xml_doc = false
189
+ end
190
+ @web_xml_doc || nil
191
+ end
124
192
  end
125
-
126
- def web_context_param(param)
127
- if web_xml && param = web_xml.root.elements["/web-app/context-param[contains(param-name, '#{param}')]"]
128
- param.elements['param-value'].text
193
+
194
+ protected
195
+
196
+ def self.rackup?(config, default_config = nil)
197
+ return true if config.has_key?(:rackup)
198
+ web_app_dir = config[:web_app_dir] ||
199
+ (default_config && default_config[:web_app_dir]) || Dir.pwd
200
+ config_ru = (default_config && default_config[:rackup]) || 'config.ru'
201
+ # Check for rackup (but still use config/environment.rb for Rails 3)
202
+ if File.exists?(File.join(web_app_dir, config_ru)) &&
203
+ ! File.exists?(File.join(web_app_dir, 'config/environment.rb'))
204
+ config[:rackup] = config_ru
129
205
  end
206
+ config[:rackup] || ! Dir[File.join(web_app_dir, 'WEB-INF/**/config.ru')].empty?
130
207
  end
131
208
 
132
- def configure_rack_servlet(servlet_class, servlet_name)
133
- servlet_config = @config[:servlet] || @app_config[:servlet] || {}
134
- @servlet = {
135
- :class => servlet_config[:class] || servlet_class,
136
- :name => servlet_config[:name] || servlet_name,
137
- :instance => servlet_config[:instance]
138
- }
209
+ def self.war?(config, default_config = nil)
210
+ config[:context_path] && config[:context_path][-4..-1] == '.war'
139
211
  end
212
+
213
+ class Holder
214
+
215
+ def initialize(web_app, context)
216
+ @web_app, @context = web_app, context
217
+ end
218
+
219
+ attr_reader :web_app
220
+ attr_accessor :context
221
+
222
+ def monitor; web_app.monitor; end
223
+
224
+ attr_accessor :monitor_mtime
225
+
226
+ def try_lock
227
+ locked? ? false : lock
228
+ end
229
+
230
+ def locked?; !!@lock; end
231
+ def lock; @lock = true; end
232
+ def unlock; @lock = false; end
233
+
234
+ # @deprecated behaves Hash like for (<= 1.3.5) compatibility
235
+ def [](key)
236
+ case key.to_sym
237
+ when :app then
238
+ web_app
239
+ when :context then
240
+ context
241
+ when :lock then
242
+ @lock
243
+ when :monitor then
244
+ monitor
245
+ when :mtime then
246
+ monitor_mtime
247
+ else raise NoMethodError, key.to_s
248
+ end
249
+ end
140
250
 
141
- def self.autodetect_configuration(config, app_config)
142
- # Check for Rails threadsafe mode
143
- environment = app_config[:environment] || config[:environment]
144
- if threadsafe_instance?(app_config[:web_app_dir], environment)
145
- app_config[:jruby_min_runtimes] = 1
146
- app_config[:jruby_max_runtimes] = 1
251
+ # @deprecated behaves Hash like for (<= 1.3.5) compatibility
252
+ def []=(key, val)
253
+ case key.to_sym
254
+ when :context then
255
+ self.context=(val)
256
+ when :lock then
257
+ @lock = val
258
+ when :mtime then
259
+ self.monitor_mtime=(val)
260
+ else raise NoMethodError, "#{key}="
261
+ end
147
262
  end
148
263
 
149
- rackup = config[:rackup] || 'config.ru'
150
- app_config[:web_app_dir] ||= config[:web_app_dir] || Dir.pwd
151
- # Check for rackup (but still use config/environment.rb for Rails 3)
152
- if !app_config[:rackup] &&
153
- File.exists?(File.join(app_config[:web_app_dir], rackup)) &&
154
- !File.exists?(File.join(app_config[:web_app_dir], 'config/environment.rb'))
155
- app_config[:rackup] = rackup
264
+ end
265
+
266
+ end
267
+
268
+ # Rack web application (looks for a rackup config.ru file).
269
+ class RackupWebApp < WebApp
270
+
271
+ def context_params
272
+ add_context_param 'rack.env', environment
273
+ if rackup = self.rackup
274
+ rackup = File.join(rackup, 'config.ru') if File.directory?(rackup)
275
+ add_context_param 'rackup.path', rackup
156
276
  end
277
+ super
278
+ end
279
+
280
+ def context_listener; 'org.jruby.rack.RackServletContextListener'; end
281
+
282
+ end
283
+
284
+ # Rails web app specifics. Supports the same versions as jruby-rack !
285
+ class RailsWebApp < WebApp
286
+
287
+ def context_params
288
+ add_context_param 'rails.env', environment
289
+ add_context_param 'rails.root', '/'
290
+ super
157
291
  end
158
292
 
159
- def self.threadsafe_instance?(app_base, environment)
293
+ def context_listener; 'org.jruby.rack.rails.RailsServletContextListener'; end
294
+
295
+ protected
296
+
297
+ def complete_config!
298
+ super
299
+ # detect threadsafe! in config/environments/environment.rb :
300
+ if self.class.threadsafe?(web_app_dir, environment)
301
+ config[:jruby_min_runtimes] = 1
302
+ config[:jruby_max_runtimes] = 1
303
+ end
304
+ end
305
+
306
+ private
307
+
308
+ def self.threadsafe?(app_base, environment)
160
309
  threadsafe_match?("#{app_base}/config/environments/#{environment}.rb") ||
161
310
  threadsafe_match?("#{app_base}/config/environment.rb")
162
311
  end
@@ -164,5 +313,28 @@ module Trinidad
164
313
  def self.threadsafe_match?(file)
165
314
  File.exist?(file) && File.readlines(file).any? { |l| l =~ /^[^#]*threadsafe!/ }
166
315
  end
316
+
317
+ end
318
+
319
+ # A web application for deploying (java) .war files.
320
+ class WarWebApp < WebApp
321
+
322
+ def context_path
323
+ super.gsub(/\.war$/, '')
324
+ end
325
+
326
+ def work_dir
327
+ File.join(web_app_dir.gsub(/\.war$/, ''), 'WEB-INF')
328
+ end
329
+
330
+ def monitor
331
+ File.expand_path(web_app_dir)
332
+ end
333
+
334
+ def define_lifecycle
335
+ Trinidad::Lifecycle::WebApp::War.new(self)
336
+ end
337
+
167
338
  end
339
+
168
340
  end
@@ -3,20 +3,21 @@ require 'tmpdir'
3
3
 
4
4
  namespace :tomcat do
5
5
 
6
- TOMCAT_CORE_PATH = File.expand_path('../../trinidad-libs/tomcat-core.jar', __FILE__)
6
+ TOMCAT_CORE_JAR = File.expand_path('../../trinidad-libs/tomcat-core.jar', __FILE__)
7
7
  TOMCAT_MAVEN_REPO = 'http://repo2.maven.org/maven2/org/apache/tomcat'
8
8
 
9
9
  tomcat = "#{TOMCAT_MAVEN_REPO}/embed/tomcat-embed-core/%s/tomcat-embed-core-%s.jar"
10
10
  tomcat_jasper = "#{TOMCAT_MAVEN_REPO}/embed/tomcat-embed-jasper/%s/tomcat-embed-jasper-%s.jar"
11
11
  tomcat_logging = "#{TOMCAT_MAVEN_REPO}/embed/tomcat-embed-logging-log4j/%s/tomcat-embed-logging-log4j-%s.jar"
12
12
 
13
- dependencies = [tomcat, tomcat_jasper, tomcat_logging]
13
+ dependencies = [ tomcat, tomcat_jasper, tomcat_logging ]
14
14
 
15
- desc "Updates Tomcat to a given version"
16
- task :update, :version do |task, args|
15
+ task :fetch, :version do |_, args|
17
16
  tomcat_version = [args[:version]] * 2
18
17
 
19
- Dir.chdir(Dir.tmpdir) do
18
+ temp_dir = File.join(Dir.tmpdir, (Time.now.to_f * 1000).to_i.to_s)
19
+ FileUtils.mkdir temp_dir
20
+ Dir.chdir(temp_dir) do
20
21
  dependencies.each do |dependency|
21
22
  dependency_path = dependency % tomcat_version
22
23
  dependency_name = dependency_path.split('/').last
@@ -28,17 +29,47 @@ namespace :tomcat do
28
29
  end
29
30
 
30
31
  # build the jar again
31
- puts "building the tomcat's core jar"
32
- %x{jar -cvf #{TOMCAT_CORE_PATH} META-INF javax org}
32
+ entries = Dir.entries(temp_dir) - [ '.', '..']
33
+ puts "building #{TOMCAT_CORE_JAR}"
34
+ %x{jar -cvf #{TOMCAT_CORE_JAR} #{entries.join(' ')}}
33
35
  end
36
+ FileUtils.rm_r temp_dir
37
+ end
38
+
39
+ TARGET_DIR = File.expand_path('../../target', __FILE__)
40
+
41
+ desc "Updates Tomcat to a given version e.g. `rake tomcat:update[7.0.26]`"
42
+ task :update, :version do |_, args|
43
+ Rake::Task['tomcat:fetch'].invoke(version = args[:version])
44
+ Rake::Task['tomcat:patch'].invoke
34
45
 
35
- puts "updating tomcat's version number to #{tomcat_version.first}"
46
+ puts "updating tomcat's version number to '#{version}'"
36
47
  path = File.expand_path('../../lib/trinidad/jars.rb', __FILE__)
37
48
  file = File.read(path)
38
- file.gsub!(/TOMCAT_VERSION = '(.+)'/, "TOMCAT_VERSION = '#{tomcat_version.first}'")
49
+ file.gsub!(/TOMCAT_VERSION = '(.+)'/, "TOMCAT_VERSION = '#{version}'")
39
50
  File.open(path, 'w') { |io| io.write(file) }
40
-
51
+
41
52
  puts "DONE - Tomcat's version has been updated succesfully, please build Trinidad again."
42
53
  end
54
+
55
+ task :compile do
56
+ FileUtils.mkdir TARGET_DIR unless File.exists?(TARGET_DIR)
57
+ sh 'javac -Xlint:deprecation -Xlint:unchecked -g -source 1.6 -target 1.6 ' +
58
+ "-classpath #{TOMCAT_CORE_JAR} -d #{TARGET_DIR} " +
59
+ Dir["src/java/**/*.java"].join(" ")
60
+ end
61
+
62
+ task :patch => :compile do
63
+ Dir.chdir(TARGET_DIR) do
64
+ entries = Dir.entries(TARGET_DIR) - [ '.', '..']
65
+ puts "updating #{TOMCAT_CORE_JAR}"
66
+ %x{jar -uvf #{TOMCAT_CORE_JAR} #{entries.join(' ')}}
67
+ end
68
+ end
69
+
70
+ task :clean do
71
+ rm_r TARGET_DIR if File.exist?(TARGET_DIR)
72
+ rm TOMCAT_CORE_JAR if File.exist?(TOMCAT_CORE_JAR)
73
+ end
43
74
 
44
75
  end