trinidad 1.4.1 → 1.4.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -29,7 +29,7 @@ module Trinidad
29
29
 
30
30
  # Load the configuration from the given options and return it.
31
31
  def load!(options)
32
- config = config_file(options[:web_app_dir])
32
+ config = config_file(options[:root_dir] || options[:web_app_dir])
33
33
  if config && File.exist?(config)
34
34
  if yaml = (File.extname(config) == '.yml')
35
35
  require 'yaml'; require 'erb'
@@ -45,10 +45,12 @@ module Trinidad
45
45
  end
46
46
  alias_method :load_configuration, :load!
47
47
 
48
+ DEFAULT_CONFIG_FILE = 'config/trinidad.{yml,rb}'
49
+
48
50
  def config_file(base_dir = nil)
49
51
  base_dir ||= Dir.pwd
50
52
  if @config_file.nil? # false means do not use no config file
51
- Dir.glob(File.join(base_dir, 'config', 'trinidad.{yml,rb}')).first
53
+ Dir.glob(File.join(base_dir, DEFAULT_CONFIG_FILE)).first
52
54
  else
53
55
  @config_file && File.expand_path(@config_file, base_dir)
54
56
  end
@@ -59,79 +61,86 @@ module Trinidad
59
61
  def options_parser
60
62
  require 'optparse'
61
63
  @parser ||= OptionParser.new do |opts|
62
- opts.banner = 'Trinidad server default options:'
64
+ opts.banner = 'Usage: trinidad [server options]'
63
65
  opts.separator ''
64
66
 
65
- opts.on('-d', '--dir WEB_APP_DIRECTORY', 'web app directory path',
66
- "default: #{Dir.pwd}") do |dir|
67
- default_options[:web_app_dir] = dir
67
+ opts.on('-d', '--dir ROOT_DIR', 'web application root directory',
68
+ "default: current working directory") do |dir|
69
+ default_options[:root_dir] = dir
68
70
  end
69
71
 
70
- opts.on('-e', '--env ENVIRONMENT', '(rails) environment',
71
- "default: #{default_options[:environment]}") do |env|
72
+ opts.on('-e', '--env ENVIRONMENT', 'rack (rails) environment',
73
+ "default: #{default(:environment)}") do |env|
72
74
  default_options[:environment] = env
73
75
  end
74
-
75
- opts.on('-p', '--port PORT', 'port to bind to',
76
- "default: #{default_options[:port]}") do |port|
77
- default_options[:port] = port
76
+
77
+ opts.on('-r', '--rackup [RACKUP_FILE]', 'rackup configuration file',
78
+ "default: config.ru") do |rackup|
79
+ default_options[:rackup] = rackup || 'config.ru'
78
80
  end
79
81
 
82
+ opts.on('--public', '--public PUBLIC_DIR', 'web application public root',
83
+ "default: #{default(:public)}") do |public|
84
+ default_options[:public] = public
85
+ end
86
+
80
87
  opts.on('-c', '--context CONTEXT_PATH', 'application context path',
81
- "default: #{default_options[:context_path]}") do |path|
88
+ "default: #{default(:context_path)}") do |path|
82
89
  default_options[:context_path] = path
83
90
  end
84
-
85
- opts.on('--lib', '--jars LIBS_DIR', 'directory containing java jars used by the application',
86
- "default: #{default_options[:libs_dir]}") do |dir|
87
- default_options[:libs_dir] = dir
88
- end
89
-
90
- opts.on('--classes', '--classes CLASSES_DIR', 'directory containing java classes used by the application',
91
- "default: #{default_options[:classes_dir]}") do |dir|
92
- default_options[:classes_dir] = dir
91
+
92
+ opts.on('--monitor', '--monitor MONITOR_FILE', 'monitor for application re-deploys',
93
+ "default: tmp/restart.txt") do |monitor|
94
+ default_options[:monitor] = monitor
93
95
  end
