You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2015/12/03 14:18:01 UTC

[24/35] ignite git commit: IGNITE-1695 - Fixed writing polymorphic types.

IGNITE-1695 - Fixed writing polymorphic types.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/2564a556
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/2564a556
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/2564a556

Branch: refs/heads/ignite-1626
Commit: 2564a556e353269d4adc58160512ed9d0a5979b4
Parents: e0c970a
Author: Alexey Goncharuk <al...@gmail.com>
Authored: Tue Dec 1 17:37:41 2015 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Tue Dec 1 17:37:41 2015 +0300

----------------------------------------------------------------------
 .../internal/portable/BinaryFieldAccessor.java  |  83 +++++++--
 .../internal/portable/BinaryReaderExImpl.java   |  11 ++
 .../ignite/internal/util/IgniteUtils.java       |   8 +
 .../portable/BinaryMarshallerSelfTest.java      | 186 ++++++++++++++++---
 4 files changed, 249 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/2564a556/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryFieldAccessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryFieldAccessor.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryFieldAccessor.java
index 0eda375..eece245 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryFieldAccessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryFieldAccessor.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.portable;
 
 import org.apache.ignite.binary.BinaryObjectException;
 import org.apache.ignite.internal.util.GridUnsafe;
+import org.apache.ignite.internal.util.typedef.internal.U;
 import sun.misc.Unsafe;
 
 import java.lang.reflect.Field;
@@ -74,8 +75,41 @@ public abstract class BinaryFieldAccessor {
             case P_DOUBLE:
                 return new DoublePrimitiveAccessor(field, id);
 
+            case BYTE:
+            case BOOLEAN:
+            case SHORT:
+            case CHAR:
+            case INT:
+            case LONG:
+            case FLOAT:
+            case DOUBLE:
+            case DECIMAL:
+            case STRING:
+            case UUID:
+            case DATE:
+            case TIMESTAMP:
+            case BYTE_ARR:
+            case SHORT_ARR:
+            case INT_ARR:
+            case LONG_ARR:
+            case FLOAT_ARR:
+            case DOUBLE_ARR:
+            case CHAR_ARR:
+            case BOOLEAN_ARR:
+            case DECIMAL_ARR:
+            case STRING_ARR:
+            case UUID_ARR:
+            case DATE_ARR:
+            case TIMESTAMP_ARR:
+            case ENUM_ARR:
+            case OBJECT_ARR:
+            case PORTABLE_OBJ:
+            case PORTABLE:
+            case EXTERNALIZABLE:
+                return new DefaultFinalClassAccessor(field, id, mode, false);
+
             default:
-                return new DefaultAccessor(field, id, mode);
+                return new DefaultFinalClassAccessor(field, id, mode, !U.isFinal(field.getType()));
         }
     }
 
