jettywrapper 1.7.0 → 2.0.0

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.
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ file = File.expand_path("../../Gemfile", __FILE__)
4
+
5
+ if File.exists?(file)
6
+ puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
7
+ instance_eval File.read(file)
8
+ end
9
+
10
+ gem 'activesupport', '~> 4.1.1'
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ file = File.expand_path("../../Gemfile", __FILE__)
4
+
5
+ if File.exists?(file)
6
+ puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
7
+ instance_eval File.read(file)
8
+ end
9
+
10
+ gem 'activesupport', '~> 4.2.0.beta2'
data/jettywrapper.gemspec CHANGED
@@ -14,20 +14,19 @@ Gem::Specification.new do |s|
14
14
  s.description = %q{Spin up a jetty instance (e.g., the one at https://github.com/projecthydra/hydra-jetty) and wrap test in it. This lets us run tests against a real copy of solr and fedora.}
15
15
  s.files = `git ls-files`.split("\n")
16
16
  s.test_files = `git ls-files -- {spec}/*`.split("\n")
17
- # s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
17
  s.require_paths = ["lib"]
18
+ s.license = 'APACHE2'
19
19
 
20
20
  s.required_rubygems_version = ">= 1.3.6"
21
21
 
22
22
  s.add_dependency "logger"
23
- s.add_dependency "mediashelf-loggable"
24
23
  s.add_dependency "childprocess"
25
24
  s.add_dependency "i18n"
26
25
  s.add_dependency "activesupport", ">=3.0.0"
27
26
 
28
- s.add_development_dependency "rspec"
27
+ s.add_development_dependency "rspec", '~> 2.99'
28
+ s.add_development_dependency "rspec-its"
29
29
  s.add_development_dependency 'rake'
30
-
31
30
 
32
31
  s.add_development_dependency 'yard'#, '0.6.5' # Yard > 0.6.5 won't generate docs.
33
32
  # I don't know why & don't have time to
@@ -1,3 +1,3 @@
1
1
  class Jettywrapper
2
- VERSION = "1.7.0"
2
+ VERSION = "2.0.0"
3
3
  end
data/lib/jettywrapper.rb CHANGED
@@ -1,26 +1,24 @@
1
- require 'loggable'
2
1
  require 'singleton'
3
2
  require 'fileutils'
4
3
  require 'shellwords'
5
4
  require 'socket'
6
5
  require 'timeout'
7
6
  require 'childprocess'
7
+ require 'active_support/benchmarkable'
8
8
  require 'active_support/core_ext/hash'
9
9
  require 'erb'
10
10
  require 'yaml'
11
+ require 'logger'
11
12
 
12
13
  Dir[File.expand_path(File.join(File.dirname(__FILE__),"tasks/*.rake"))].each { |ext| load ext } if defined?(Rake)
13
14
 
14
-
15
15
  # Jettywrapper is a Singleton class, so you can only create one jetty instance at a time.
16
16
  class Jettywrapper
17
-
17
+
18
18
  include Singleton
19
- include Loggable
20
19
  include ActiveSupport::Benchmarkable
21
-
22
-
23
- attr_accessor :jetty_home # Jetty's home directory
20
+
21
+ attr_accessor :jetty_home # Jetty's home directory
24
22
  attr_accessor :port # Jetty's port. Default is 8888. Note that attribute is named port, but params passed in expect :jetty_port
25
23
  attr_accessor :startup_wait # How many seconds to wait for jetty to spin up. Default is 5.
26
24
  attr_accessor :quiet # true (default) to reduce Jetty's output
@@ -28,21 +26,20 @@ class Jettywrapper
28
26
  attr_accessor :base_path # The root of the application. Used for determining where log files and PID files should go.
29
27
  attr_accessor :java_opts # Options to pass to java (ex. ["-Xmx512mb", "-Xms128mb"])
30
28
  attr_accessor :jetty_opts # Options to pass to jetty (ex. ["etc/my_jetty.xml", "etc/other.xml"] as in http://wiki.eclipse.org/Jetty/Reference/jetty.xml_usage
31
-
29
+
32
30
  # configure the singleton with some defaults
33
31
  def initialize(params = {})
34
32
  self.base_path = self.class.app_root
35
33
  end
36
34
 
37
-
38
- # Methods inside of the class << self block can be called directly on Jettywrapper, as class methods.
35
+ # Methods inside of the class << self block can be called directly on Jettywrapper, as class methods.
39
36
  # Methods outside the class << self block must be called on Jettywrapper.instance, as instance methods.
40
37
  class << self
41
38
 
42
39
  attr_writer :hydra_jetty_version, :url, :tmp_dir, :jetty_dir, :env
43
40
 
44
41
  def hydra_jetty_version
45
- @hydra_jetty_version ||= 'v7.0.0'
42
+ @hydra_jetty_version ||= 'v8.1.1'
46
43
  end
47
44
 
48
45
  def url
@@ -63,16 +60,17 @@ class Jettywrapper
63
60
  end
64
61
 
65
62
  def download(url = nil)
63
+ return if File.exists? zip_file
66
64
  self.url = url if url
67
65
  logger.info "Downloading jetty at #{self.url} ..."
68
66
  FileUtils.mkdir tmp_dir unless File.exists? tmp_dir
69
67
  system "curl -L #{self.url} -o #{zip_file}"
70
68
  abort "Unable to download jetty from #{self.url}" unless $?.success?
71
69
  end
72
-
70
+
73
71
  def unzip
74
72
  download unless File.exists? zip_file
75
- logger.info "Unpacking jetty..."
73
+ logger.info "Unpacking #{zip_file}..."
76
74
  tmp_save_dir = File.join tmp_dir, 'jetty_generator'
77
75
  system "unzip -d #{tmp_save_dir} -qo #{zip_file}"
78
76
  abort "Unable to unzip #{zip_file} into tmp_save_dir/" unless $?.success?
@@ -88,8 +86,8 @@ class Jettywrapper
88
86
 
89
87
  def expanded_zip_dir(tmp_save_dir)
90
88
  # This old way is more specific, but won't work for blacklight-jetty
91
- #expanded_dir = Dir[File.join(tmp_save_dir, "hydra-jetty-*")].first
92
- Dir[File.join(tmp_save_dir, "*")].first
89
+ #expanded_dir = Dir[File.join(tmp_save_dir, "hydra-jetty-*")].first
90
+ Dir[File.join(tmp_save_dir, "*")].first
93
91
  end
94
92
 
95
93
  def clean
@@ -113,25 +111,25 @@ class Jettywrapper
113
111
 
114
112
  def env
115
113
  @env ||= begin
116
- case
117
- when ENV['JETTYWRAPPER_ENV']
114
+ case
115
+ when ENV['JETTYWRAPPER_ENV']
118
116
  ENV['JETTYWRAPPER_ENV']
119
117
  when defined?(Rails) && Rails.respond_to?(:env)
120
118
  Rails.env
121
- when ENV['RAILS_ENV']
122
- ENV['RAILS_ENV']
123
- when ENV['environment']
124
- ENV['environment']
119
+ when ENV['RAILS_ENV']
120
+ ENV['RAILS_ENV']
121
+ when ENV['environment']
122
+ ENV['environment']
125
123
  else
126
124
  default_environment
127
125
  end
128
126
  end
129
127
  end
130
-
128
+
131
129
  def default_environment
132
130
  'development'
133
131
  end
134
-
132
+
135
133
  def load_config(config_name = env)
136
134
  @env = config_name
137
135
  jetty_file = "#{app_root}/config/jetty.yml"
@@ -160,15 +158,14 @@ class Jettywrapper
160
158
  config = jetty_yml.with_indifferent_access
161
159
  config[config_name] || config['default'.freeze]
162
160
  end
163
-
164
161
 
165
- # Set the jetty parameters. It accepts a Hash of symbols.
162
+ # Set the jetty parameters. It accepts a Hash of symbols.
166
163
  # @param [Hash<Symbol>] params
167
164
  # :jetty_home Required. Jetty's home direcotry
168
165
  # :jetty_port Jetty's port. Default is 8888. Note that attribute is named port, but params passed in expect :jetty_port
169
166
  # :startup_wait How many seconds to wait for jetty to spin up. Default is 5. If jetty doesn't finish spinning up, tests can fail because they can't reach jetty.
170
167
  # :solr_home Solr's home directory. Default is jetty_home/solr
171
- # :quiet Keep True(default) to reduce jetty's output
168
+ # :quiet Keep True(default) to reduce jetty's output
172
169
  # :java_opts options to pass to the jvm (ex. ["-Xmx512mb", "-Xms128mb"])
173
170
  # :jetty_opts options to pass to jetty (ex. ["etc/my_jetty.xml", "etc/other.xml"] as in http://wiki.eclipse.org/Jetty/Reference/jetty.xml_usage
174
171
  def configure(params = {})
@@ -184,25 +181,24 @@ class Jettywrapper
184
181
  jetty_server.jetty_opts = params[:jetty_opts] || []
185
182
  return jetty_server
186
183
  end
187
-
188
-
184
+
189
185
  # Wrap the tests. Startup jetty, yield to the test task, capture any errors, shutdown
190
- # jetty, and return the error.
186
+ # jetty, and return the error.
191
187
  # @example Using this method in a rake task
192
188
  # require 'jettywrapper'
193
189
  # desc "Spin up jetty and run tests against it"
194
190
  # task :newtest do
195
- # jetty_params = {
196
- # :jetty_home => "/path/to/jetty",
197
- # :quiet => false,
198
- # :jetty_port => 8983,
191
+ # jetty_params = {
192
+ # :jetty_home => "/path/to/jetty",
193
+ # :quiet => false,
194
+ # :jetty_port => 8983,
199
195
  # :startup_wait => 30,
200
196
  # :jetty_opts => "/etc/jetty.xml"
201
197
  # }
202
- # error = Jettywrapper.wrap(jetty_params) do
203
- # Rake::Task["rake:spec"].invoke
204
- # Rake::Task["rake:cucumber"].invoke
205
- # end
198
+ # error = Jettywrapper.wrap(jetty_params) do
199
+ # Rake::Task["rake:spec"].invoke
200
+ # Rake::Task["rake:cucumber"].invoke
201
+ # end
206
202
  # raise "test failures: #{error}" if error
207
203
  # end
208
204
  def wrap(params)
@@ -224,42 +220,43 @@ class Jettywrapper
224
220
 
225
221
  return error
226
222
  end
227
-
223
+
228
224
  # Convenience method for configuring and starting jetty with one command
229
225
  # @param [Hash] params: The configuration to use for starting jetty
230
- # @example
226
+ # @example
231
227
  # Jettywrapper.start(:jetty_home => '/path/to/jetty', :jetty_port => '8983')
232
228
  def start(params)
233
- Jettywrapper.configure(params)
234
- Jettywrapper.instance.start
235
- return Jettywrapper.instance
229
+ unzip unless File.exists? jetty_dir
230
+ Jettywrapper.configure(params)
231
+ Jettywrapper.instance.start
232
+ return Jettywrapper.instance
236
233
  end
237
-
234
+
238
235
  # Convenience method for configuring and starting jetty with one command. Note
239
- # that for stopping, only the :jetty_home value is required (including other values won't
240
- # hurt anything, though).
236
+ # that for stopping, only the :jetty_home value is required (including other values won't
237
+ # hurt anything, though).
241
238
  # @param [Hash] params: The jetty_home to use for stopping jetty
242
239
  # @return [Jettywrapper.instance]
243
- # @example
240
+ # @example
244
241
  # Jettywrapper.stop_with_params(:jetty_home => '/path/to/jetty')
245
242
  def stop(params)
246
243
  Jettywrapper.configure(params)
247
244
  Jettywrapper.instance.stop
248
245
  return Jettywrapper.instance
249
246
  end
250
-
247
+
251
248
  # Determine whether the jetty at the given jetty_home is running
252
249
  # @param [Hash] params: :jetty_home is required. Which jetty do you want to check the status of?
253
250
  # @return [Boolean]
254
251
  # @example
255
252
  # Jettywrapper.is_jetty_running?(:jetty_home => '/path/to/jetty')
256
- def is_jetty_running?(params)
253
+ def is_jetty_running?(params)
257
254
  Jettywrapper.configure(params)
258
255
  pid = Jettywrapper.instance.pid
259
256
  return false unless pid
260
257
  true
261
258
  end
262
-
259
+
263
260
  # Return the pid of the specified jetty, or return nil if it isn't running
264
261
  # @param [Hash] params: :jetty_home is required.
265
262
  # @return [Fixnum] or [nil]
@@ -271,7 +268,7 @@ class Jettywrapper
271
268
  return nil unless pid
272
269
  pid
273
270
  end
274
-
271
+
275
272
  # Check to see if the port is open so we can raise an error if we have a conflict
276
273
  # @param [Fixnum] port the port to check
277
274
  # @return [Boolean]
@@ -295,8 +292,8 @@ class Jettywrapper
295
292
 
296
293
  return false
297
294
  end
298
-
299
- # Check to see if the pid is actually running. This only works on unix.
295
+
296
+ # Check to see if the pid is actually running. This only works on unix.
300
297
  def is_pid_running?(pid)
301
298
  begin
302
299
  return Process.getpgid(pid) != -1
@@ -304,155 +301,166 @@ class Jettywrapper
304
301
  return false
305
302
  end
306
303
  end
307
-
308
- end #end of class << self
309
-
310
-
311
- # What command is being run to invoke jetty?
312
- def jetty_command
313
- ["java", java_variables, java_opts, "-jar", "start.jar", jetty_opts].flatten
314
- end
315
-
316
- def java_variables
317
- ["-Djetty.port=#{@port}",
318
- "-Dsolr.solr.home=#{Shellwords.escape(@solr_home)}"]
319
- end
320
-
321
- # Start the jetty server. Check the pid file to see if it is running already,
322
- # and stop it if so. After you start jetty, write the PID to a file.
323
- # This is the instance start method. It must be called on Jettywrapper.instance
324
- # You're probably better off using Jettywrapper.start(:jetty_home => "/path/to/jetty")
325
- # @example
326
- # Jettywrapper.configure(params)
327
- # Jettywrapper.instance.start
328
- # return Jettywrapper.instance
329
- def start
330
- logger.debug "Starting jetty with these values: "
331
- logger.debug "jetty_home: #{@jetty_home}"
332
- logger.debug "jetty_command: #{jetty_command.join(' ')}"
333
-
334
- # Check to see if we can start.
335
- # 1. If there is a pid, check to see if it is really running
336
- # 2. Check to see if anything is blocking the port we want to use
337
- if pid
338
- if Jettywrapper.is_pid_running?(pid)
339
- raise("Server is already running with PID #{pid}")
340
- else
341
- logger.warn "Removing stale PID file at #{pid_path}"
342
- File.delete(pid_path)
343
- end
344
- end
345
- if Jettywrapper.is_port_in_use?(self.port)
346
- raise("Port #{self.port} is already in use.")
347
- end
348
- benchmark "Started jetty" do
349
- Dir.chdir(@jetty_home) do
350
- process.start
351
- end
352
- FileUtils.makedirs(pid_dir) unless File.directory?(pid_dir)
353
- begin
354
- f = File.new(pid_path, "w")
355
- rescue Errno::ENOENT, Errno::EACCES
356
- f = File.new(File.join(base_path,'tmp',pid_file),"w")
357
- end
358
- f.puts "#{process.pid}"
359
- f.close
360
- logger.debug "Wrote pid file to #{pid_path} with value #{process.pid}"
361
- startup_wait!
362
- end
363
- end
364
-
365
- # Wait for the jetty server to start and begin listening for requests
366
- def startup_wait!
367
- begin
368
- Timeout::timeout(startup_wait) do
369
- sleep 1 until (Jettywrapper.is_port_in_use? self.port)
370
- end
371
- rescue Timeout::Error
372
- logger.warn "Waited #{startup_wait} seconds for jetty to start, but it is not yet listening on port #{self.port}. Continuing anyway."
373
- end
374
- end
375
-
376
- def process
377
- @process ||= begin
378
- process = ChildProcess.build(*jetty_command)
379
- if self.quiet
380
- process.io.stderr = File.open(File.expand_path("jettywrapper.log"), "w+")
381
- process.io.stdout = process.io.stderr
382
- logger.warn "Logging jettywrapper stdout to #{File.expand_path(process.io.stderr.path)}"
383
- else
384
- process.io.inherit!
385
- end
386
- process.detach = true
387
304
 
388
- process
305
+ def logger=(logger)
306
+ @@logger = logger
307
+ end
308
+
309
+ # If ::Rails.logger is defined and is not nil, it will be returned.
310
+ # If no logger has been defined, a new STDOUT Logger will be created.
311
+ def logger
312
+ @@logger ||= defined?(::Rails) && Rails.logger ? ::Rails.logger : ::Logger.new(STDOUT)
313
+ end
314
+
315
+ end #end of class << self
316
+
317
+ def logger
318
+ self.class.logger
319
+ end
320
+
321
+ # What command is being run to invoke jetty?
322
+ def jetty_command
323
+ ["java", java_variables, java_opts, "-jar", "start.jar", jetty_opts].flatten
324
+ end
325
+
326
+ def java_variables
327
+ ["-Djetty.port=#{@port}",
328
+ "-Dsolr.solr.home=#{Shellwords.escape(@solr_home)}"]
329
+ end
330
+
331
+ # Start the jetty server. Check the pid file to see if it is running already,
332
+ # and stop it if so. After you start jetty, write the PID to a file.
333
+ # This is the instance start method. It must be called on Jettywrapper.instance
334
+ # You're probably better off using Jettywrapper.start(:jetty_home => "/path/to/jetty")
335
+ # @example
336
+ # Jettywrapper.configure(params)
337
+ # Jettywrapper.instance.start
338
+ # return Jettywrapper.instance
339
+ def start
340
+ logger.debug "Starting jetty with these values: "
341
+ logger.debug "jetty_home: #{@jetty_home}"
342
+ logger.debug "jetty_command: #{jetty_command.join(' ')}"
343
+
344
+ # Check to see if we can start.
345
+ # 1. If there is a pid, check to see if it is really running
346
+ # 2. Check to see if anything is blocking the port we want to use
347
+ if pid
348
+ if Jettywrapper.is_pid_running?(pid)
349
+ raise("Server is already running with PID #{pid}")
350
+ else
351
+ logger.warn "Removing stale PID file at #{pid_path}"
352
+ File.delete(pid_path)
353
+ end
354
+ end
355
+ if Jettywrapper.is_port_in_use?(self.port)
356
+ raise("Port #{self.port} is already in use.")
357
+ end
358
+ benchmark "Started jetty" do
359
+ Dir.chdir(@jetty_home) do
360
+ process.start
361
+ end
362
+ FileUtils.makedirs(pid_dir) unless File.directory?(pid_dir)
363
+ begin
364
+ f = File.new(pid_path, "w")
365
+ rescue Errno::ENOENT, Errno::EACCES
366
+ f = File.new(File.join(base_path,'tmp',pid_file),"w")
389
367
  end
390
- end
391
-
392
- def reset_process!
393
- @process = nil
394
- end
395
- # Instance stop method. Must be called on Jettywrapper.instance
396
- # You're probably better off using Jettywrapper.stop(:jetty_home => "/path/to/jetty")
397
- # @example
398
- # Jettywrapper.configure(params)
399
- # Jettywrapper.instance.stop
400
- # return Jettywrapper.instance
401
- def stop
402
- logger.debug "Instance stop method called for pid '#{pid}'"
403
- if pid
404
- if @process
405
- @process.stop
368
+ f.puts "#{process.pid}"
369
+ f.close
370
+ logger.debug "Wrote pid file to #{pid_path} with value #{process.pid}"
371
+ startup_wait!
372
+ end
373
+ end
374
+
375
+ # Wait for the jetty server to start and begin listening for requests
376
+ def startup_wait!
377
+ begin
378
+ Timeout::timeout(startup_wait) do
379
+ sleep 1 until (Jettywrapper.is_port_in_use? self.port)
380
+ end
381
+ rescue Timeout::Error
382
+ logger.warn "Waited #{startup_wait} seconds for jetty to start, but it is not yet listening on port #{self.port}. Continuing anyway."
383
+ end
384
+ end
385
+
386
+ def process
387
+ @process ||= begin
388
+ process = ChildProcess.build(*jetty_command)
389
+ if self.quiet
390
+ process.io.stderr = File.open(File.expand_path("jettywrapper.log"), "w+")
391
+ process.io.stdout = process.io.stderr
392
+ logger.warn "Logging jettywrapper stdout to #{File.expand_path(process.io.stderr.path)}"
406
393
  else
407
- Process.kill("KILL", pid) rescue nil
394
+ process.io.inherit!
408
395
  end
396
+ process.detach = true
409
397
 
410
- begin
411
- File.delete(pid_path)
412
- rescue
413
- end
398
+ process
414
399
  end
415
- end
416
-
417
-
418
- # The fully qualified path to the pid_file
419
- def pid_path
420
- #need to memoize this, becasuse the base path could be relative and the cwd can change in the yield block of wrap
421
- @path ||= File.join(pid_dir, pid_file)
422
- end
423
-
424
- # The file where the process ID will be written
425
- def pid_file
426
- jetty_home_to_pid_file(@jetty_home)
427
- end
428
-
429
- # Take the @jetty_home value and transform it into a legal filename
430
- # @return [String] the name of the pid_file
431
- # @example
432
- # /usr/local/jetty1 => _usr_local_jetty1.pid
433
- def jetty_home_to_pid_file(jetty_home)
400
+ end
401
+
402
+ def reset_process!
403
+ @process = nil
404
+ end
405
+
406
+ # Instance stop method. Must be called on Jettywrapper.instance
407
+ # You're probably better off using Jettywrapper.stop(:jetty_home => "/path/to/jetty")
408
+ # @example
409
+ # Jettywrapper.configure(params)
410
+ # Jettywrapper.instance.stop
411
+ # return Jettywrapper.instance
412
+ def stop
413
+ logger.debug "Instance stop method called for pid '#{pid}'"
414
+ if pid
415
+ if @process
416
+ @process.stop
417
+ else
418
+ Process.kill("KILL", pid) rescue nil
419
+ end
420
+
434
421
  begin
435
- jetty_home.gsub(/\//,'_') << "_#{self.class.env}" << ".pid"
436
- rescue Exception => e
437
- raise "Couldn't make a pid file for jetty_home value #{jetty_home}\n Caused by: #{e}"
422
+ File.delete(pid_path)
423
+ rescue
438
424
  end
439
425
  end
426
+ end
427
+
428
+ # The fully qualified path to the pid_file
429
+ def pid_path
430
+ #need to memoize this, becasuse the base path could be relative and the cwd can change in the yield block of wrap
431
+ @path ||= File.join(pid_dir, pid_file)
432
+ end
433
+
434
+ # The file where the process ID will be written
435
+ def pid_file
436
+ jetty_home_to_pid_file(@jetty_home)
437
+ end
438
+
439
+ # Take the @jetty_home value and transform it into a legal filename
440
+ # @return [String] the name of the pid_file
441
+ # @example
442
+ # /usr/local/jetty1 => _usr_local_jetty1.pid
443
+ def jetty_home_to_pid_file(jetty_home)
444
+ begin
445
+ jetty_home.gsub(/\//,'_') << "_#{self.class.env}" << ".pid"
446
+ rescue Exception => e
447
+ raise "Couldn't make a pid file for jetty_home value #{jetty_home}\n Caused by: #{e}"
448
+ end
449
+ end
440
450
 
441
- # The directory where the pid_file will be written
442
- def pid_dir
443
- File.expand_path(File.join(base_path,'tmp','pids'))
444
- end
445
-
446
- # Check to see if there is a pid file already
447
- # @return true if the file exists, otherwise false
448
- def pid_file?
449
- return true if File.exist?(pid_path)
450
- false
451
- end
452
-
453
- # the process id of the currently running jetty instance
454
- def pid
455
- File.open( pid_path ) { |f| return f.gets.to_i } if File.exist?(pid_path)
456
- end
457
-
451
+ # The directory where the pid_file will be written
452
+ def pid_dir
453
+ File.expand_path(File.join(base_path,'tmp','pids'))
454
+ end
455
+
456
+ # Check to see if there is a pid file already
457
+ # @return true if the file exists, otherwise false
458
+ def pid_file?
459
+ File.exist?(pid_path)
460
+ end
461
+
462
+ # the process id of the currently running jetty instance
463
+ def pid
464
+ File.open( pid_path ) { |f| return f.gets.to_i } if File.exist?(pid_path)
465
+ end
458
466
  end