94
-
95
- opts.on('-s', '--ssl [SSL_PORT]', 'enable secure socket layout',
96
- "default port: 8443") do |port|
97
- default_options[:ssl] = { :port => (port || 8443).to_i }
96
+
97
+ opts.on('-t', '--threadsafe', 'force thread-safe mode (use single runtime)') do
98
+ default_options[:jruby_min_runtimes] = 1
99
+ default_options[:jruby_max_runtimes] = 1
98
100
  end
99
-
100
- opts.on('-a', '--ajp [AJP_PORT]', 'enable ajp connections (deprecated)',
101
- "default port: 8009") do |port|
102
- default_options[:ajp] = { :port => (port || 8009).to_i }
101
+
102
+ opts.on('--runtimes MIN:MAX', 'use given number of min/max jruby runtimes',
103
+ "default: #{default(:jruby_min_runtimes)}:#{default(:jruby_max_runtimes)}") do
104
+ |min_max| min, max = min_max.split(':')
105
+ default_options[:jruby_min_runtimes] = min.to_i if min
106
+ default_options[:jruby_max_runtimes] = max.to_i if max
103
107
  end
104
-
108
+
105
109
  opts.on('-f', '--config [CONFIG_FILE]', 'configuration file',
106
- "default: config/trinidad.{yml,rb}") do |file|
110
+ "default: #{DEFAULT_CONFIG_FILE}") do |file|
107
111
  self.config_file = file
108
112
  end
109
-
110
- opts.on('-r', '--rackup [RACKUP_FILE]', 'rackup configuration file',
111
- 'default: config.ru') do |rackup|
112
- default_options[:rackup] = rackup || 'config.ru'
113
+
114
+ opts.on('--address', '--address ADDRESS', 'host address',
115
+ "default: #{default(:address)}") do |address|
116
+ default_options[:address] = address
113
117
  end
114
-
115
- opts.on('--public', '--public DIRECTORY', 'public directory', 'default: public') do |public|
116
- default_options[:public] = public
118
+
119
+ opts.on('-p', '--port PORT', 'port to bind to',
120
+ "default: #{default(:port)}") do |port|
121
+ default_options[:port] = port
117
122
  end
118
123
 
119
- opts.on('-t', '--threadsafe', 'force thread-safe mode') do
120
- default_options[:jruby_min_runtimes] = 1
121
- default_options[:jruby_max_runtimes] = 1
124
+ opts.on('-s', '--ssl [SSL_PORT]', 'enable secure socket layout',
125
+ "default port: 8443") do |port|
126
+ default_options[:ssl] = { :port => (port || 8443).to_i }
122
127
  end
123
128
 
124
- opts.on('--address', '--address ADDRESS', 'host address', 'default: localhost') do |address|
125
- default_options[:address] = address
129
+ opts.on('-a', '--ajp [AJP_PORT]', 'enable the AJP web protocol',
130
+ "default port: 8009") do |port|
131
+ default_options[:ajp] = { :port => (port || 8009).to_i }
126
132
  end
127
133
 
128
- opts.on('-g', '--log LEVEL', 'log level', 'default: INFO') do |log|
129
- default_options[:log] = log
134
+ opts.on('--java_lib LIB_DIR', '--lib LIB_DIR (deprecated use --java_lib)',
135
+ 'contains .jar files used by the app',
136
+ "default: #{default(:java_lib)}") do |lib|
137
+ default_options[:java_lib] = lib
130
138
  end
131
139
 
132
- opts.on('-v', '--version', 'display the current version') do
133
- puts "trinidad #{Trinidad::VERSION} (tomcat #{Trinidad::TOMCAT_VERSION})"
134
- exit
140
+ opts.on('--java_classes CLASSES_DIR', '--classes CLASSES_DIR (deprecated use --java_classes)',
141
+ 'contains java classes used by the app',
142
+ "default: #{default_java_classes}") do |classes|
143
+ default_options[:java_classes] = classes
135
144
  end
136
145
 
137
146
  opts.on('-l', '--load EXTENSION_NAMES', Array, 'load options for extensions') do |ext_names|
@@ -140,20 +149,37 @@ module Trinidad
140
149
  end
141
150
  end
142
151
 
