Skip to content

Commit 9d14207

Browse files
author
Mr14huashao
committed
[kryo-699] Add an exception for extendedFieldName
1 parent 78f3332 commit 9d14207

2 files changed

Lines changed: 132 additions & 0 deletions

File tree

src/com/esotericsoftware/kryo/serializers/CompatibleFieldSerializer.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import com.esotericsoftware.kryo.io.OutputChunked;
3232
import com.esotericsoftware.kryo.util.ObjectMap;
3333
import com.esotericsoftware.kryo.util.Util;
34+
import java.util.ArrayList;
3435

3536
/** Serializes objects using direct field assignment, providing both forward and backward compatibility. This means fields can be
3637
* added or removed without invalidating previously serialized bytes. Renaming or changing the type of a field is not supported.
@@ -64,11 +65,18 @@ public void write (Kryo kryo, Output output, T object) {
6465

6566
CachedField[] fields = cachedFields.fields;
6667
ObjectMap context = kryo.getGraphContext();
68+
ArrayList fieldsList = new ArrayList();
6769
if (!context.containsKey(this)) {
6870
if (TRACE) trace("kryo", "Write fields for class: " + type.getName());
6971
context.put(this, null);
7072
output.writeVarInt(fields.length, true);
7173
for (int i = 0, n = fields.length; i < n; i++) {
74+
fieldsList.add(fields[i].name);
75+
if (i + 1 < n) {
76+
if (fieldsList.contains(fields[i+1].name))
77+
throw new IllegalArgumentException(fields[i].field.getDeclaringClass() +
78+
" has the same field as the super class, config.ExtendedFieldNames must be true");
79+
}
7280
if (TRACE) trace("kryo", "Write field name: " + fields[i].name + pos(output.position()));
7381
output.writeString(fields[i].name);
7482
}

test/com/esotericsoftware/kryo/serializers/CompatibleFieldSerializerTest.java

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,28 @@
2424
import com.esotericsoftware.kryo.Kryo;
2525
import com.esotericsoftware.kryo.KryoException;
2626
import com.esotericsoftware.kryo.KryoTestCase;
27+
import com.esotericsoftware.kryo.Serializer;
28+
import com.esotericsoftware.kryo.SerializerFactory;
2729
import com.esotericsoftware.kryo.SerializerFactory.CompatibleFieldSerializerFactory;
2830

31+
import java.io.File;
32+
import java.io.FileInputStream;
33+
import java.io.FileOutputStream;
34+
import java.io.IOException;
2935
import java.io.Serializable;
3036
import java.util.Arrays;
3137
import java.util.List;
3238
import java.util.Objects;
3339

40+
import com.esotericsoftware.kryo.io.Input;
41+
import com.esotericsoftware.kryo.io.Output;
42+
import com.esotericsoftware.kryo.util.DefaultInstantiatorStrategy;
3443
import org.apache.commons.lang.builder.EqualsBuilder;
44+
import org.junit.Assert;
3545
import org.junit.Rule;
3646
import org.junit.Test;
3747
import org.junit.rules.ExpectedException;
48+
import org.objenesis.strategy.SerializingInstantiatorStrategy;
3849

3950
/** @author Nathan Sweet */
4051
public class CompatibleFieldSerializerTest extends KryoTestCase {
@@ -642,4 +653,117 @@ public int hashCode () {
642653
return Objects.hash(value, list, serializable);
643654
}
644655
}
656+
// #699 check ExtendedFieldName for CompatibleFieldSerializer
657+
static public class ExtendedFieldNamesTest {
658+
@Test(expected = IllegalArgumentException.class)
659+
public void setExtendedFieldNamesDefault() throws IOException {
660+
final Child child = new Child();
661+
child.setCustomNote(true);
662+
child.setCid(3);
663+
Kryo kryo = getKryo(false);
664+
final File outputFile = File.createTempFile("temp_output", "dat");
665+
try (final Output output = new Output(new FileOutputStream(outputFile))) {
666+
kryo.writeObject(output, child);
667+
}
668+
}
669+
670+
@Test
671+
public void setExtendedFieldNamesIsTrue() throws IOException {
672+
final Child child = new Child();
673+
child.setCustomNote(true);
674+
child.setCid(3);
675+
Kryo kryo = getKryo(true);
676+
final File outputFile = File.createTempFile("temp_output", "dat");
677+
try (final Output output = new Output(new FileOutputStream(outputFile))) {
678+
kryo.writeObject(output, child);
679+
final Input input = new Input(new FileInputStream(outputFile));
680+
final Child restoreChild = kryo.readObject(input, Child.class);
681+
Assert.assertEquals(true, restoreChild.customNote);
682+
input.close();
683+
}
684+
}
685+
686+
private Kryo getKryo(Boolean isSetExtendedFieldNames) {
687+
final Kryo kryo = new Kryo();
688+
kryo.setDefaultSerializer(new SerializerFactory.BaseSerializerFactory() {
689+
@Override
690+
public Serializer newSerializer(Kryo kryo, Class type) {
691+
final CompatibleFieldSerializer.CompatibleFieldSerializerConfig config =
692+
new CompatibleFieldSerializer.CompatibleFieldSerializerConfig();
693+
config.setChunkedEncoding(true);
694+
config.setReadUnknownFieldData(true);
695+
if (isSetExtendedFieldNames)
696+
config.setExtendedFieldNames(true);
697+
final CompatibleFieldSerializer serializer = new CompatibleFieldSerializer(kryo, type, config);
698+
return serializer;
699+
}
700+
});
701+
kryo.setRegistrationRequired(false);
702+
kryo.setInstantiatorStrategy(new DefaultInstantiatorStrategy(new SerializingInstantiatorStrategy()));
703+
return kryo;
704+
}
705+
706+
private class Child extends Father {
707+
private Integer cid = 1;
708+
private Boolean customNote = true;
709+
710+
public void setCid(Integer cid) {
711+
this.cid = cid;
712+
}
713+
714+
public int getCid() {
715+
return this.cid;
716+
}
717+
718+
public void setCustomNote(Boolean customNote) {
719+
this.customNote = customNote;
720+
}
721+
722+
public Boolean getCustomNote() {
723+
return this.customNote;
724+
}
725+
}
726+
727+
private class Father extends Grandpa {
728+
private Integer fid = 1;
729+
private String name = "Alan";
730+
731+
public void setFid(Integer fid) {
732+
this.fid = fid;
733+
}
734+
735+
public int getFid() {
736+
return this.fid;
737+
}
738+
739+
public void setName(String name) {
740+
this.name = name;
741+
}
742+
743+
public String getName() {
744+
return this.name;
745+
}
746+
}
747+
748+
private class Grandpa implements Serializable {
749+
private Integer gid = 1;
750+
private Boolean customNote = false;
751+
752+
public void setGid(Integer gid) {
753+
this.gid = gid;
754+
}
755+
756+
public int getGid() {
757+
return this.gid;
758+
}
759+
760+
public void setCustomNote(Boolean customNote) {
761+
this.customNote = customNote;
762+
}
763+
764+
public Boolean getCustomNote() {
765+
return this.customNote;
766+
}
767+
}
768+
}
645769
}

0 commit comments

Comments
 (0)