Class: Jettywrapper
- Inherits:
-
Object
- Object
- Jettywrapper
- Includes:
- ActiveSupport::Benchmarkable, Loggable, Singleton
- Defined in:
- lib/jettywrapper.rb,
lib/jettywrapper/version.rb
Overview
Jettywrapper is a Singleton class, so you can only create one jetty instance at a time.
Constant Summary collapse
- VERSION =
"1.5.0"
Class Attribute Summary collapse
Instance Attribute Summary collapse
-
#base_path ⇒ Object
The root of the application.
-
#java_opts ⇒ Object
Options to pass to java (ex. [“-Xmx512mb”, “-Xms128mb”]).
-
#jetty_home ⇒ Object
Jetty’s home directory.
-
#jetty_opts ⇒ Object
Options to pass to jetty (ex. [“etc/my_jetty.xml”, “etc/other.xml”] as in wiki.eclipse.org/Jetty/Reference/jetty.xml_usage.
-
#port ⇒ Object
Jetty’s port.
-
#quiet ⇒ Object
true (default) to reduce Jetty’s output.
-
#solr_home ⇒ Object
Solr’s home directory.
-
#startup_wait ⇒ Object
How many seconds to wait for jetty to spin up.
Class Method Summary collapse
- .app_root ⇒ Object
- .clean ⇒ Object
-
.configure(params = {}) ⇒ Object
Set the jetty parameters.
- .download(url = nil) ⇒ Object
- .expanded_zip_dir(tmp_save_dir) ⇒ Object
-
.is_jetty_running?(params) ⇒ Boolean
Determine whether the jetty at the given jetty_home is running.
-
.is_pid_running?(pid) ⇒ Boolean
Check to see if the pid is actually running.
-
.is_port_in_use?(port) ⇒ Boolean
Check to see if the port is open so we can raise an error if we have a conflict.
- .jetty_dir ⇒ Object
- .load_config ⇒ Object
-
.pid(params) ⇒ Fixnum
Return the pid of the specified jetty, or return nil if it isn’t running.
- .reset_config ⇒ Object
-
.start(params) ⇒ Object
Convenience method for configuring and starting jetty with one command.
-
.stop(params) ⇒ Jettywrapper.instance
Convenience method for configuring and starting jetty with one command.
- .unzip ⇒ Object
-
.wrap(params) ⇒ Object
Wrap the tests.
- .zip_file ⇒ Object
Instance Method Summary collapse
-
#initialize(params = {}) ⇒ Jettywrapper
constructor
configure the singleton with some defaults.
- #java_variables ⇒ Object
-
#jetty_command ⇒ Object
What command is being run to invoke jetty?.
-
#jetty_home_to_pid_file(jetty_home) ⇒ String
Take the @jetty_home value and transform it into a legal filename.
-
#pid ⇒ Object
the process id of the currently running jetty instance.
-
#pid_dir ⇒ Object
The directory where the pid_file will be written.
-
#pid_file ⇒ Object
The file where the process ID will be written.
-
#pid_file? ⇒ Boolean
Check to see if there is a pid file already.
-
#pid_path ⇒ Object
The fully qualified path to the pid_file.
- #process ⇒ Object
- #reset_process! ⇒ Object
-
#start ⇒ Object
Start the jetty server.
-
#startup_wait! ⇒ Object
Wait for the jetty server to start and begin listening for requests.
-
#stop ⇒ Object
Instance stop method.
Constructor Details
#initialize(params = {}) ⇒ Jettywrapper
configure the singleton with some defaults
33 34 35 |
# File 'lib/jettywrapper.rb', line 33 def initialize(params = {}) self.base_path = self.class.app_root end |
Class Attribute Details
.hydra_jetty_version ⇒ Object
43 44 45 |
# File 'lib/jettywrapper.rb', line 43 def hydra_jetty_version @hydra_jetty_version ||= 'v7.0.0' end |
.tmp_dir ⇒ Object
52 53 54 |
# File 'lib/jettywrapper.rb', line 52 def tmp_dir @tmp_dir ||= 'tmp' end |
.url ⇒ Object
47 48 49 50 |
# File 'lib/jettywrapper.rb', line 47 def url @url ||= defined?(ZIP_URL) ? ZIP_URL : "https://github.com/projecthydra/hydra-jetty/archive/#{hydra_jetty_version}.zip" @url end |
Instance Attribute Details
#base_path ⇒ Object
The root of the application. Used for determining where log files and PID files should go.
28 29 30 |
# File 'lib/jettywrapper.rb', line 28 def base_path @base_path end |
#java_opts ⇒ Object
Options to pass to java (ex. [“-Xmx512mb”, “-Xms128mb”])
29 30 31 |
# File 'lib/jettywrapper.rb', line 29 def java_opts @java_opts end |
#jetty_home ⇒ Object
Jetty’s home directory
23 24 25 |
# File 'lib/jettywrapper.rb', line 23 def jetty_home @jetty_home end |
#jetty_opts ⇒ Object
Options to pass to jetty (ex. [“etc/my_jetty.xml”, “etc/other.xml”] as in wiki.eclipse.org/Jetty/Reference/jetty.xml_usage
30 31 32 |
# File 'lib/jettywrapper.rb', line 30 def jetty_opts @jetty_opts end |
#port ⇒ Object
Jetty’s port. Default is 8888. Note that attribute is named port, but params passed in expect :jetty_port
24 25 26 |
# File 'lib/jettywrapper.rb', line 24 def port @port end |
#quiet ⇒ Object
true (default) to reduce Jetty’s output
26 27 28 |
# File 'lib/jettywrapper.rb', line 26 def quiet @quiet end |
#solr_home ⇒ Object
Solr’s home directory. Default is jetty_home/solr
27 28 29 |
# File 'lib/jettywrapper.rb', line 27 def solr_home @solr_home end |
#startup_wait ⇒ Object
How many seconds to wait for jetty to spin up. Default is 5.
25 26 27 |
# File 'lib/jettywrapper.rb', line 25 def startup_wait @startup_wait end |
Class Method Details
.app_root ⇒ Object
105 106 107 108 109 110 |
# File 'lib/jettywrapper.rb', line 105 def app_root return @app_root if @app_root @app_root = Rails.root if defined?(Rails.root) @app_root ||= APP_ROOT if defined?(APP_ROOT) @app_root ||= '.' end |
.clean ⇒ Object
94 95 96 97 |
# File 'lib/jettywrapper.rb', line 94 def clean system "rm -rf #{jetty_dir}" unzip end |
.configure(params = {}) ⇒ Object
Set the jetty parameters. It accepts a Hash of symbols.
156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/jettywrapper.rb', line 156 def configure(params = {}) jetty_server = self.instance jetty_server.reset_process! jetty_server.quiet = params[:quiet].nil? ? true : params[:quiet] jetty_server.jetty_home = params[:jetty_home] || File.(File.join(app_root, 'jetty')) jetty_server.solr_home = params[:solr_home] || File.join( jetty_server.jetty_home, "solr") jetty_server.port = params[:jetty_port] || 8888 jetty_server.startup_wait = params[:startup_wait] || 5 jetty_server.java_opts = params[:java_opts] || [] jetty_server.jetty_opts = params[:jetty_opts] || [] return jetty_server end |
.download(url = nil) ⇒ Object
64 65 66 67 68 69 70 |
# File 'lib/jettywrapper.rb', line 64 def download(url = nil) self.url = url if url logger.info "Downloading jetty at #{self.url} ..." FileUtils.mkdir tmp_dir unless File.exists? tmp_dir system "curl -L #{self.url} -o #{zip_file}" abort "Unable to download jetty from #{self.url}" unless $?.success? end |
.expanded_zip_dir(tmp_save_dir) ⇒ Object
88 89 90 91 92 |
# File 'lib/jettywrapper.rb', line 88 def (tmp_save_dir) # This old way is more specific, but won't work for blacklight-jetty #expanded_dir = Dir[File.join(tmp_save_dir, "hydra-jetty-*")].first Dir[File.join(tmp_save_dir, "*")].first end |
.is_jetty_running?(params) ⇒ Boolean
Determine whether the jetty at the given jetty_home is running
238 239 240 241 242 243 |
# File 'lib/jettywrapper.rb', line 238 def is_jetty_running?(params) Jettywrapper.configure(params) pid = Jettywrapper.instance.pid return false unless pid true end |
.is_pid_running?(pid) ⇒ Boolean
Check to see if the pid is actually running. This only works on unix.
282 283 284 285 286 287 288 |
# File 'lib/jettywrapper.rb', line 282 def is_pid_running?(pid) begin return Process.getpgid(pid) != -1 rescue Errno::ESRCH return false end end |
.is_port_in_use?(port) ⇒ Boolean
Check to see if the port is open so we can raise an error if we have a conflict
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/jettywrapper.rb', line 262 def is_port_in_use?(port) begin Timeout::timeout(1) do begin s = TCPSocket.new('127.0.0.1', port) s.close return true rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH return false rescue return false end end rescue Timeout::Error end return false end |
.jetty_dir ⇒ Object
60 61 62 |
# File 'lib/jettywrapper.rb', line 60 def jetty_dir 'jetty' end |
.load_config ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/jettywrapper.rb', line 112 def load_config if defined? Rails config_name = Rails.env else config_name = ENV['environment'] end jetty_file = "#{app_root}/config/jetty.yml" unless File.exists?(jetty_file) logger.warn "Didn't find expected jettywrapper config file at #{jetty_file}, using default file instead." jetty_file = File.("../config/jetty.yml", File.dirname(__FILE__)) end begin @jetty_erb = ERB.new(IO.read(jetty_file)).result(binding) rescue Exception => e raise("jetty.yml was found, but could not be parsed with ERB. \n#{$!.inspect}") end begin @jetty_yml = YAML::load(@jetty_erb) rescue StandardError => e raise("jetty.yml was found, but could not be parsed.\n") end if @jetty_yml.nil? || !@jetty_yml.is_a?(Hash) raise("jetty.yml was found, but was blank or malformed.\n") end config = @jetty_yml.with_indifferent_access config[config_name] || config[:default] end |
.pid(params) ⇒ Fixnum
Return the pid of the specified jetty, or return nil if it isn’t running
250 251 252 253 254 255 |
# File 'lib/jettywrapper.rb', line 250 def pid(params) Jettywrapper.configure(params) pid = Jettywrapper.instance.pid return nil unless pid pid end |
.reset_config ⇒ Object
99 100 101 102 103 |
# File 'lib/jettywrapper.rb', line 99 def reset_config @app_root = nil @url = nil @hydra_jetty_version = nil end |
.start(params) ⇒ Object
Convenience method for configuring and starting jetty with one command
214 215 216 217 218 |
# File 'lib/jettywrapper.rb', line 214 def start(params) Jettywrapper.configure(params) Jettywrapper.instance.start return Jettywrapper.instance end |
.stop(params) ⇒ Jettywrapper.instance
Convenience method for configuring and starting jetty with one command. Note that for stopping, only the :jetty_home value is required (including other values won’t hurt anything, though).
227 228 229 230 231 |
# File 'lib/jettywrapper.rb', line 227 def stop(params) Jettywrapper.configure(params) Jettywrapper.instance.stop return Jettywrapper.instance end |
.unzip ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/jettywrapper.rb', line 72 def unzip download unless File.exists? zip_file logger.info "Unpacking jetty..." tmp_save_dir = File.join tmp_dir, 'jetty_generator' system "unzip -d #{tmp_save_dir} -qo #{zip_file}" abort "Unable to unzip #{zip_file} into tmp_save_dir/" unless $?.success? # Remove the old jetty directory if it exists system "rm -r #{jetty_dir}" if File.directory?(jetty_dir) # Move the expanded zip file into the final destination. = (tmp_save_dir) system "mv #{} #{jetty_dir}" abort "Unable to move #{} into #{jetty_dir}/" unless $?.success? end |
.wrap(params) ⇒ Object
Wrap the tests. Startup jetty, yield to the test task, capture any errors, shutdown jetty, and return the error.
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/jettywrapper.rb', line 190 def wrap(params) error = false jetty_server = self.configure(params) begin jetty_server.start yield rescue error = $! logger.error "*** Error starting jetty: #{error}" ensure # puts "stopping jetty server" jetty_server.stop end raise error if error return error end |
.zip_file ⇒ Object
56 57 58 |
# File 'lib/jettywrapper.rb', line 56 def zip_file File.join tmp_dir, url.split('/').last end |
Instance Method Details
#java_variables ⇒ Object
298 299 300 301 |
# File 'lib/jettywrapper.rb', line 298 def java_variables ["-Djetty.port=#{@port}", "-Dsolr.solr.home=#{Shellwords.escape(@solr_home)}"] end |
#jetty_command ⇒ Object
What command is being run to invoke jetty?
294 295 296 |
# File 'lib/jettywrapper.rb', line 294 def jetty_command ["java", java_variables, java_opts, "-jar", "start.jar", jetty_opts].flatten end |
#jetty_home_to_pid_file(jetty_home) ⇒ String
Take the @jetty_home value and transform it into a legal filename
415 416 417 418 419 420 421 422 |
# File 'lib/jettywrapper.rb', line 415 def jetty_home_to_pid_file(jetty_home) begin jetty_home.gsub(/\//,'_') << ".pid" rescue raise "Couldn't make a pid file for jetty_home value #{jetty_home}" raise $! end end |
#pid ⇒ Object
the process id of the currently running jetty instance
437 438 439 |
# File 'lib/jettywrapper.rb', line 437 def pid File.open( pid_path ) { |f| return f.gets.to_i } if File.exist?(pid_path) end |
#pid_dir ⇒ Object
The directory where the pid_file will be written
425 426 427 |
# File 'lib/jettywrapper.rb', line 425 def pid_dir File.(File.join(base_path,'tmp','pids')) end |
#pid_file ⇒ Object
The file where the process ID will be written
407 408 409 |
# File 'lib/jettywrapper.rb', line 407 def pid_file jetty_home_to_pid_file(@jetty_home) end |
#pid_file? ⇒ Boolean
Check to see if there is a pid file already
431 432 433 434 |
# File 'lib/jettywrapper.rb', line 431 def pid_file? return true if File.exist?(pid_path) false end |
#pid_path ⇒ Object
The fully qualified path to the pid_file
401 402 403 404 |
# File 'lib/jettywrapper.rb', line 401 def pid_path #need to memoize this, becasuse the base path could be relative and the cwd can change in the yield block of wrap @path ||= File.join(pid_dir, pid_file) end |
#process ⇒ Object
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
# File 'lib/jettywrapper.rb', line 358 def process @process ||= begin process = ChildProcess.build(*jetty_command) if self.quiet process.io.stderr = File.open(File.("jettywrapper.log"), "w+") process.io.stdout = process.io.stderr logger.warn "Logging jettywrapper stdout to #{File.(process.io.stderr.path)}" else process.io.inherit! end process.detach = true process end end |
#reset_process! ⇒ Object
374 375 376 |
# File 'lib/jettywrapper.rb', line 374 def reset_process! @process = nil end |
#start ⇒ Object
Start the jetty server. Check the pid file to see if it is running already, and stop it if so. After you start jetty, write the PID to a file. This is the instance start method. It must be called on Jettywrapper.instance You’re probably better off using Jettywrapper.start(:jetty_home => “/path/to/jetty”)
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 |
# File 'lib/jettywrapper.rb', line 311 def start logger.debug "Starting jetty with these values: " logger.debug "jetty_home: #{@jetty_home}" logger.debug "jetty_command: #{jetty_command.join(' ')}" # Check to see if we can start. # 1. If there is a pid, check to see if it is really running # 2. Check to see if anything is blocking the port we want to use if pid if Jettywrapper.is_pid_running?(pid) raise("Server is already running with PID #{pid}") else logger.warn "Removing stale PID file at #{pid_path}" File.delete(pid_path) end end if Jettywrapper.is_port_in_use?(self.port) raise("Port #{self.port} is already in use.") end benchmark "Started jetty" do Dir.chdir(@jetty_home) do process.start end FileUtils.makedirs(pid_dir) unless File.directory?(pid_dir) begin f = File.new(pid_path, "w") rescue Errno::ENOENT, Errno::EACCES f = File.new(File.join(base_path,'tmp',pid_file),"w") end f.puts "#{process.pid}" f.close logger.debug "Wrote pid file to #{pid_path} with value #{process.pid}" startup_wait! end end |
#startup_wait! ⇒ Object
Wait for the jetty server to start and begin listening for requests
348 349 350 351 352 353 354 355 356 |
# File 'lib/jettywrapper.rb', line 348 def startup_wait! begin Timeout::timeout(startup_wait) do sleep 1 until (Jettywrapper.is_port_in_use? self.port) end rescue Timeout::Error logger.warn "Waited #{startup_wait} seconds for jetty to start, but it is not yet listening on port #{self.port}. Continuing anyway." end end |
#stop ⇒ Object
Instance stop method. Must be called on Jettywrapper.instance You’re probably better off using Jettywrapper.stop(:jetty_home => “/path/to/jetty”)
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 |
# File 'lib/jettywrapper.rb', line 383 def stop logger.debug "Instance stop method called for pid '#{pid}'" if pid if @process @process.stop else Process.kill("KILL", pid) rescue nil end begin File.delete(pid_path) rescue end end end |