143
- opts.on('--apps', '--apps APPS_BASE_DIR', 'applications base directory') do |path|
144
- default_options[:apps_base] = path
152
+ opts.on('--apps_base APPS_BASE_DIR', '--apps APPS_BASE_DIR (deprecated use --apps_base)',
153
+ 'set applications base directory') do |apps_base|
154
+ default_options[:apps_base] = apps_base
145
155
  end
146
-
147
- opts.on('--monitor' '--monitor MONITOR_FILE', 'monitor file for hot deployments') do |monitor|
148
- default_options[:monitor] = monitor
156
+
157
+ opts.on('-g', '--log LEVEL', 'set logging level') do |log|
158
+ default_options[:log] = log
149
159
  end
150
160
 
151
- opts.on('-h', '--help', 'display the help') do
161
+ opts.on('-v', '--version', 'show server version') do
162
+ puts "Trinidad #{Trinidad::VERSION} (Tomcat #{Trinidad::TOMCAT_VERSION})"
163
+ exit
164
+ end
165
+
166
+ opts.on('-h', '--help', 'display this help') do
152
167
  puts opts
153
168
  exit
154
169
  end
155
170
  end
156
171
  end
157
172
 
173
+ private
174
+
175
+ def default(key)
176
+ default_options[key] || Configuration::DEFAULTS[key]
177
+ end
178
+
179
+ def default_java_classes
180
+ default(:java_classes) ||
181
+ ( default(:java_lib) && File.join(default(:java_lib), 'classes') )
182
+ end
183
+
158
184
  end
159
185
  end
@@ -9,10 +9,10 @@ module Trinidad
9
9
  config = ( self.configuration ||= Configuration.new )
10
10
  args.compact!
11
11
  if options = args.shift
12
- options = Trinidad::Configuration.symbolize_options(options)
12
+ options = Configuration.symbolize_options(options)
13
13
  args.each do |opts|
14
- opts = Trinidad::Configuration.symbolize_options(opts)
15
- options = Trinidad::Configuration.merge_options(options, opts)
14
+ opts = Configuration.symbolize_options(opts)
15
+ options = Configuration.merge_options(options, opts)
16
16
  end
17
17
  config.update!(options)
18
18
  end
@@ -32,20 +32,22 @@ module Trinidad
32
32
  # the instance using Trinidad#configuration
33
33
  class Configuration
34
34
 
35
+ DEFAULTS = {
36
+ :port => 3000,
37
+ :address => 'localhost',
38
+ :environment => 'development',
39
+ :context_path => '/',
40
+ :public => 'public',
41
+ :java_lib => 'lib/java',
42
+ :default_web_xml => 'config/web.xml',
43
+ :jruby_min_runtimes => 1,
44
+ :jruby_max_runtimes => 5,
45
+ :log => 'INFO',
46
+ :trap => true
47
+ }
48
+
35
49
  def initialize(options = {})
36
- @config = {
37
- :port => 3000,
38
- :address => 'localhost',
39
- :environment => 'development',
40
- :context_path => '/',
41
- :libs_dir => 'lib',
42
- :classes_dir => 'classes',
43
- :default_web_xml => 'config/web.xml',
44
- :jruby_min_runtimes => 1,
45
- :jruby_max_runtimes => 5,
46
- :log => 'INFO',
47
- :trap => true
48
- }
50
+ @config = DEFAULTS.clone
49
51
  update!(options)
50
52
  end
51
53
 
@@ -77,15 +79,16 @@ module Trinidad
77
79
  end
78
80
 
79
81
  %w{ port address environment context_path
80
- libs_dir classes_dir default_web_xml
81
- jruby_min_runtimes jruby_max_runtimes
82
- rackup servlet public hosts
82
+ java_lib libs_dir java_classes classes_dir default_web_xml
83
+ jruby_min_runtimes jruby_max_runtimes jruby_compat_version
84
+ rackup servlet rack_servlet default_servlet public hosts
83
85
  http ajp ssl extensions
84
86
  apps_base web_apps web_app_dir
85
- monitor log trap }.each do |method|
87
+ monitor reload_strategy log trap }.each do |method|
86
88
  class_eval "def #{method}; self[:'#{method}']; end"
