From bd642b995f3e154c1dce015a13e3341eeed87eef Mon Sep 17 00:00:00 2001 From: leventov Date: Fri, 3 Oct 2014 06:41:54 +0400 Subject: [PATCH] Abstract classes and interfaces always use the most conservative serializer. Fixed a bug with different objectSerializers during read and write (introduced in 38cda580321617a65359e7b015ce2bfd123e9474) --- .../chronicle/map/ChronicleMapBuilder.java | 3 + .../chronicle/map/SerializationBuilder.java | 74 ++++++++++++++----- 2 files changed, 58 insertions(+), 19 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java index be93dadf3..0ac5f334a 100644 --- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java @@ -524,6 +524,9 @@ public class ChronicleMapBuilder implements Cloneable { } private void preMapConstruction() { + keyBuilder.objectSerializer(objectSerializer()); + valueBuilder.objectSerializer(objectSerializer()); + int maxSize = entrySize() * figureBufferAllocationFactor(); keyBuilder.maxSize(maxSize); valueBuilder.maxSize(maxSize); diff --git a/src/main/java/net/openhft/chronicle/map/SerializationBuilder.java b/src/main/java/net/openhft/chronicle/map/SerializationBuilder.java index ca6743b2f..6728d638f 100644 --- a/src/main/java/net/openhft/chronicle/map/SerializationBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/SerializationBuilder.java @@ -22,17 +22,22 @@ import net.openhft.lang.io.Bytes; import net.openhft.lang.io.serialization.*; import net.openhft.lang.io.serialization.impl.*; import net.openhft.lang.model.Byteable; -import net.openhft.lang.model.DataValueClasses; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.Externalizable; +import java.io.IOException; import java.io.Serializable; +import java.lang.reflect.Modifier; import static net.openhft.chronicle.map.Objects.hash; import static net.openhft.chronicle.map.serialization.SizeMarshallers.stopBit; final class SerializationBuilder implements Cloneable { + + private static boolean concreteClass(Class c) { + return !c.isInterface() && !Modifier.isAbstract(c.getModifiers()); + } private static boolean marshallerUseFactory(Class c) { return Byteable.class.isAssignableFrom(c) || @@ -51,25 +56,22 @@ final class SerializationBuilder implements Cloneable { private CopyingInterop copyingInterop = null; private MetaBytesInterop metaInterop; private MetaProvider metaInteropProvider; - private ObjectFactory factory; + private ObjectFactory factory; @SuppressWarnings("unchecked") SerializationBuilder(Class eClass, Role role) { this.bufferIdentity = role; this.eClass = eClass; - Class classForMarshaller = marshallerUseFactory(eClass) && eClass.isInterface() ? - DataValueClasses.directClassFor(eClass) : eClass; - ObjectFactory factory = null; - if (role == Role.VALUE) { - factory = marshallerUseFactory(eClass) ? - new AllocateInstanceObjectFactory( - eClass.isInterface() ? classForMarshaller : eClass) : + ObjectFactory factory = this.factory; + if (factory == null && role == Role.VALUE) { + factory = concreteClass(eClass) && marshallerUseFactory(eClass) ? + new AllocateInstanceObjectFactory(eClass) : NullObjectFactory.INSTANCE; } - if (Byteable.class.isAssignableFrom(eClass)) { - agileMarshaller(ByteableMarshaller.of((Class) classForMarshaller), factory); + if (concreteClass(eClass) && Byteable.class.isAssignableFrom(eClass)) { + agileMarshaller(ByteableMarshaller.of((Class) eClass), factory); } else if (eClass == CharSequence.class || eClass == String.class) { reader((BytesReader) CharSequenceReader.of(), factory); writer((BytesWriter) CharSequenceWriter.instance()); @@ -78,8 +80,10 @@ final class SerializationBuilder implements Cloneable { } else if (eClass == byte[].class) { reader((BytesReader) ByteArrayMarshaller.INSTANCE, factory); interop((BytesInterop) ByteArrayMarshaller.INSTANCE); - } else { - marshaller(chooseMarshaller(eClass, classForMarshaller), factory); + } else if (concreteClass(eClass)) { + BytesMarshaller marshaller = chooseMarshaller(eClass, eClass); + if (marshaller != null) + marshaller(marshaller, factory); } } @@ -93,7 +97,7 @@ final class SerializationBuilder implements Cloneable { return (BytesMarshaller) IntegerMarshaller.INSTANCE; if (eClass == Double.class) return (BytesMarshaller) DoubleMarshaller.INSTANCE; - return SerializableMarshaller.INSTANCE; + return null; } private SerializationBuilder copyingInterop(CopyingInterop copyingInterop) { @@ -148,6 +152,16 @@ final class SerializationBuilder implements Cloneable { return this; } + public SerializationBuilder objectSerializer(ObjectSerializer serializer) { + if (reader == null || interop == null) { + ObjectFactory factory = this.factory; + if (factory == null) + factory = NullObjectFactory.INSTANCE; + marshaller(new SerializableMarshaller(serializer), factory); + } + return this; + } + public SizeMarshaller sizeMarshaller() { return sizeMarshaller; } @@ -297,24 +311,46 @@ final class SerializationBuilder implements Cloneable { } - private enum SerializableMarshaller implements BytesMarshaller { - INSTANCE; + private static class SerializableMarshaller implements BytesMarshaller { + private static final long serialVersionUID = 0L; + + private final ObjectSerializer serializer; + + private SerializableMarshaller(ObjectSerializer serializer) { + this.serializer = serializer; + } @Override public void write(Bytes bytes, Object obj) { - bytes.writeObject(obj); + try { + serializer.writeSerializable(bytes, obj, null); + } catch (IOException e) { + throw new IllegalStateException(e); + } } @Nullable @Override public Object read(Bytes bytes) { - return bytes.readObject(); + try { + return serializer.readSerializable(bytes, null, null); + } catch (IOException e) { + throw new IllegalStateException(e); + } catch (ClassNotFoundException e) { + throw new IllegalStateException(e); + } } @Nullable @Override public Object read(Bytes bytes, @Nullable Object obj) { - return bytes.readInstance(null, obj); + try { + return serializer.readSerializable(bytes, null, obj); + } catch (IOException e) { + throw new IllegalStateException(e); + } catch (ClassNotFoundException e) { + throw new IllegalStateException(e); + } } }