You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ip...@apache.org on 2020/01/23 11:43:24 UTC
[ignite] branch master updated: IGNITE-12569 Can't set serialized
enum to a BinaryObject's field - Fixes #7292.
This is an automated email from the ASF dual-hosted git repository.
ipavlukhin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new e89c71d IGNITE-12569 Can't set serialized enum to a BinaryObject's field - Fixes #7292.
e89c71d is described below
commit e89c71d3cb769ebe25c09e241cfc6cd511b150b3
Author: korlov42 <ko...@gridgain.com>
AuthorDate: Thu Jan 23 14:42:57 2020 +0300
IGNITE-12569 Can't set serialized enum to a BinaryObject's field - Fixes #7292.
Signed-off-by: ipavlukhin <vo...@gmail.com>
---
.../apache/ignite/internal/binary/BinaryUtils.java | 2 +-
.../binary/builder/BinaryBuilderSerializer.java | 35 +++---
.../binary/builder/BinaryObjectBuilderImpl.java | 11 +-
.../BinaryObjectBuilderAdditionalSelfTest.java | 139 ++++++++++++++++++---
.../BinarySimpleNameTestPropertySelfTest.java | 3 +-
5 files changed, 152 insertions(+), 38 deletions(-)
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
index 9568c4b..84e4e97 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
@@ -1715,7 +1715,7 @@ public class BinaryUtils {
private static Object[] doReadBinaryEnumArray(BinaryInputStream in, BinaryContext ctx) {
int len = in.readInt();
- Object[] arr = (Object[])Array.newInstance(BinaryObject.class, len);
+ Object[] arr = (Object[])Array.newInstance(BinaryEnumObjectImpl.class, len);
for (int i = 0; i < len; i++) {
byte flag = in.readByte();
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java
index 9e6411f..439e65c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java
@@ -19,10 +19,9 @@ package org.apache.ignite.internal.binary.builder;
import java.util.Collection;
import java.util.IdentityHashMap;
-import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.ignite.binary.BinaryObject;
-import org.apache.ignite.internal.binary.BinaryMetadata;
+import org.apache.ignite.internal.binary.BinaryEnumObjectImpl;
import org.apache.ignite.internal.binary.BinaryObjectExImpl;
import org.apache.ignite.internal.binary.BinaryUtils;
import org.apache.ignite.internal.binary.BinaryWriterExImpl;
@@ -111,22 +110,24 @@ class BinaryBuilderSerializer {
return;
}
- if (IgniteUtils.isEnum(val.getClass())) {
- String clsName = ((Enum)val).getDeclaringClass().getName();
+ if (val instanceof BinaryEnumObjectImpl) {
+ BinaryEnumObjectImpl obj = (BinaryEnumObjectImpl)val;
- int typeId = writer.context().typeId(clsName);
- String typeName = writer.context().userTypeName(clsName);
+ writer.writeByte(GridBinaryMarshaller.ENUM);
+ writer.writeInt(obj.typeId());
- Object[] enumVals = val.getClass().getEnumConstants();
+ if (obj.typeId() == GridBinaryMarshaller.UNREGISTERED_TYPE_ID)
+ writer.doWriteString(obj.className());
- Map<String, Integer> enumMap = new LinkedHashMap<>(enumVals.length);
+ writer.writeInt(obj.enumOrdinal());
- for (Object enumVal : enumVals)
- enumMap.put(((Enum)enumVal).name(), ((Enum)enumVal).ordinal());
+ return;
+ }
- BinaryMetadata meta = new BinaryMetadata(typeId, typeName, null, null, null, true, enumMap);
+ if (IgniteUtils.isEnum(val.getClass())) {
+ String clsName = ((Enum)val).getDeclaringClass().getName();
- writer.context().updateMetadata(typeId, meta, writer.failIfUnregistered());
+ int typeId = writer.context().typeId(clsName);
// Need register class for marshaller to be able to deserialize enum value.
writer.context().registerClass(((Enum)val).getDeclaringClass(), true, false);
@@ -179,17 +180,21 @@ class BinaryBuilderSerializer {
}
if (val instanceof Object[]) {
- int compTypeId = writer.context().typeId(((Object[])val).getClass().getComponentType().getName());
+ Class<?> compCls = ((Object[])val).getClass().getComponentType();
- if (val instanceof BinaryBuilderEnum[]) {
+ int compTypeId = writer.context().typeId(compCls.getName());
+
+ if (BinaryEnumObjectImpl.class.isAssignableFrom(compCls) || val instanceof BinaryBuilderEnum[]) {
writeArray(writer, GridBinaryMarshaller.ENUM_ARR, (Object[])val, compTypeId);
return;
}
- if (((Object[])val).getClass().getComponentType().isEnum()) {
+ if (compCls.isEnum()) {
Enum[] enumArr = (Enum[])val;
+ writer.context().registerClass(compCls, true, false);
+
writer.writeByte(GridBinaryMarshaller.ENUM_ARR);
writer.writeInt(compTypeId);
writer.writeInt(enumArr.length);
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
index 45a13c0..48c3fce 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
@@ -402,12 +402,13 @@ public class BinaryObjectBuilderImpl implements BinaryObjectBuilder {
// Detect Enum and Enum array type.
else if (newVal instanceof BinaryEnumObjectImpl)
newFldTypeId = GridBinaryMarshaller.ENUM;
- else if (newVal.getClass().isArray() && newVal.getClass().getComponentType() == BinaryObject.class) {
- BinaryObject[] arr = (BinaryObject[])newVal;
- newFldTypeId = arr.length > 0 && arr[0] instanceof BinaryEnumObjectImpl ?
- GridBinaryMarshaller.ENUM_ARR : GridBinaryMarshaller.OBJ_ARR;
- }
+ else if (newVal.getClass().isArray() && BinaryEnumObjectImpl.class.isAssignableFrom(newVal.getClass().getComponentType()))
+ newFldTypeId = GridBinaryMarshaller.ENUM_ARR;
+
+ else if (newVal.getClass().isArray() && BinaryObject.class.isAssignableFrom(newVal.getClass().getComponentType()))
+ newFldTypeId = GridBinaryMarshaller.OBJ_ARR;
+
else
newFldTypeId = BinaryUtils.typeByClass(newVal.getClass());
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java
index b24d9d6..2877a64 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java
@@ -1500,6 +1500,14 @@ public class BinaryObjectBuilderAdditionalSelfTest extends GridCommonAbstractTes
processor.binaryContext().userTypeName(typeName));
}
+ /** */
+ private void clearBinaryMeta() {
+ BinaryContext binCtx = ((CacheObjectBinaryProcessorImpl)((IgniteBinaryImpl)binaries()).processor()).binaryContext();
+
+ binCtx.unregisterBinarySchemas();
+ binCtx.unregisterUserTypeDescriptors();
+ }
+
/**
* Check that correct type is stored in binary object.
*/
@@ -1618,28 +1626,102 @@ public class BinaryObjectBuilderAdditionalSelfTest extends GridCommonAbstractTes
/**
* Checks correct serialization/deserialization of enums in builder.
- *
- * @throws Exception If failed.
*/
@Test
- public void testEnum() throws Exception {
- BinaryObjectBuilder builder = newWrapper("TestType");
+ public void testEnum() {
+ try {
+ BinaryObjectBuilder builder = newWrapper(TestClsWithEnum.class.getName());
+
+ TestEnum[] expArr = {TestEnum.A, TestEnum.B};
+
+ BinaryObject enumObj = builder
+ .setField("testEnumA", TestEnum.A)
+ .setField("testEnumB", TestEnum.B)
+ .setField("testEnumArr", expArr)
+ .build();
+
+ Assert.assertSame(TestEnum.A, ((BinaryObject)enumObj.field("testEnumA")).deserialize());
+ Assert.assertSame(TestEnum.B, ((BinaryObject)enumObj.field("testEnumB")).deserialize());
+ Assert.assertArrayEquals(expArr, deserializeEnumBinaryArray(enumObj.field("testEnumArr")));
+
+ Assert.assertSame(TestEnum.A, ((TestClsWithEnum)enumObj.deserialize()).testEnumA);
+ Assert.assertSame(TestEnum.B, ((TestClsWithEnum)enumObj.deserialize()).testEnumB);
+ Assert.assertArrayEquals(expArr, ((TestClsWithEnum)enumObj.deserialize()).testEnumArr);
+
+ builder = newWrapper(enumObj.type().typeName());
+
+ enumObj = builder
+ .setField("testEnumA", (Object)enumObj.field("testEnumA"))
+ .setField("testEnumB", (Object)enumObj.field("testEnumB"))
+ .setField("testEnumArr", (Object)enumObj.field("testEnumArr"))
+ .build();
+
+ Assert.assertSame(TestEnum.A, ((BinaryObject)enumObj.field("testEnumA")).deserialize());
+ Assert.assertSame(TestEnum.B, ((BinaryObject)enumObj.field("testEnumB")).deserialize());
+ Assert.assertArrayEquals(expArr, deserializeEnumBinaryArray(enumObj.field("testEnumArr")));
+
+ Assert.assertSame(TestEnum.A, ((TestClsWithEnum)enumObj.deserialize()).testEnumA);
+ Assert.assertSame(TestEnum.B, ((TestClsWithEnum)enumObj.deserialize()).testEnumB);
+ Assert.assertArrayEquals(expArr, ((TestClsWithEnum)enumObj.deserialize()).testEnumArr);
+
+ builder = newWrapper(enumObj.type().typeName());
+
+ expArr = new TestEnum[0];
+
+ enumObj = builder.setField("testEnumArr", expArr).build();
+
+ Assert.assertArrayEquals(expArr, deserializeEnumBinaryArray(enumObj.field("testEnumArr")));
+ Assert.assertArrayEquals(expArr, ((TestClsWithEnum)enumObj.deserialize()).testEnumArr);
+
+ enumObj = builder.setField("testEnumArr", (Object)enumObj.field("testEnumArr")).build();
+
+ Assert.assertArrayEquals(expArr, deserializeEnumBinaryArray(enumObj.field("testEnumArr")));
+ Assert.assertArrayEquals(expArr, ((TestClsWithEnum)enumObj.deserialize()).testEnumArr);
+ }
+ finally {
+ clearBinaryMeta();
+ }
+ }
- final TestEnum exp = TestEnum.A;
- final TestEnum[] expArr = {TestEnum.A, TestEnum.B};
+ /** */
+ @Test
+ public void testEnum2() {
+ try {
+ BinaryObjectBuilder builder = newWrapper(TestClsWithEnum.class.getName());
+
+ Object[] expArr = new TestEnum[0];
+
+ BinaryObject enumObj = builder.setField("testEnumArr", expArr).build();
+
+ Assert.assertArrayEquals(expArr, deserializeEnumBinaryArray(enumObj.field("testEnumArr")));
+ Assert.assertArrayEquals(expArr, ((TestClsWithEnum)enumObj.deserialize()).testEnumArr);
+
+ builder = newWrapper(enumObj.type().typeName());
- BinaryObject enumObj = builder.setField("testEnum", exp).setField("testEnumArr", expArr).build();
+ enumObj = builder.setField("testEnumArr", (Object)enumObj.field("testEnumArr")).build();
- assertEquals(exp, ((BinaryObject)enumObj.field("testEnum")).deserialize());
- Assert.assertArrayEquals(expArr, (Object[])deserializeEnumBinaryArray(enumObj.field("testEnumArr")));
+ Assert.assertArrayEquals(expArr, deserializeEnumBinaryArray(enumObj.field("testEnumArr")));
+ Assert.assertArrayEquals(expArr, ((TestClsWithEnum)enumObj.deserialize()).testEnumArr);
- builder = newWrapper(enumObj.type().typeName());
+ expArr = new TestEnum[] {TestEnum.A, TestEnum.B};
- enumObj = builder.setField("testEnum", (Object)enumObj.field("testEnum"))
- .setField("testEnumArr", (Object)enumObj.field("testEnumArr")).build();
+ builder = newWrapper(enumObj.type().typeName());
- assertEquals(exp, ((BinaryObject)enumObj.field("testEnum")).deserialize());
- Assert.assertArrayEquals(expArr, (Object[])deserializeEnumBinaryArray(enumObj.field("testEnumArr")));
+ enumObj = builder.setField("testEnumArr", expArr).build();
+
+ Assert.assertArrayEquals(expArr, deserializeEnumBinaryArray(enumObj.field("testEnumArr")));
+ Assert.assertArrayEquals(expArr, ((TestClsWithEnum)enumObj.deserialize()).testEnumArr);
+
+ builder = newWrapper(enumObj.type().typeName());
+
+ enumObj = builder.setField("testEnumArr", (Object)enumObj.field("testEnumArr")).build();
+
+ Assert.assertArrayEquals(expArr, deserializeEnumBinaryArray(enumObj.field("testEnumArr")));
+ Assert.assertArrayEquals(expArr, ((TestClsWithEnum)enumObj.deserialize()).testEnumArr);
+ }
+ finally {
+ clearBinaryMeta();
+ }
}
/**
@@ -1759,12 +1841,39 @@ public class BinaryObjectBuilderAdditionalSelfTest extends GridCommonAbstractTes
}
}
+ /** Test class with enum and array of enums. */
+ public static class TestClsWithEnum {
+ /** */
+ private final TestEnum testEnumA;
+
+ /** */
+ private final TestEnum testEnumB;
+
+ /** */
+ private final TestEnum[] testEnumArr;
+
+ /** */
+ public TestClsWithEnum(TestEnum testEnumA, TestEnum testEnumB, TestEnum[] testEnumArr) {
+ this.testEnumA = testEnumA;
+ this.testEnumB = testEnumB;
+ this.testEnumArr = testEnumArr;
+ }
+ }
+
/**
*
*/
private enum TestEnum {
/** */
- A,
+ A {
+ /**
+ * An empty function is needed so that {@link TestEnum#A}
+ * becomes a subclass.
+ */
+ public void foo() {
+
+ }
+ },
/** */
B
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinarySimpleNameTestPropertySelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinarySimpleNameTestPropertySelfTest.java
index 7e1709e..22a5d24 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinarySimpleNameTestPropertySelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinarySimpleNameTestPropertySelfTest.java
@@ -65,8 +65,7 @@ public class BinarySimpleNameTestPropertySelfTest extends GridCommonAbstractTest
checkProperty("TestClass");
}
finally {
- if (useSimpleNameBackup != null)
- GridTestProperties.setProperty(BINARY_MARSHALLER_USE_SIMPLE_NAME_MAPPER, "true");
+ GridTestProperties.setProperty(BINARY_MARSHALLER_USE_SIMPLE_NAME_MAPPER, useSimpleNameBackup);
}
}