87
89
  class_eval "def #{method}=(value); self[:'#{method}'] = value; end"
88
90
  end
91
+ # TODO #deprecate libs_dir classes_dir servlet
89
92
 
90
93
  # a Hash like #symbolize helper
91
94
  def self.symbolize_options(options, deep = true)
@@ -1,3 +1,5 @@
1
+ require 'trinidad/lifecycle/base'
2
+
1
3
  module Trinidad
2
4
  module Lifecycle
3
5
  # A host lifecycle listener - monitors deployed web apps.
@@ -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
@@ -14,47 +17,65 @@ module Trinidad
14
17
  configure_context_params(context)
15
18
  configure_context_loader(context)
16
19
  end
17
-
20
+
21
+ def before_init(event)
22
+ super
23
+ set_context_xml event.lifecycle
24
+ # AFTER_INIT_EVENT ContextConfig#init() will pick this up
25
+ end
26
+
18
27
  protected
19
28
 
29
+ @@_add_context_config = true # due backward compatibility
30
+
20
31
  def configure_deployment_descriptor(context)
21
- if descriptor = web_app.deployment_descriptor
32
+ descriptor = web_app.deployment_descriptor
33
+ if descriptor && File.exist?(descriptor)
22
34
  listeners = context.findLifecycleListeners
23
35
  context_config = listeners && listeners.find do |listener|
24
36
  listener.is_a?(Trinidad::Tomcat::ContextConfig)
25
37
  end
26
38
 
27
- unless context_config
28
- context_config = Trinidad::Tomcat::ContextConfig.new
29
- context.addLifecycleListener(context_config)
39
+ if context_config.nil?
40
+ if @@_add_context_config
41
+ context_config = Trinidad::Tomcat::ContextConfig.new
42
+ context.addLifecycleListener(context_config)
43
+ else
44
+ raise "initialized context is missing a ContextConfig listener"
45
+ end
30
46
  end
31
47
 
32
48
  context_config.setDefaultWebXml(descriptor)
49
+ descriptor
33
50
  end
34
- descriptor
35
51
  end
36
52
 
37
53
  def configure_rack_servlet(context)
38
54
  wrapper = context.create_wrapper
39
- if web_app.rack_servlet[:instance]
40
- wrapper.servlet = web_app.rack_servlet[:instance]
55
+ rack_servlet = web_app.rack_servlet
56
+ if rack_servlet[:instance]
57
+ wrapper.servlet = rack_servlet[:instance]
41
58
  else
42
- wrapper.servlet_class = web_app.rack_servlet[:class]
43
- wrapper.async_supported = web_app.rack_servlet[:async_supported]
59
+ wrapper.servlet_class = rack_servlet[:class]
60
+ wrapper.async_supported = rack_servlet[:async_supported]
61
+ wrapper.load_on_startup = rack_servlet[:load_on_startup]
62
+ add_init_params wrapper, rack_servlet[:init_params]
44
63
  end
45
- wrapper.name = web_app.rack_servlet[:name]
64
+ name = wrapper.name = rack_servlet[:name]
46
65
 
47
66
  context.add_child(wrapper)
48
- context.add_servlet_mapping('/*', wrapper.name)
67
+ add_servlet_mapping(context, rack_servlet[:mapping], name)
49
68
  end
50
69
 
51
70
  def configure_rack_listener(context)
52
- context.addApplicationListener(web_app.rack_listener) unless web_app.rack_servlet[:instance]
71
+ unless web_app.rack_servlet[:instance]
72
+ context.add_application_listener(web_app.rack_listener)
73
+ end
53
74
  end
54
75
 
55
76
  def configure_context_params(context)
56
77
  web_app.context_params.each do |name, value|
57
- context.addParameter(name, value)
78
+ context.add_parameter(name, value)
58
79
  end
59
80
  end
60
81
  # @deprecated use {#configure_context_params}
