Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id A4C9D200BFB for ; Tue, 6 Dec 2016 09:40:03 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id A3912160B29; Tue, 6 Dec 2016 08:40:03 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id CCC5B160B3E for ; Tue, 6 Dec 2016 09:40:00 +0100 (CET) Received: (qmail 50617 invoked by uid 500); 6 Dec 2016 08:40:00 -0000 Mailing-List: contact commits-help@ignite.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ignite.apache.org Delivered-To: mailing list commits@ignite.apache.org Received: (qmail 49803 invoked by uid 99); 6 Dec 2016 08:39:59 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 06 Dec 2016 08:39:59 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 5F707F16B3; Tue, 6 Dec 2016 08:39:59 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sboikov@apache.org To: commits@ignite.apache.org Date: Tue, 06 Dec 2016 08:40:21 -0000 Message-Id: <97cde401c5b64dc18e415ad2a53872c0@git.apache.org> In-Reply-To: <2926d977d02c462bb9538c249d38c406@git.apache.org> References: <2926d977d02c462bb9538c249d38c406@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [24/50] ignite git commit: IGNITE-4026: Fixed BinaryObjectBuilder.build() can fail if one of the fields is Externalizable, enum from binary object. This closes #1281. This closes #1289. archived-at: Tue, 06 Dec 2016 08:40:03 -0000 IGNITE-4026: Fixed BinaryObjectBuilder.build() can fail if one of the fields is Externalizable, enum from binary object. This closes #1281. This closes #1289. Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/0b7c62d2 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/0b7c62d2 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/0b7c62d2 Branch: refs/heads/ignite-comm-balance-master Commit: 0b7c62d2939854223653d832a616ddb61211bf22 Parents: d1cc292 Author: dkarachentsev Authored: Mon Nov 28 11:30:14 2016 +0300 Committer: devozerov Committed: Mon Nov 28 11:30:14 2016 +0300 ---------------------------------------------------------------------- .../internal/binary/GridBinaryMarshaller.java | 2 +- .../binary/builder/BinaryBuilderReader.java | 11 ++ .../binary/builder/BinaryBuilderSerializer.java | 4 + .../binary/builder/BinaryObjectBuilderImpl.java | 10 ++ .../BinaryObjectBuilderAdditionalSelfTest.java | 157 ++++++++++++++++++- 5 files changed, 181 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/0b7c62d2/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java index ad63521..624fa33 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java @@ -43,7 +43,7 @@ public class GridBinaryMarshaller { private static final ThreadLocal BINARY_CTX = new ThreadLocal<>(); /** */ - static final byte OPTM_MARSH = -2; + public static final byte OPTM_MARSH = -2; /** */ public static final byte BYTE = 1; http://git-wip-us.apache.org/repos/asf/ignite/blob/0b7c62d2/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderReader.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderReader.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderReader.java index 347fb2b..baaabd6 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderReader.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderReader.java @@ -33,6 +33,7 @@ import java.sql.Timestamp; import java.util.Date; import java.util.HashMap; import java.util.Map; +import org.apache.ignite.internal.util.typedef.internal.U; import static java.nio.charset.StandardCharsets.UTF_8; @@ -757,6 +758,16 @@ public class BinaryBuilderReader implements BinaryPositionReadable { return new BinaryPlainBinaryObject(binaryObj); } + case GridBinaryMarshaller.OPTM_MARSH: { + final BinaryHeapInputStream bin = BinaryHeapInputStream.create(arr, pos); + + final Object obj = BinaryUtils.doReadOptimized(bin, ctx, U.resolveClassLoader(ctx.configuration())); + + pos = bin.position(); + + return obj; + } + default: throw new BinaryObjectException("Invalid flag value: " + type); } http://git-wip-us.apache.org/repos/asf/ignite/blob/0b7c62d2/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java ---------------------------------------------------------------------- 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 b296437..6974176 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 @@ -116,8 +116,12 @@ class BinaryBuilderSerializer { String typeName = writer.context().userTypeName(clsName); BinaryMetadata meta = new BinaryMetadata(typeId, typeName, null, null, null, true); + writer.context().updateMetadata(typeId, meta); + // Need register class for marshaller to be able to deserialize enum value. + writer.context().descriptorForClass(val.getClass(), false); + writer.writeByte(GridBinaryMarshaller.ENUM); writer.writeInt(typeId); writer.writeInt(((Enum)val).ordinal()); http://git-wip-us.apache.org/repos/asf/ignite/blob/0b7c62d2/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java ---------------------------------------------------------------------- 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 ddd2423..a847d04 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 @@ -22,6 +22,7 @@ import org.apache.ignite.binary.BinaryObject; import org.apache.ignite.binary.BinaryObjectBuilder; import org.apache.ignite.binary.BinaryObjectException; import org.apache.ignite.binary.BinaryType; +import org.apache.ignite.internal.binary.BinaryEnumObjectImpl; import org.apache.ignite.internal.binary.BinaryMetadata; import org.apache.ignite.internal.binary.BinaryObjectImpl; import org.apache.ignite.internal.binary.BinaryWriterExImpl; @@ -391,6 +392,15 @@ public class BinaryObjectBuilderImpl implements BinaryObjectBuilder { if (((BinaryValueWithType)newVal).value() == null) nullFieldVal = true; } + // 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 newFldTypeId = BinaryUtils.typeByClass(newVal.getClass()); http://git-wip-us.apache.org/repos/asf/ignite/blob/0b7c62d2/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java ---------------------------------------------------------------------- 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 24806cb..507aa6b 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 @@ -21,6 +21,10 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; import java.lang.reflect.Field; import java.math.BigDecimal; import java.math.BigInteger; @@ -1423,11 +1427,19 @@ public class BinaryObjectBuilderAdditionalSelfTest extends GridCommonAbstractTes * @return Wrapper. */ private BinaryObjectBuilderImpl newWrapper(Class aCls) { + return newWrapper(aCls.getName()); + } + + /** + * @param typeName Type name. + * @return Wrapper. + */ + private BinaryObjectBuilderImpl newWrapper(String typeName) { CacheObjectBinaryProcessorImpl processor = (CacheObjectBinaryProcessorImpl)( (IgniteBinaryImpl)binaries()).processor(); - return new BinaryObjectBuilderImpl(processor.binaryContext(), processor.typeId(aCls.getName()), - processor.binaryContext().userTypeName(aCls.getName())); + return new BinaryObjectBuilderImpl(processor.binaryContext(), processor.typeId(typeName), + processor.binaryContext().userTypeName(typeName)); } /** @@ -1508,4 +1520,145 @@ public class BinaryObjectBuilderAdditionalSelfTest extends GridCommonAbstractTes assert OBJ.equals(binaryObj.type().fieldTypeName("asSetHint")); assert OBJ.equals(binaryObj.type().fieldTypeName("asMapHint")); } + + /** + * Checks that externalizable value is correctly serialized/deserialized. + * + * @throws Exception If failed. + */ + public void testBuilderExternalizable() throws Exception { + BinaryObjectBuilder builder = newWrapper("TestType"); + + final TestObjectExternalizable exp = new TestObjectExternalizable("test"); + final TestObjectExternalizable[] expArr = new TestObjectExternalizable[]{ + new TestObjectExternalizable("test1"), new TestObjectExternalizable("test2")}; + + BinaryObject extObj = builder.setField("extVal", exp).setField("extArr", expArr).build(); + + assertEquals(exp, extObj.field("extVal")); + Assert.assertArrayEquals(expArr, (Object[])extObj.field("extArr")); + + builder = extObj.toBuilder(); + + extObj = builder.setField("intVal", 10).build(); + + assertEquals(exp, extObj.field("extVal")); + Assert.assertArrayEquals(expArr, (Object[])extObj.field("extArr")); + assertEquals(Integer.valueOf(10), extObj.field("intVal")); + + builder = extObj.toBuilder(); + + extObj = builder.setField("strVal", "some string").build(); + + assertEquals(exp, extObj.field("extVal")); + Assert.assertArrayEquals(expArr, (Object[])extObj.field("extArr")); + assertEquals(Integer.valueOf(10), extObj.field("intVal")); + assertEquals("some string", extObj.field("strVal")); + } + + /** + * Checks correct serialization/deserialization of enums in builder. + * + * @throws Exception If failed. + */ + public void testEnum() throws Exception { + BinaryObjectBuilder builder = newWrapper("TestType"); + + final TestEnum exp = TestEnum.A; + final TestEnum[] expArr = {TestEnum.A, TestEnum.B}; + + BinaryObject enumObj = builder.setField("testEnum", exp).setField("testEnumArr", expArr).build(); + + assertEquals(exp, ((BinaryObject)enumObj.field("testEnum")).deserialize()); + Assert.assertArrayEquals(expArr, (Object[])deserializeEnumBinaryArray(enumObj.field("testEnumArr"))); + + builder = newWrapper(enumObj.type().typeName()); + + enumObj = builder.setField("testEnum", (Object)enumObj.field("testEnum")) + .setField("testEnumArr", (Object)enumObj.field("testEnumArr")).build(); + + assertEquals(exp, ((BinaryObject)enumObj.field("testEnum")).deserialize()); + Assert.assertArrayEquals(expArr, (Object[])deserializeEnumBinaryArray(enumObj.field("testEnumArr"))); + } + + /** + * @param obj BinaryObject array. + * @return Deserialized enums. + */ + private TestEnum[] deserializeEnumBinaryArray(Object obj) { + Object[] arr = (Object[])obj; + + final TestEnum[] res = new TestEnum[arr.length]; + + for (int i = 0; i < arr.length; i++) + res[i] = ((BinaryObject)arr[i]).deserialize(); + + return res; + } + + /** + * + */ + private static class TestObjectExternalizable implements Externalizable { + /** */ + private String val; + + /** + * + */ + public TestObjectExternalizable() { + } + + /** + * @param val Value. + */ + public TestObjectExternalizable(final String val) { + this.val = val; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(final ObjectOutput out) throws IOException { + out.writeUTF(val); + } + + /** {@inheritDoc} */ + @Override public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException { + val = in.readUTF(); + } + + /** {@inheritDoc} */ + @Override public boolean equals(final Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + final TestObjectExternalizable that = (TestObjectExternalizable)o; + + return val != null ? val.equals(that.val) : that.val == null; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + return val != null ? val.hashCode() : 0; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return "TestObjectExternalizable{" + + "val='" + val + '\'' + + '}'; + } + } + + /** + * + */ + private enum TestEnum { + /** */ + A, + + /** */ + B + } }