@@ -389,10 +423,13 @@ public abstract class BinaryFieldAccessor {
     /**
      * Default accessor.
      */
-    private static class DefaultAccessor extends BinaryFieldAccessor {
+    private static class DefaultFinalClassAccessor extends BinaryFieldAccessor {
         /** Target field. */
         private final Field field;
 
+        /** Dynamic accessor flag. */
+        private final boolean dynamic;
+
         /**
          * Constructor.
          *
@@ -400,12 +437,13 @@ public abstract class BinaryFieldAccessor {
          * @param id Field ID.
          * @param mode Mode.
          */
-        public DefaultAccessor(Field field, int id, BinaryWriteMode mode) {
+        DefaultFinalClassAccessor(Field field, int id, BinaryWriteMode mode, boolean dynamic) {
             super(id, mode);
 
             assert field != null;
 
             this.field = field;
+            this.dynamic = dynamic;
         }
 
         /** {@inheritDoc} */
@@ -424,7 +462,7 @@ public abstract class BinaryFieldAccessor {
                 throw new BinaryObjectException("Failed to get value for field: " + field, e);
             }
 
-            switch (mode) {
+            switch (mode(val)) {
                 case BYTE:
                     writer.writeByteField((Byte) val);
 
@@ -609,6 +647,25 @@ public abstract class BinaryFieldAccessor {
 
         /** {@inheritDoc} */
         @Override public void read(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException {
+            Object val = dynamic ? reader.readField(id) : readFixedType(reader);
+
+            try {
+                if (val != null || !field.getType().isPrimitive())
+                    field.set(obj, val);
+            }
+            catch (IllegalAccessException e) {
+                throw new BinaryObjectException("Failed to set value for field: " + field, e);
+            }
+        }
+
+        /**
+         * Reads fixed type from the given reader with flags validation.
+         *
+         * @param reader Reader to read from.
+         * @return Read value.
+         * @throws BinaryObjectException If failed to read value from the stream.
+         */
+        protected Object readFixedType(BinaryReaderExImpl reader) throws BinaryObjectException {
             Object val = null;
 
             switch (mode) {
@@ -793,13 +850,17 @@ public abstract class BinaryFieldAccessor {
                     assert false : "Invalid mode: " + mode;
             }
 
-            try {
-                if (val != null || !field.getType().isPrimitive())
-                    field.set(obj, val);
-            }
-            catch (IllegalAccessException e) {
-                throw new BinaryObjectException("Failed to set value for field: " + field, e);
-            }
+            return val;
+        }
+
+        /**
+         * @param val Val to get write mode for.
+         * @return Write mode.
+         */
+        protected BinaryWriteMode mode(Object val) {
+            return dynamic ?
+                val == null ? BinaryWriteMode.OBJECT : PortableUtils.mode(val.getClass()) :
+                mode;
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/2564a556/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryReaderExImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryReaderExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryReaderExImpl.java
index b9f851c..ddbf6ba 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryReaderExImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryReaderExImpl.java
@@ -1628,6 +1628,17 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina
     }
 
     /**
+     * @return Deserialized object.
+     * @throws BinaryObjectException If failed.
+     */
+    @Nullable Object readField(int fieldId) throws BinaryObjectException {
+        if (!findFieldById(fieldId))
+            return null;
+
+        return new BinaryReaderExImpl(ctx, in, ldr, hnds).deserialize();
+    }
+
+    /**
      * @param name Field name.
      * @return Field offset.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/2564a556/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
index 3dfa9cc..121cd46 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
@@ -7667,6 +7667,14 @@ public abstract class IgniteUtils {
     }
 
     /**
+     * @param cls Class to check.
+     * @return {@code True} if class is final.
+     */
+    public static boolean isFinal(Class<?> cls) {
+        return Modifier.isFinal(cls.getModifiers());
+    }
+
+    /**
      * Gets field value.
      *
      * @param cls Class.

http://git-wip-us.apache.org/repos/asf/ignite/blob/2564a556/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryMarshallerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryMarshallerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryMarshallerSelfTest.java
index cc035f6..49be8dd 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryMarshallerSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/BinaryMarshallerSelfTest.java
@@ -21,6 +21,33 @@ import java.io.Externalizable;
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.InetSocketAddress;
+import java.sql.Timestamp;
+import java.util.AbstractQueue;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Queue;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListSet;
 import junit.framework.Assert;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.binary.BinaryIdMapper;
@@ -47,32 +74,10 @@ import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.marshaller.MarshallerContextTestImpl;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.jetbrains.annotations.NotNull;
 import org.jsr166.ConcurrentHashMap8;
 import sun.misc.Unsafe;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.net.InetSocketAddress;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentSkipListSet;
-
 import static org.apache.ignite.internal.portable.streams.PortableMemoryAllocator.INSTANCE;
 import static org.junit.Assert.assertArrayEquals;
 
@@ -98,7 +103,7 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
      * @throws Exception If failed.
      */
     public void testByte() throws Exception {
-        assertEquals((byte) 100, marshalUnmarshal((byte) 100).byteValue());
+        assertEquals((byte) 100, marshalUnmarshal((byte)100).byteValue());
     }
 
     /**
@@ -126,14 +131,14 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
      * @throws Exception If failed.
      */
     public void testFloat() throws Exception {
-        assertEquals(100.001f, marshalUnmarshal(100.001f).floatValue(), 0);
+        assertEquals(100.001f, marshalUnmarshal(100.001f), 0);
     }
 
     /**
      * @throws Exception If failed.
      */
     public void testDouble() throws Exception {
-        assertEquals(100.001d, marshalUnmarshal(100.001d).doubleValue(), 0);
+        assertEquals(100.001d, marshalUnmarshal(100.001d), 0);
     }
 
     /**
@@ -280,7 +285,7 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
      * @throws Exception If failed.
      */
     public void testDecimalArray() throws Exception {
-        BigDecimal[] arr = new BigDecimal[] { BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN } ;
+        BigDecimal[] arr = new BigDecimal[] {BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN} ;
 
         assertArrayEquals(arr, marshalUnmarshal(arr));
     }
@@ -348,7 +353,7 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
      */
     public void testMap() throws Exception {
         testMap(new HashMap<Integer, String>());
-        testMap(new LinkedHashMap());
+        testMap(new LinkedHashMap<Integer, String>());
         testMap(new TreeMap<Integer, String>());
         testMap(new ConcurrentHashMap8<Integer, String>());
         testMap(new ConcurrentHashMap<Integer, String>());
@@ -385,6 +390,18 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    public void testExternalizableInEnclosing() throws Exception {
+        SimpleEnclosingObject obj = new SimpleEnclosingObject();
+        obj.simpl = new SimpleExternalizable("field");
+
+        SimpleEnclosingObject other = marshalUnmarshal(obj);
+
+        assertEquals(((SimpleExternalizable)obj.simpl).field, ((SimpleExternalizable)other.simpl).field);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
     public void testMapEntry() throws Exception {
         Map.Entry<Integer, String> e = new GridMapEntry<>(1, "str1");
 
@@ -674,6 +691,111 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    public void testObjectFieldOfExternalizableCollection() throws Exception {
+        EnclosingObj obj = new EnclosingObj();
+
+        obj.queue = new TestQueue("test");
+
+        assertEquals(obj, marshalUnmarshal(obj));
+    }
+
+    /**
+     *
+     */
+    private static class EnclosingObj implements Serializable {
+        /** Queue. */
+        Queue<Integer> queue = new TestQueue("test");
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object o) {
+            if (this == o)
+                return true;
+
+            if (o == null || getClass() != o.getClass())
+                return false;
+
+            EnclosingObj obj = (EnclosingObj)o;
+
+            return Objects.equals(queue, obj.queue);
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return Objects.hash(queue);
+        }
+    }
+
+    /**
+     *
+     */
+    private static class TestQueue extends AbstractQueue<Integer> implements Externalizable {
+        /** Name. */
+        private String name;
+
+        /**
+         * @param name Name.
+         */
+        public TestQueue(String name) {
+            this.name = name;
+        }
+
+        /** {@inheritDoc} */
+        @NotNull @Override public Iterator<Integer> iterator() {
+            return Collections.emptyIterator();
+        }
+
+        /** {@inheritDoc} */
+        @Override public int size() {
+            return 0;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void writeExternal(ObjectOutput out) throws IOException {
+            out.writeObject(name);
+        }
+
+        /** {@inheritDoc} */
+        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+            name = (String)in.readObject();
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean offer(Integer integer) {
+            throw new UnsupportedOperationException();
+        }
+
+        /** {@inheritDoc} */
+        @Override public Integer poll() {
+            throw new UnsupportedOperationException();
+        }
+
+        /** {@inheritDoc} */
+        @Override public Integer peek() {
+            throw new UnsupportedOperationException();
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object o) {
+            if (this == o)
+                return true;
+
+            if (o == null || getClass() != o.getClass())
+                return false;
+
+            TestQueue integers = (TestQueue)o;
+
+            return Objects.equals(name, integers.name);
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return Objects.hash(name);
+        }
+    }
+
+    /**
      * @param obj Simple object.
      * @param po Portable object.
      */
@@ -3642,6 +3764,14 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
     /**
      *
      */
+    public static class SimpleEnclosingObject {
+        /** */
+        private Object simpl;
+    }
+
+    /**
+     *
+     */
     public static class SimpleExternalizable implements Externalizable {
         /** */
         private String field;