#7712 integer and long bivalues removed

Fixes #8107
This commit is contained in:
Armin 2017-08-30 17:49:56 +02:00 committed by Armin Braun
parent 78689716b7
commit d5530a42c4
10 changed files with 55 additions and 188 deletions

View file

@ -1,7 +1,7 @@
package org.logstash;
import org.jruby.RubyBoolean;
import org.jruby.RubyFixnum;
import org.jruby.RubyFloat;
import org.jruby.RubyString;
import org.logstash.bivalues.BiValue;
@ -22,8 +22,9 @@ public class Javafier {
if (o instanceof RubyString) {
return o.toString();
}
if (o instanceof String || o instanceof Float || o instanceof Double ||
o instanceof Boolean || o instanceof Timestamp) {
if (o instanceof String || o instanceof Float || o instanceof Double ||
o instanceof Long || o instanceof Integer || o instanceof Boolean ||
o instanceof Timestamp) {
return o;
}
if (o instanceof RubyFloat) {
@ -35,6 +36,9 @@ public class Javafier {
if (o instanceof RubyBoolean) {
return ((RubyBoolean) o).isTrue();
}
if (o instanceof RubyFixnum) {
return ((RubyFixnum) o).getLongValue();
}
if (o instanceof BiValue) {
return ((BiValue)o).javaValue();
} else if(o instanceof ConvertedMap) {

View file

@ -11,6 +11,7 @@ import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
import java.io.IOException;
import java.util.HashMap;
import org.jruby.RubyBoolean;
import org.jruby.RubyFixnum;
import org.jruby.RubyFloat;
import org.jruby.RubyString;
@ -20,7 +21,8 @@ public final class ObjectMappers {
new SimpleModule("RubySerializers")
.addSerializer(RubyString.class, new RubyStringSerializer())
.addSerializer(RubyFloat.class, new RubyFloatSerializer())
.addSerializer(RubyBoolean.class, new RubyBooleanSerializer());
.addSerializer(RubyBoolean.class, new RubyBooleanSerializer())
.addSerializer(RubyFixnum.class, new RubyFixnumSerializer());
public static final ObjectMapper JSON_MAPPER =
new ObjectMapper().registerModule(RUBY_SERIALIZERS);
@ -92,4 +94,22 @@ public final class ObjectMappers {
generator.writeBoolean(value.isTrue());
}
}
/**
* Serializer for {@link RubyFixnum} since Jackson can't handle that type natively, so we
* simply serialize it as if it were a {@code long}.
*/
private static final class RubyFixnumSerializer
extends NonTypedScalarSerializerBase<RubyFixnum> {
RubyFixnumSerializer() {
super(RubyFixnum.class, true);
}
@Override
public void serialize(final RubyFixnum value, final JsonGenerator generator,
final SerializerProvider provider) throws IOException {
generator.writeNumber(value.getLongValue());
}
}
}

View file

@ -6,6 +6,7 @@ import java.util.Map;
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyBoolean;
import org.jruby.RubyFixnum;
import org.jruby.RubyFloat;
import org.jruby.RubyHash;
import org.jruby.RubyString;
@ -30,18 +31,21 @@ public final class Rubyfier {
public static IRubyObject deep(Ruby runtime, final Object input) {
if (input instanceof RubyString || input instanceof RubyFloat
|| input instanceof RubyBoolean
|| input instanceof RubyBoolean || input instanceof RubyFixnum
|| input instanceof JrubyTimestampExtLibrary.RubyTimestamp) {
return (IRubyObject) input;
}
if (input instanceof String) return RubyUtil.RUBY.newString((String) input);
if (input instanceof String) return runtime.newString((String) input);
if (input instanceof Double || input instanceof Float) {
return RubyUtil.RUBY.newFloat(((Number) input).doubleValue());
return runtime.newFloat(((Number) input).doubleValue());
}
if (input instanceof Boolean) return RubyUtil.RUBY.newBoolean((Boolean) input);
if (input instanceof Integer || input instanceof Long) {
return runtime.newFixnum(((Number) input).longValue());
}
if (input instanceof Boolean) return runtime.newBoolean((Boolean) input);
if (input instanceof Timestamp) {
return JrubyTimestampExtLibrary.RubyTimestamp.newRubyTimestamp(
RubyUtil.RUBY, (Timestamp) input
runtime, (Timestamp) input
);
}
if (input instanceof BiValue) return ((BiValue) input).rubyValue(runtime);

View file

@ -7,6 +7,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.joda.time.DateTime;
import org.jruby.RubyArray;
import org.jruby.RubyBoolean;
import org.jruby.RubyFixnum;
import org.jruby.RubyFloat;
import org.jruby.RubyHash;
import org.jruby.RubyString;
@ -28,6 +29,9 @@ public final class Valuefier {
private static final Valuefier.Converter FLOAT_CONVERTER =
input -> RubyUtil.RUBY.newFloat(((Number) input).doubleValue());
private static final Valuefier.Converter LONG_CONVERTER
= input -> RubyUtil.RUBY.newFixnum(((Number) input).longValue());
private static final Valuefier.Converter JAVAPROXY_CONVERTER =
input -> {
final Object obj = JavaUtil.unwrapJavaObject((JavaProxy) input);
@ -95,6 +99,7 @@ public final class Valuefier {
final Map<Class<?>, Valuefier.Converter> converters =
new ConcurrentHashMap<>(50, 0.2F, 1);
converters.put(RubyString.class, IDENTITY);
converters.put(RubyFixnum.class, IDENTITY);
converters.put(JrubyTimestampExtLibrary.RubyTimestamp.class, IDENTITY);
converters.put(RubyFloat.class, IDENTITY);
converters.put(ConvertedMap.class, IDENTITY);
@ -104,6 +109,8 @@ public final class Valuefier {
converters.put(String.class, input -> RubyUtil.RUBY.newString((String) input));
converters.put(Float.class, FLOAT_CONVERTER);
converters.put(Double.class, FLOAT_CONVERTER);
converters.put(Long.class, LONG_CONVERTER);
converters.put(Integer.class, LONG_CONVERTER);
converters.put(Boolean.class, input -> RubyUtil.RUBY.newBoolean((Boolean) input));
converters.put(
Timestamp.class,

View file

@ -5,8 +5,6 @@ import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import org.jruby.RubyBignum;
import org.jruby.RubyFixnum;
import org.jruby.RubyInteger;
import org.jruby.RubyNil;
import org.jruby.RubySymbol;
import org.jruby.ext.bigdecimal.RubyBigDecimal;
@ -44,13 +42,9 @@ public final class BiValues {
private static Map<Class<?>, BiValues.BiValueType> initCache() {
final Map<Class<?>, BiValues.BiValueType> hm = new HashMap<>(50, 0.2F);
hm.put(Integer.class, value -> new IntegerBiValue((Integer) value));
hm.put(Long.class, value -> new LongBiValue((Long) value));
hm.put(BigDecimal.class, value -> new BigDecimalBiValue((BigDecimal) value));
hm.put(BigInteger.class, value -> new BigIntegerBiValue((BigInteger) value));
hm.put(RubyBignum.class, value -> new BigIntegerBiValue((RubyBignum) value));
hm.put(RubyFixnum.class, value -> new LongBiValue((RubyInteger) value));
hm.put(RubyInteger.class, value -> new IntegerBiValue((RubyInteger) value));
hm.put(RubyNil.class, value -> NULL_BI_VALUE);
hm.put(RubySymbol.class, value -> new SymbolBiValue((RubySymbol) value));
hm.put(RubyBigDecimal.class, value -> new BigDecimalBiValue((RubyBigDecimal) value));

View file

@ -1,40 +0,0 @@
package org.logstash.bivalues;
import org.jruby.Ruby;
import org.jruby.RubyInteger;
import org.jruby.javasupport.JavaUtil;
import java.io.ObjectStreamException;
public class IntegerBiValue extends BiValue<RubyInteger, Integer> {
public IntegerBiValue(RubyInteger rubyValue) {
this.rubyValue = rubyValue;
javaValue = null;
}
public IntegerBiValue(int javaValue) {
this.javaValue = javaValue;
rubyValue = null;
}
private IntegerBiValue() {
}
protected void addRuby(Ruby runtime) {
rubyValue = (RubyInteger) JavaUtil.convertJavaToUsableRubyObject(runtime, javaValue);
}
protected void addJava() {
long value = rubyValue.getLongValue();
if ((int) value != value) {
throw new ArithmeticException("Integer overflow - Incorrect IntegerBiValue usage: BiValues should pick LongBiValue for RubyInteger");
}
javaValue = (int) value;
}
// Called when object is to be serialized on a stream to allow the object to substitute a proxy for itself.
private Object writeReplace() throws ObjectStreamException {
return newProxy(this);
}
}

View file

@ -1,36 +0,0 @@
package org.logstash.bivalues;
import org.jruby.Ruby;
import org.jruby.RubyInteger;
import org.jruby.javasupport.JavaUtil;
import java.io.ObjectStreamException;
public class LongBiValue extends BiValue<RubyInteger, Long> {
public LongBiValue(RubyInteger rubyValue) {
this.rubyValue = rubyValue;
javaValue = null;
}
public LongBiValue(long javaValue) {
this.javaValue = javaValue;
rubyValue = null;
}
private LongBiValue() {
}
protected void addRuby(Ruby runtime) {
rubyValue = (RubyInteger) JavaUtil.convertJavaToUsableRubyObject(runtime, javaValue);
}
protected void addJava() {
javaValue = rubyValue.getLongValue();
}
// Called when object is to be serialized on a stream to allow the object to substitute a proxy for itself.
private Object writeReplace() throws ObjectStreamException {
return newProxy(this);
}
}

View file

@ -28,7 +28,7 @@ public final class EventTest {
byte[] binary = e.serialize();
Event er = Event.deserialize(binary);
assertEquals(42L, er.getField("foo"));
assertEquals(42, er.getField("bar"));
assertEquals(42L, er.getField("bar"));
assertEquals(42L, er.getField("[baz][innerFoo]"));
assertEquals(42.42, er.getField("[baz][innerQuux]"));
assertEquals(42L, er.getField("[@metadata][foo]"));
@ -48,7 +48,7 @@ public final class EventTest {
e.setField("[@metadata][foo]", 42L);
Event er = Event.deserialize(e.serialize());
assertEquals(42L, er.getField("foo"));
assertEquals(42, er.getField("bar"));
assertEquals(42L, er.getField("bar"));
assertEquals(42L, er.getField("[baz][innerFoo]"));
assertEquals(42.42, er.getField("[baz][innerQuux]"));
assertEquals(42L, er.getField("[@metadata][foo]"));
@ -78,6 +78,14 @@ public final class EventTest {
assertJsonEquals("{\"@timestamp\":\"" + e.getTimestamp().toIso8601() + "\",\"foo\":1,\"@version\":\"1\"}", e.toJson());
}
@Test
public void testSimpleLongFieldToJson() throws Exception {
Map<String, Object> data = new HashMap<>();
data.put("foo", 1L);
Event e = new Event(data);
assertJsonEquals("{\"@timestamp\":\"" + e.getTimestamp().toIso8601() + "\",\"foo\":1,\"@version\":\"1\"}", e.toJson());
}
@Test
public void testSimpleDecimalFieldToJson() throws Exception {
Map<String, Object> data = new HashMap<>();
@ -139,7 +147,7 @@ public final class EventTest {
data.put("foo", l);
l.add(1);
Event e = new Event(data);
assertEquals(1, e.getField("[foo][0]"));
assertEquals(1L, e.getField("[foo][0]"));
}
@Test

View file

@ -7,8 +7,6 @@ import java.io.ObjectOutputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.jruby.RubyBignum;
import org.jruby.RubyFixnum;
import org.jruby.RubyInteger;
import org.jruby.RubySymbol;
import org.jruby.ext.bigdecimal.RubyBigDecimal;
import org.junit.Test;
@ -29,43 +27,6 @@ public class BiValueTest extends TestBase {
assertEquals(s, subject.javaValue());
}
@Test
public void testLongBiValueFromRuby() {
Long s = 123456789L;
LongBiValue subject = new LongBiValue(RubyFixnum.newFixnum(ruby, s));
assertTrue(subject.hasRubyValue());
assertFalse(subject.hasJavaValue());
assertEquals(s, subject.javaValue());
}
@Test
public void testLongBiValueFromJava() {
RubyInteger v = RubyFixnum.newFixnum(ruby, 123456789L);
LongBiValue subject = new LongBiValue(123456789L);
assertFalse(subject.hasRubyValue());
assertTrue(subject.hasJavaValue());
assertEquals(v, subject.rubyValue(ruby));
}
@Test
public void testIntegerBiValueFromRuby() {
int j = 123456789;
IntegerBiValue subject = new IntegerBiValue(RubyFixnum.newFixnum(ruby, j));
assertTrue(subject.hasRubyValue());
assertFalse(subject.hasJavaValue());
assertTrue(j - subject.javaValue() == 0);
}
@Test
public void testIntegerBiValueFromJava() {
RubyInteger v = RubyFixnum.newFixnum(ruby, 123456789);
IntegerBiValue subject = new IntegerBiValue(123456789);
assertFalse(subject.hasRubyValue());
assertTrue(subject.hasJavaValue());
assertEquals(v, subject.rubyValue(ruby));
}
@Test
public void testBigDecimalBiValueFromRuby() {
BigDecimal s = BigDecimal.valueOf(12345.678D);

View file

@ -3,12 +3,9 @@ package org.logstash.bivalues;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.jruby.RubyBignum;
import org.jruby.RubyFixnum;
import org.jruby.RubyInteger;
import org.jruby.RubyNil;
import org.jruby.RubySymbol;
import org.jruby.ext.bigdecimal.RubyBigDecimal;
import org.jruby.javasupport.JavaUtil;
import org.junit.Test;
import org.logstash.TestBase;
@ -29,30 +26,6 @@ public class BiValuesTest extends TestBase {
assertEquals(String.class, subject.javaValue().getClass());
}
@Test
public void testBiValuesLongRuby() {
long jo = 1234567L;
RubyInteger ro = (RubyInteger) JavaUtil.convertJavaToUsableRubyObject(ruby, jo);
BiValue subject = BiValues.newBiValue(ro);
assertEquals(ro, subject.rubyValueUnconverted());
assertEquals(ro.getClass(), subject.rubyValue(ruby).getClass());
assertEquals(jo, subject.javaValue());
assertEquals(Long.class, subject.javaValue().getClass());
}
@Test
public void testBiValuesLongJava() {
long jo = 1234567L;
RubyInteger ro = (RubyInteger) JavaUtil.convertJavaToUsableRubyObject(ruby, jo);
BiValue subject = BiValues.newBiValue(jo);
assertEquals(jo, subject.javaValue());
assertEquals(Long.class, subject.javaValue().getClass());
assertEquals(ro, subject.rubyValue(ruby));
assertEquals(ro.getClass(), subject.rubyValue(ruby).getClass());
}
@Test
public void testBiValuesBigDecimalRuby() {
BigDecimal jo = BigDecimal.valueOf(12345.678D);
@ -121,32 +94,4 @@ public class BiValuesTest extends TestBase {
assertEquals(ro, subject.rubyValue(ruby));
assertEquals(ro.getClass(), subject.rubyValue(ruby).getClass());
}
// NOTE: testBiValuesIntegerRuby will map to LongBiValue
@Test
public void testBiValuesIntegerRuby() {
int jo = 12345678;
RubyInteger ro = RubyFixnum.newFixnum(ruby, jo);
BiValue subject = BiValues.newBiValue(ro);
assertEquals(LongBiValue.class, subject.getClass());
assertEquals(ro, subject.rubyValueUnconverted());
assertEquals(ro.getClass(), subject.rubyValue(ruby).getClass());
assertEquals(12345678L, subject.javaValue());
assertEquals(Long.class, subject.javaValue().getClass());
}
@Test
public void testBiValuesIntegerJava() {
int jo = 12345678;
RubyInteger ro = RubyFixnum.newFixnum(ruby, jo);
BiValue subject = BiValues.newBiValue(jo);
assertEquals(IntegerBiValue.class, subject.getClass());
assertEquals(jo, subject.javaValue());
assertEquals(Integer.class, subject.javaValue().getClass());
assertEquals(ro, subject.rubyValue(ruby));
assertEquals(ro.getClass(), subject.rubyValue(ruby).getClass());
}
}