@@ -63,28 +84,41 @@ module Trinidad
63
84
  def configure_context_loader(context)
64
85
  class_loader = web_app.class_loader
65
86
 
66
- add_application_jars(class_loader)
67
87
  add_application_java_classes(class_loader)
88
+ add_application_jars(class_loader) # classes takes precedence !
68
89
 
69
90
  loader = Trinidad::Tomcat::WebappLoader.new(class_loader)
70
91
  context.loader = loader # does loader.container = context
71
92
  end
72
93
 
73
94
  def add_application_jars(class_loader)
74
- return unless web_app.libs_dir
75
-
76
- resources_dir = File.join(web_app.web_app_dir, web_app.libs_dir, '**', '*.jar')
77
-
78
- Dir[resources_dir].each do |resource|
79
- class_loader.addURL(java.io.File.new(resource).to_url)
95
+ return unless lib_dir = web_app.java_lib_dir
96
+ Dir[ File.join(lib_dir, "**/*.jar") ].each do |jar|
97
+ logger.debug "[#{web_app.context_path}] adding jar: #{jar}"
98
+ class_loader.addURL java.io.File.new(jar).to_url
80
99
  end
81
100
  end
82
101
 
83
102
  def add_application_java_classes(class_loader)
84
- return unless web_app.classes_dir
85
-
86
- resources_dir = File.join(web_app.web_app_dir, web_app.classes_dir)
87
- class_loader.addURL(java.io.File.new(resources_dir).to_url)
103
+ return unless classes_dir = web_app.java_classes_dir
104
+ class_loader.addURL java.io.File.new(classes_dir).to_url
105
+ end
106
+
107
+ def set_context_xml(context)
108
+ # behave similar to a .war - checking /META-INF/context.xml on CP
109
+ context_xml = web_app.context_xml
110
+ context_xml = 'META-INF/context.xml' if context_xml.nil?
111
+ if context_xml
112
+ # NOTE: make it absolute to ContextConfig to not use a baseDir :
113
+ unless java.io.File.new(context_xml).absolute?
114
+ if web_app.java_classes_dir
115
+ context_xml = File.join(web_app.java_classes_dir, context_xml)
116
+ else
117
+ context_xml = File.expand_path(context_xml, web_app.root_dir)
118
+ end
119
+ end
120
+ context.setDefaultContextXml(context_xml)
121
+ end
88
122
  end
89
123
 
90
124
  end
@@ -17,37 +17,138 @@ module Trinidad
17
17
  super
18
18
  configure(event.lifecycle)
19
19
  end
20
-
20
+
21
21
  # Configure the web application before it's started.
22
22
  def configure(context)
23
+ adjust_context(context)
23
24
  remove_defaults(context)
25
+ configure_default_servlet(context)
26
+ configure_jsp_servlet(context)
24
27
  configure_logging(context)
25
28
  end
26
29
 
27
30
  protected
28
-
31
+
32
+ def adjust_context(context)
33
+ context.name = web_app.context_name if web_app.context_name
34
+ context.doc_base = web_app.doc_base if web_app.doc_base
35
+ context.work_dir = web_app.work_dir if web_app.work_dir
36
+ context.aliases = web_app.aliases if web_app.aliases
37
+
38
+ context.caching_allowed = web_app.caching_allowed?
39
+ context.cache_ttl = web_app.cache_ttl if web_app.cache_ttl
40
+ if max_size = web_app.cache_max_size
41
+ context.cache_max_size = max_size
42
+ end
43
+ if object_max_size = web_app.cache_object_max_size
44
+ context.cache_object_max_size = object_max_size
45
+ end
46
+ end
47
+
48
+ def configure_default_servlet(context)
49
+ configure_builtin_servlet(context,
50
+ web_app.default_servlet,
51
+ Trinidad::WebApp::DEFAULT_SERVLET_NAME
52
+ )
53
+ end
54
+
55
+ def configure_jsp_servlet(context)
56
+ wrapper = configure_builtin_servlet(context,
57
+ web_app.jsp_servlet,
58
+ Trinidad::WebApp::JSP_SERVLET_NAME
59
+ )
60
+ if wrapper == false # jsp servlet removed
61
+ context.process_tlds = false
62
+ end
63
+ wrapper
64
+ end
65
+
29
66
  def configure_logging(context)
