From 63146323225621a0bcaabd14d6db605305546c4c Mon Sep 17 00:00:00 2001 From: Mr14huashao Date: Mon, 31 Aug 2020 11:02:31 +0800 Subject: [PATCH] Add a WARN for extendedFieldName --- .../CompatibleFieldSerializer.java | 17 +++ .../CompatibleFieldSerializerTest.java | 123 ++++++++++++++++++ 2 files changed, 140 insertions(+) diff --git a/src/com/esotericsoftware/kryo/serializers/CompatibleFieldSerializer.java b/src/com/esotericsoftware/kryo/serializers/CompatibleFieldSerializer.java index b6c3c371d..5f9e538f2 100644 --- a/src/com/esotericsoftware/kryo/serializers/CompatibleFieldSerializer.java +++ b/src/com/esotericsoftware/kryo/serializers/CompatibleFieldSerializer.java @@ -31,6 +31,7 @@ import com.esotericsoftware.kryo.io.OutputChunked; import com.esotericsoftware.kryo.util.ObjectMap; import com.esotericsoftware.kryo.util.Util; +import java.util.HashSet; /** Serializes objects using direct field assignment, providing both forward and backward compatibility. This means fields can be * added or removed without invalidating previously serialized bytes. Renaming or changing the type of a field is not supported. @@ -58,6 +59,22 @@ public CompatibleFieldSerializer (Kryo kryo, Class type, CompatibleFieldSerializ this.config = config; } + @Override + protected void initializeCachedFields() { + if (!this.getFieldSerializerConfig().extendedFieldNames) { + final HashSet hashSet = new HashSet(); + CachedField[] fields = cachedFields.fields; + if (TRACE) trace("kryo", "Write fields for class: " + type.getName()); + for (int i = 0, n = fields.length; i < n; i++) { + if (!hashSet.add(fields[i].field.getName())) { + if (WARN) warn(fields[i].field.getDeclaringClass() + + ": Duplicate field detected in class hierarchy"); + break; + } + } + } + } + @Override public void write (Kryo kryo, Output output, T object) { int pop = pushTypeVariables(); diff --git a/test/com/esotericsoftware/kryo/serializers/CompatibleFieldSerializerTest.java b/test/com/esotericsoftware/kryo/serializers/CompatibleFieldSerializerTest.java index 829382467..cbc5cd681 100644 --- a/test/com/esotericsoftware/kryo/serializers/CompatibleFieldSerializerTest.java +++ b/test/com/esotericsoftware/kryo/serializers/CompatibleFieldSerializerTest.java @@ -24,17 +24,28 @@ import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.KryoException; import com.esotericsoftware.kryo.KryoTestCase; +import com.esotericsoftware.kryo.Serializer; +import com.esotericsoftware.kryo.SerializerFactory; import com.esotericsoftware.kryo.SerializerFactory.CompatibleFieldSerializerFactory; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; import java.io.Serializable; import java.util.Arrays; import java.util.List; import java.util.Objects; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; +import com.esotericsoftware.kryo.util.DefaultInstantiatorStrategy; import org.apache.commons.lang.builder.EqualsBuilder; +import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.objenesis.strategy.SerializingInstantiatorStrategy; /** @author Nathan Sweet */ public class CompatibleFieldSerializerTest extends KryoTestCase { @@ -642,4 +653,116 @@ public int hashCode () { return Objects.hash(value, list, serializable); } } + + @Test + public void testExtendedFieldNamesDefault() throws IOException { + final ClassWithDuplicateField duplicateField = new ClassWithDuplicateField(); + duplicateField.setCustomNote(true); + duplicateField.setCid(3); + Kryo kryo = getKryo(false); + final File outputFile = File.createTempFile("temp_output", "dat"); + try (final Output output = new Output(new FileOutputStream(outputFile))) { + kryo.writeObject(output, duplicateField); + output.flush(); + } + } + + @Test + public void testExtendedFieldNamesTrue() throws IOException { + final ClassWithDuplicateField duplicateField = new ClassWithDuplicateField(); + duplicateField.setCustomNote(true); + duplicateField.setCid(3); + Kryo kryo = getKryo(true); + final File outputFile = File.createTempFile("temp_output", "dat"); + try (final Output output = new Output(new FileOutputStream(outputFile))) { + kryo.writeObject(output, duplicateField); + final Input input = new Input(new FileInputStream(outputFile)); + final ClassWithDuplicateField restoreField = kryo.readObject(input, ClassWithDuplicateField.class); + Assert.assertEquals(true, restoreField.customNote); + input.close(); + } + } + + private static Kryo getKryo(Boolean isSetExtendedFieldNames) { + final Kryo kryo = new Kryo(); + kryo.setDefaultSerializer(new SerializerFactory.BaseSerializerFactory() { + @Override + public Serializer newSerializer(Kryo kryo, Class type) { + final CompatibleFieldSerializer.CompatibleFieldSerializerConfig config = + new CompatibleFieldSerializer.CompatibleFieldSerializerConfig(); + config.setChunkedEncoding(true); + config.setReadUnknownFieldData(true); + if (isSetExtendedFieldNames) + config.setExtendedFieldNames(true); + final CompatibleFieldSerializer serializer = new CompatibleFieldSerializer(kryo, type, config); + return serializer; + } + }); + kryo.setRegistrationRequired(false); + kryo.setInstantiatorStrategy(new DefaultInstantiatorStrategy(new SerializingInstantiatorStrategy())); + return kryo; + } + + static class ClassWithDuplicateField extends SuperClass { + private Integer cid = 1; + private Boolean customNote = true; + + public void setCid(Integer cid) { + this.cid = cid; + } + + public int getCid() { + return this.cid; + } + + public void setCustomNote(Boolean customNote) { + this.customNote = customNote; + } + + public Boolean getCustomNote() { + return this.customNote; + } + } + + static class SuperClass extends SuperSuperClass { + private Integer fid = 1; + private String name = "Alan"; + + public void setFid(Integer fid) { + this.fid = fid; + } + + public int getFid() { + return this.fid; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + } + + static class SuperSuperClass implements Serializable { + private Integer gid = 1; + private Boolean customNote = false; + + public void setGid(Integer gid) { + this.gid = gid; + } + + public int getGid() { + return this.gid; + } + + public void setCustomNote(Boolean customNote) { + this.customNote = customNote; + } + + public Boolean getCustomNote() { + return this.customNote; + } + } }