diff --git a/lib/logstash/java_integration.rb b/lib/logstash/java_integration.rb index 8daddba41..ef9c22a29 100644 --- a/lib/logstash/java_integration.rb +++ b/lib/logstash/java_integration.rb @@ -24,6 +24,24 @@ class Hash end end + +# this is a temporary fix to solve a bug in JRuby where classes implementing the Map interface, like LinkedHashMap +# have a bug in the has_key? method that is implemented in the Enumerable module that is somehow mixed in the Map interface. +# this bug makes has_key? (and all its aliases) return false for a key that has a nil value. +# Only LinkedHashMap is patched here because patching the Map interface is not working. +# TODO find proper fix, and submit upstream +# releavant JRuby files: +# https://github.com/jruby/jruby/blob/master/core/src/main/ruby/jruby/java/java_ext/java.util.rb +# https://github.com/jruby/jruby/blob/master/core/src/main/java/org/jruby/java/proxies/MapJavaProxy.java +class Java::JavaUtil::LinkedHashMap + def has_key?(key) + self.containsKey(key) + end + alias_method :include?, :has_key? + alias_method :member?, :has_key? + alias_method :key?, :has_key? +end + module java::util::Map # have Map objects like LinkedHashMap objects report is_a?(Array) == true def is_a?(clazz) diff --git a/spec/lib/logstash/java_integration_spec.rb b/spec/lib/logstash/java_integration_spec.rb index 3b5b0b32a..19c4f0d75 100644 --- a/spec/lib/logstash/java_integration_spec.rb +++ b/spec/lib/logstash/java_integration_spec.rb @@ -166,4 +166,63 @@ describe "Java integration" do end end end + + context "Enumerable implementation" do + context "Java Map interface should report key with nil value as included" do + + it "should support include? method" do + expect(Java::JavaUtil::LinkedHashMap.new({"foo" => nil}).include?("foo")).to be_true + end + + it "should support has_key? method" do + expect(Java::JavaUtil::LinkedHashMap.new({"foo" => nil}).has_key?("foo")).to be_true + end + + it "should support member? method" do + expect(Java::JavaUtil::LinkedHashMap.new({"foo" => nil}).member?("foo")).to be_true + end + + it "should support key? method" do + expect(Java::JavaUtil::LinkedHashMap.new({"foo" => nil}).key?("foo")).to be_true + end + end + + context "Java Map interface should report key with a value as included" do + + it "should support include? method" do + expect(Java::JavaUtil::LinkedHashMap.new({"foo" => 1}).include?("foo")).to be_true + end + + it "should support has_key? method" do + expect(Java::JavaUtil::LinkedHashMap.new({"foo" => 1}).has_key?("foo")).to be_true + end + + it "should support member? method" do + expect(Java::JavaUtil::LinkedHashMap.new({"foo" => 1}).member?("foo")).to be_true + end + + it "should support key? method" do + expect(Java::JavaUtil::LinkedHashMap.new({"foo" => 1}).key?("foo")).to be_true + end + end + + context "Java Map interface should report non existing key as not included" do + + it "should support include? method" do + expect(Java::JavaUtil::LinkedHashMap.new({"foo" => 1}).include?("bar")).to be_false + end + + it "should support has_key? method" do + expect(Java::JavaUtil::LinkedHashMap.new({"foo" => 1}).has_key?("bar")).to be_false + end + + it "should support member? method" do + expect(Java::JavaUtil::LinkedHashMap.new({"foo" => 1}).member?("bar")).to be_false + end + + it "should support key? method" do + expect(Java::JavaUtil::LinkedHashMap.new({"foo" => 1}).key?("bar")).to be_false + end + end + end end