diff --git a/lib/logstash/runner.rb b/lib/logstash/runner.rb index 340deb32d..9f425a6f8 100644 --- a/lib/logstash/runner.rb +++ b/lib/logstash/runner.rb @@ -16,6 +16,7 @@ class LogStash::Runner def main(args) require "logstash/util" + require "logstash/util/java_version" require "stud/trap" require "stud/task" @startup_interruption_trap = Stud::trap("INT") { puts "Interrupted"; exit 0 } @@ -27,6 +28,9 @@ class LogStash::Runner return 1 end + # Print a warning to STDERR for bad java versions + LogStash::Util::JavaVersion.warn_on_bad_java_version + Stud::untrap("INT", @startup_interruption_trap) task = run(args) diff --git a/lib/logstash/util/java_version.rb b/lib/logstash/util/java_version.rb new file mode 100644 index 000000000..4c6b627b4 --- /dev/null +++ b/lib/logstash/util/java_version.rb @@ -0,0 +1,50 @@ +module LogStash::Util::JavaVersion + # Print a warning if we're on a bad version of java + def self.warn_on_bad_java_version + if self.bad_java_version?(self.version) + STDERR.puts("Please upgrade your java version, the current version '#{self.version}' may cause problems. We recommend a minimum version of 1.7.0_51") + end + end + + # Check to see if this is a recommended java version, print a warning to stdout if this is a bad version + # Returns the current java version + def self.version + return nil if RUBY_ENGINE != "jruby" + + require 'java' + java_import "java.lang.System" + + System.getProperties["java.runtime.version"] + end + + def self.parse_java_version(version_string) + return nil if version_string.nil? + + # Crazy java versioning rules @ http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html + # The regex below parses this all correctly http://rubular.com/r/sInQc3Nc7f + + match = version_string.match(/\A(\d+)\.(\d+)\.(\d+)(_(\d+))?(-(.+))?\Z/) + major, minor, patch, ufull, update, bfull, build = match.captures + + return { + :full => version_string, + :major => major.to_i, + :minor => minor.to_i, + :patch => patch.to_i, + :update => update.to_i, # this is always coerced to an int (a nil will be zero) to make comparisons easier + :build => build # not an integer, could be b06 for instance!, + } + end + + def self.bad_java_version?(version_string) + return nil if version_string.nil? + + parsed = parse_java_version(version_string) + + if parsed[:major] >= 1 && parsed[:minor] == 7 && parsed[:patch] == 0 && parsed[:update] < 51 + return true + elsif parsed[:major] >= 1 && parsed[:minor] < 7 + return true + end + end +end \ No newline at end of file diff --git a/spec/util/java_version_spec.rb b/spec/util/java_version_spec.rb new file mode 100644 index 000000000..c6924a652 --- /dev/null +++ b/spec/util/java_version_spec.rb @@ -0,0 +1,64 @@ +require 'spec_helper' +require 'logstash/util/java_version' + +describe "LogStash::Util::JavaVersion" do + let(:mod) { LogStash::Util::JavaVersion } + it "should get the current java version if we're on Java" do + if RUBY_ENGINE == "jruby" + expect(LogStash::Util::JavaVersion.version).to be_a(String) + end + end + + it "should mark a bad java version as bad" do + expect(mod.bad_java_version?("1.7.0_45-beta")).to be_truthy + expect(mod.bad_java_version?("1.6.0")).to be_truthy + end + + it "should mark a good java version as good" do + expect(mod.bad_java_version?("1.7.0_51")).to be_falsey + expect(mod.bad_java_version?("1.8.0-beta")).to be_falsey + end + + describe "parsing java versions" do + it "should return nil on a nil version" do + expect(mod.parse_java_version(nil)).to be_nil + end + + it "should parse a plain version" do + parsed = mod.parse_java_version("1.3.0") + expect(parsed[:major]).to eql(1) + expect(parsed[:minor]).to eql(3) + expect(parsed[:patch]).to eql(0) + expect(parsed[:update]).to eql(0) + expect(parsed[:build]).to be_nil + end + + it "should parse an update" do + parsed = mod.parse_java_version("1.4.0_03") + expect(parsed[:major]).to eql(1) + expect(parsed[:minor]).to eql(4) + expect(parsed[:patch]).to eql(0) + expect(parsed[:update]).to eql(3) + expect(parsed[:build]).to be_nil + end + + it "should parse a version with just a build" do + parsed = mod.parse_java_version("1.4.0-beta") + expect(parsed[:major]).to eql(1) + expect(parsed[:minor]).to eql(4) + expect(parsed[:patch]).to eql(0) + expect(parsed[:update]).to eql(0) + expect(parsed[:build]).to eql("beta") + end + + it "should parse a version with an update and a build" do + parsed = mod.parse_java_version("1.4.0_03-beta") + expect(parsed[:major]).to eql(1) + expect(parsed[:minor]).to eql(4) + expect(parsed[:patch]).to eql(0) + expect(parsed[:update]).to eql(3) + expect(parsed[:build]).to eql("beta") + end + end + +end \ No newline at end of file