30
67
  Trinidad::Logging.configure_web_app(web_app, context)
31
68
  end
32
-
69
+
33
70
  private
34
71
 
72
+ def configure_builtin_servlet(context, servlet_config, name)
73
+ name_wrapper = context.find_child(name)
74
+ case servlet_config
75
+ when true
76
+ return true # nothing to do leave built-in servlet as is
77
+ when false
78
+ # remove what Tomcat set-up (e.g. use one from web.xml)
79
+ remove_servlet_mapping(context, name)
80
+ context.remove_child(name_wrapper)
81
+ return false
82
+ else
83
+ wrapper, name = name_wrapper, name
84
+ if servlet = servlet_config[:instance]
85
+ wrapper = context.create_wrapper
86
+ wrapper.name = name = servlet_config[:name] || name
87
+ wrapper.servlet = servlet
88
+ context.remove_child(name_wrapper)
89
+ context.add_child(wrapper)
90
+ elsif servlet_class = servlet_config[:class]
91
+ wrapper.servlet_class = servlet_class
92
+ end
93
+ # do not remove wrapper but only "update" the default :
94
+ wrapper.load_on_startup = ( servlet_config[:load_on_startup] ||
95
+ name_wrapper.load_on_startup ).to_i
96
+ add_init_params(wrapper, servlet_config[:init_params])
97
+ if mapping = servlet_config[:mapping]
98
+ # NOTE: we override the default mapping :
99
+ remove_servlet_mapping(context, name)
100
+ add_servlet_mapping(context, mapping, name)
101
+ # else keep the servlet mapping as is ...
102
+ end
103
+ wrapper
104
+ end
105
+ end
106
+
35
107
  def remove_defaults(context)
36
- context.remove_welcome_file('index.jsp')
37
108
  context.remove_welcome_file('index.htm')
38
109
  context.remove_welcome_file('index.html')
39
-
40
- jsp_servlet = context.find_child('jsp')
41
- context.remove_child(jsp_servlet) if jsp_servlet
42
-
43
- context.remove_servlet_mapping('*.jspx')
44
- context.remove_servlet_mapping('*.jsp')
45
-
46
- context.process_tlds = false
47
- context.xml_validation = false
110
+ context.remove_welcome_file('index.jsp')
111
+ end
112
+
113
+ def add_init_params(wrapper, params)
114
+ return unless params
115
+ params.each do |param, value|
116
+ val = value.to_s unless value.nil?
117
+ wrapper.add_init_parameter(param.to_s, val)
118
+ end
119
+ end
120
+
121
+ def add_servlet_mapping(context, mapping, name)
122
+ if mapping.is_a?(String) || mapping.is_a?(Symbol)
123
+ context.add_servlet_mapping(mapping.to_s, name)
124
+ else
125
+ mapping.each { |m| add_servlet_mapping(context, m, name) }
126
+ end
127
+ end
128
+
129
+ # Remove all servlet mappings for given (servlet) name.
130
+ def remove_servlet_mapping(context, name)
131
+ find_servlet_mapping(context, name).each do
132
+ |pattern| context.remove_servlet_mapping(pattern)
133
+ end
134
+ end
135
+
136
+ # Find all servlet mappings for given (servlet) name.
137
+ def find_servlet_mapping(context, name)
138
+ name_mapping = []
139
+ context.find_servlet_mappings.each do |pattern|
140
+ mapping_for = context.find_servlet_mapping(pattern)
141
+ name_mapping << pattern if mapping_for == name
142
+ end
143
+ name_mapping
144
+ end
145
+
146
+ def logger
147
+ @logger ||= Trinidad::Logging::LogFactory.
148
+ getLog('org.apache.catalina.core.StandardContext')
48
149
  end
49
150
 
50
151
  end
51
- end
152
+ end
52
153
  end
53
154
  end