TINKERPOP-1584 Made Gryo support a number of classes GraphSON supported. Added ByteBuffer, Timestamp, InetAddress and fixed serialization of Class (which never worked in the first place).
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/5f132ebc Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/5f132ebc Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/5f132ebc Branch: refs/heads/TINKERPOP-1545-tp32 Commit: 5f132ebc41538691f5d2f52921ad032e33ffcf78 Parents: c66bbdf Author: Stephen Mallette <sp...@genoprime.com> Authored: Fri Dec 16 08:39:59 2016 -0500 Committer: Stephen Mallette <sp...@genoprime.com> Committed: Tue Dec 20 13:23:58 2016 -0500 ---------------------------------------------------------------------- CHANGELOG.asciidoc | 2 + .../structure/io/gryo/GryoClassResolver.java | 9 +++ .../gremlin/structure/io/gryo/GryoMapper.java | 9 ++- .../structure/io/gryo/UtilSerializers.java | 62 ++++++++++++++++++++ .../structure/io/gryo/GryoMapperTest.java | 27 +++++++++ 5 files changed, 107 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5f132ebc/CHANGELOG.asciidoc ---------------------------------------------------------------------- diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 60e1bb1..02531ba 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -28,6 +28,8 @@ TinkerPop 3.2.4 (Release Date: NOT OFFICIALLY RELEASED YET) * Lessened the severity of Gremlin Server logging when it encounters two or more serializers addressing the same mime type. * Bumped to Netty 4.0.42.final. +* Added `ByteBuffer`, `InetAddress`, `Timestamp` to the list of Gryo supported classes. +* Fixed Gryo serialization of `Class`. * Fixed a bug in Gremlin-Python around `__.__()` and `__.start()`. * Fixed a bug around long serialization in Gremlin-Python when using Python3. * Deprecated `TraversalSource.withBindings()` as it is no longer needed in Gremlin-Java and never was needed for other variants. http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5f132ebc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoClassResolver.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoClassResolver.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoClassResolver.java index 53f4382..1ee8612 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoClassResolver.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoClassResolver.java @@ -44,6 +44,9 @@ import org.apache.tinkerpop.shaded.kryo.util.IdentityObjectIntMap; import org.apache.tinkerpop.shaded.kryo.util.IntMap; import org.apache.tinkerpop.shaded.kryo.util.ObjectMap; +import java.net.InetAddress; +import java.nio.ByteBuffer; + import static org.apache.tinkerpop.shaded.kryo.util.Util.getWrapperClass; /** @@ -108,6 +111,12 @@ public class GryoClassResolver implements ClassResolver { type = Path.class; else if (Lambda.class.isAssignableFrom(clazz)) type = Lambda.class; + else if (ByteBuffer.class.isAssignableFrom(clazz)) + type = ByteBuffer.class; + else if (Class.class.isAssignableFrom(clazz)) + type = Class.class; + else if (InetAddress.class.isAssignableFrom(clazz)) + type = InetAddress.class; else type = clazz; http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5f132ebc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java index fef7288..bbd3999 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java @@ -96,7 +96,9 @@ import org.javatuples.Pair; import java.math.BigDecimal; import java.math.BigInteger; +import java.net.InetAddress; import java.net.URI; +import java.nio.ByteBuffer; import java.time.Duration; import java.time.Instant; import java.time.LocalDate; @@ -274,7 +276,7 @@ public final class GryoMapper implements Mapper<Kryo> { add(GryoTypeReg.of(BigInteger.class, 34)); add(GryoTypeReg.of(BigDecimal.class, 35)); add(GryoTypeReg.of(Calendar.class, 39)); - add(GryoTypeReg.of(Class.class, 41)); + add(GryoTypeReg.of(Class.class, 41, new UtilSerializers.ClassSerializer())); add(GryoTypeReg.of(Collection.class, 37)); add(GryoTypeReg.of(Collections.EMPTY_LIST.getClass(), 51)); add(GryoTypeReg.of(Collections.EMPTY_MAP.getClass(), 52)); @@ -313,6 +315,9 @@ public final class GryoMapper implements Mapper<Kryo> { add(GryoTypeReg.of(VertexTerminator.class, 13)); add(GryoTypeReg.of(AbstractMap.SimpleEntry.class, 120)); add(GryoTypeReg.of(AbstractMap.SimpleImmutableEntry.class, 121)); + add(GryoTypeReg.of(java.sql.Timestamp.class, 138)); + add(GryoTypeReg.of(InetAddress.class, 139, new UtilSerializers.InetAddressSerializer())); + add(GryoTypeReg.of(ByteBuffer.class, 140, new UtilSerializers.ByteBufferSerializer())); // ***LAST ID*** add(GryoTypeReg.of(ReferenceEdge.class, 81)); add(GryoTypeReg.of(ReferenceVertexProperty.class, 82)); @@ -350,7 +355,7 @@ public final class GryoMapper implements Mapper<Kryo> { add(GryoTypeReg.of(Column.class, 132)); add(GryoTypeReg.of(Pop.class, 133)); add(GryoTypeReg.of(SackFunctions.Barrier.class, 135)); - add(GryoTypeReg.of(TraversalOptionParent.Pick.class, 137)); // ***LAST ID*** + add(GryoTypeReg.of(TraversalOptionParent.Pick.class, 137)); add(GryoTypeReg.of(HashSetSupplier.class, 136, new UtilSerializers.HashSetSupplierSerializer())); add(GryoTypeReg.of(TraverserSet.class, 58)); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5f132ebc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/UtilSerializers.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/UtilSerializers.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/UtilSerializers.java index 6f0a632..958978c 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/UtilSerializers.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/UtilSerializers.java @@ -29,7 +29,9 @@ import org.apache.tinkerpop.shaded.kryo.io.Input; import org.apache.tinkerpop.shaded.kryo.io.Output; import org.javatuples.Pair; +import java.net.InetAddress; import java.net.URI; +import java.nio.ByteBuffer; import java.util.AbstractMap; import java.util.ArrayList; import java.util.List; @@ -60,6 +62,66 @@ final class UtilSerializers { } } + public final static class ByteBufferSerializer implements SerializerShim<ByteBuffer> { + @Override + public <O extends OutputShim> void write(final KryoShim<?, O> kryo, final O output, final ByteBuffer bb) { + final byte[] b = new byte[bb.remaining()]; + bb.get(b); + output.writeInt(b.length); + output.writeBytes(b, 0, b.length); + } + + @Override + public <I extends InputShim> ByteBuffer read(final KryoShim<I, ?> kryo, final I input, final Class<ByteBuffer> clazz) { + final int len = input.readInt(); + final byte[] b = input.readBytes(len); + final ByteBuffer bb = ByteBuffer.allocate(len); + bb.put(b); + return bb; + } + } + + public final static class ClassSerializer implements SerializerShim<Class> { + @Override + public <O extends OutputShim> void write(final KryoShim<?, O> kryo, final O output, final Class object) { + output.writeString(object.getCanonicalName()); + } + + @Override + public <I extends InputShim> Class read(final KryoShim<I, ?> kryo, final I input, final Class<Class> clazz) { + final String name = input.readString(); + try { + return Class.forName(name); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + } + + public final static class InetAddressSerializer implements SerializerShim<InetAddress> { + @Override + public <O extends OutputShim> void write(final KryoShim<?, O> kryo, final O output, final InetAddress addy) { + final String str = addy.toString().trim(); + final int slash = str.indexOf('/'); + if (slash >= 0) { + if (slash == 0) { + output.writeString(str.substring(1)); + } else { + output.writeString(str.substring(0, slash)); + } + } + } + + @Override + public <I extends InputShim> InetAddress read(final KryoShim<I, ?> kryo, final I input, final Class<InetAddress> clazz) { + try { + return InetAddress.getByName(input.readString()); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + } + public final static class HashSetSupplierSerializer implements SerializerShim<HashSetSupplier> { @Override public <O extends OutputShim> void write(final KryoShim<?, O> kryo, final O output, final HashSetSupplier hashSetSupplier) { http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5f132ebc/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapperTest.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapperTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapperTest.java index 6f808e4..9f5ba41 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapperTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapperTest.java @@ -40,6 +40,9 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; +import java.net.InetAddress; +import java.nio.ByteBuffer; +import java.sql.Timestamp; import java.time.Duration; import java.time.Instant; import java.time.LocalDate; @@ -338,6 +341,30 @@ public class GryoMapperTest { assertEquals(bytecode.toString(), serializeDeserialize(bytecode, Bytecode.class).toString()); } + @Test + public void shouldHandleClass() throws Exception { + final Class clazz = java.io.File.class; + assertEquals(clazz, serializeDeserialize(clazz, Class.class)); + } + + @Test + public void shouldHandleTimestamp() throws Exception { + final Timestamp ts = new java.sql.Timestamp(1481750076295L); + assertEquals(ts, serializeDeserialize(ts, java.sql.Timestamp.class)); + } + + @Test + public void shouldHandleINetAddress() throws Exception { + final InetAddress addy = InetAddress.getByName("localhost"); + assertEquals(addy, serializeDeserialize(addy, InetAddress.class)); + } + + @Test + public void shouldHandleByteBuffer() throws Exception { + final ByteBuffer bb = ByteBuffer.wrap("some bytes for you".getBytes()); + assertEquals(bb, serializeDeserialize(bb, ByteBuffer.class)); + } + public <T> T serializeDeserialize(final Object o, final Class<T> clazz) throws Exception { try (final ByteArrayOutputStream stream = new ByteArrayOutputStream()) { final Output out = new Output(stream);