Commit 964201af authored by Jonathan Haber's avatar Jonathan Haber Committed by Feng Xiao

Store the class object itself (#4927)

* Store the class object itself

* Add test for backwards compatibility

* Rename and add test

* Add comments
parent bc2364c6
...@@ -1407,7 +1407,7 @@ public abstract class GeneratedMessageLite< ...@@ -1407,7 +1407,7 @@ public abstract class GeneratedMessageLite<
/** /**
* A serialized (serializable) form of the generated message. Stores the * A serialized (serializable) form of the generated message. Stores the
* message as a class name and a byte array. * message as a class and a byte array.
*/ */
protected static final class SerializedForm implements Serializable { protected static final class SerializedForm implements Serializable {
...@@ -1417,6 +1417,9 @@ public abstract class GeneratedMessageLite< ...@@ -1417,6 +1417,9 @@ public abstract class GeneratedMessageLite<
private static final long serialVersionUID = 0L; private static final long serialVersionUID = 0L;
// since v3.6.1
private final Class<?> messageClass;
// only included for backwards compatibility before messageClass was added
private final String messageClassName; private final String messageClassName;
private final byte[] asBytes; private final byte[] asBytes;
...@@ -1425,7 +1428,8 @@ public abstract class GeneratedMessageLite< ...@@ -1425,7 +1428,8 @@ public abstract class GeneratedMessageLite<
* @param regularForm the message to serialize * @param regularForm the message to serialize
*/ */
SerializedForm(MessageLite regularForm) { SerializedForm(MessageLite regularForm) {
messageClassName = regularForm.getClass().getName(); messageClass = regularForm.getClass();
messageClassName = messageClass.getName();
asBytes = regularForm.toByteArray(); asBytes = regularForm.toByteArray();
} }
...@@ -1437,7 +1441,7 @@ public abstract class GeneratedMessageLite< ...@@ -1437,7 +1441,7 @@ public abstract class GeneratedMessageLite<
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected Object readResolve() throws ObjectStreamException { protected Object readResolve() throws ObjectStreamException {
try { try {
Class<?> messageClass = Class.forName(messageClassName); Class<?> messageClass = resolveMessageClass();
java.lang.reflect.Field defaultInstanceField = java.lang.reflect.Field defaultInstanceField =
messageClass.getDeclaredField("DEFAULT_INSTANCE"); messageClass.getDeclaredField("DEFAULT_INSTANCE");
defaultInstanceField.setAccessible(true); defaultInstanceField.setAccessible(true);
...@@ -1464,7 +1468,7 @@ public abstract class GeneratedMessageLite< ...@@ -1464,7 +1468,7 @@ public abstract class GeneratedMessageLite<
@Deprecated @Deprecated
private Object readResolveFallback() throws ObjectStreamException { private Object readResolveFallback() throws ObjectStreamException {
try { try {
Class<?> messageClass = Class.forName(messageClassName); Class<?> messageClass = resolveMessageClass();
java.lang.reflect.Field defaultInstanceField = java.lang.reflect.Field defaultInstanceField =
messageClass.getDeclaredField("defaultInstance"); messageClass.getDeclaredField("defaultInstance");
defaultInstanceField.setAccessible(true); defaultInstanceField.setAccessible(true);
...@@ -1484,6 +1488,10 @@ public abstract class GeneratedMessageLite< ...@@ -1484,6 +1488,10 @@ public abstract class GeneratedMessageLite<
throw new RuntimeException("Unable to understand proto buffer", e); throw new RuntimeException("Unable to understand proto buffer", e);
} }
} }
private Class<?> resolveMessageClass() throws ClassNotFoundException {
return messageClass != null ? messageClass : Class.forName(messageClassName);
}
} }
/** /**
......
...@@ -32,6 +32,7 @@ package com.google.protobuf; ...@@ -32,6 +32,7 @@ package com.google.protobuf;
import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Int32Value;
import com.google.protobuf.test.UnittestImport; import com.google.protobuf.test.UnittestImport;
import protobuf_unittest.EnumWithNoOuter; import protobuf_unittest.EnumWithNoOuter;
import protobuf_unittest.MessageWithNoOuter; import protobuf_unittest.MessageWithNoOuter;
...@@ -853,6 +854,75 @@ public class GeneratedMessageTest extends TestCase { ...@@ -853,6 +854,75 @@ public class GeneratedMessageTest extends TestCase {
assertEquals(expected, actual); assertEquals(expected, actual);
} }
public void testDeserializeWithoutClassField() throws Exception {
// serialized form for version <=3.6.0
// just includes messageClassName and asBytes
// Int32Value.newBuilder().setValue(123).build()
byte[] int32ValueBytes = new byte[]{
-84, -19, 0, 5, 115, 114, 0, 55, 99, 111, 109, 46, 103, 111, 111,
103, 108, 101, 46, 112, 114, 111, 116, 111, 98, 117, 102, 46, 71,
101, 110, 101, 114, 97, 116, 101, 100, 77, 101, 115, 115, 97, 103,
101, 76, 105, 116, 101, 36, 83, 101, 114, 105, 97, 108, 105, 122,
101, 100, 70, 111, 114, 109, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 91,
0, 7, 97, 115, 66, 121, 116, 101, 115, 116, 0, 2, 91, 66, 76, 0,
16, 109, 101, 115, 115, 97, 103, 101, 67, 108, 97, 115, 115, 78,
97, 109, 101, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110,
103, 47, 83, 116, 114, 105, 110, 103, 59, 120, 112, 117, 114, 0,
2, 91, 66, -84, -13, 23, -8, 6, 8, 84, -32, 2, 0, 0, 120, 112, 0,
0, 0, 2, 8, 123, 116, 0, 30, 99, 111, 109, 46, 103, 111, 111, 103,
108, 101, 46, 112, 114, 111, 116, 111, 98, 117, 102, 46, 73, 110,
116, 51, 50, 86, 97, 108, 117, 101
};
ByteArrayInputStream bais = new ByteArrayInputStream(int32ValueBytes);
ObjectInputStream in = new ObjectInputStream(bais);
Int32Value int32Value = (Int32Value) in.readObject();
assertEquals(123, int32Value.getValue());
}
public void testDeserializeWithClassField() throws Exception {
// serialized form for version > 3.6.0
// includes messageClass, messageClassName (for compatibility), and asBytes
// Int32Value.newBuilder().setValue(123).build()
byte[] int32ValueBytes = new byte[]{
-84, -19, 0, 5, 115, 114, 0, 55, 99, 111, 109, 46, 103, 111, 111,
103, 108, 101, 46, 112, 114, 111, 116, 111, 98, 117, 102, 46, 71,
101, 110, 101, 114, 97, 116, 101, 100, 77, 101, 115, 115, 97, 103,
101, 76, 105, 116, 101, 36, 83, 101, 114, 105, 97, 108, 105, 122,
101, 100, 70, 111, 114, 109, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 91,
0, 7, 97, 115, 66, 121, 116, 101, 115, 116, 0, 2, 91, 66, 76, 0,
12, 109, 101, 115, 115, 97, 103, 101, 67, 108, 97, 115, 115, 116,
0, 17, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 67, 108,
97, 115, 115, 59, 76, 0, 16, 109, 101, 115, 115, 97, 103, 101, 67,
108, 97, 115, 115, 78, 97, 109, 101, 116, 0, 18, 76, 106, 97, 118,
97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59,
120, 112, 117, 114, 0, 2, 91, 66, -84, -13, 23, -8, 6, 8, 84, -32,
2, 0, 0, 120, 112, 0, 0, 0, 2, 8, 123, 118, 114, 0, 30, 99, 111,
109, 46, 103, 111, 111, 103, 108, 101, 46, 112, 114, 111, 116, 111,
98, 117, 102, 46, 73, 110, 116, 51, 50, 86, 97, 108, 117, 101, 0, 0,
0, 0, 0, 0, 0, 0, 2, 0, 2, 66, 0, 21, 109, 101, 109, 111, 105, 122,
101, 100, 73, 115, 73, 110, 105, 116, 105, 97, 108, 105, 122, 101,
100, 73, 0, 6, 118, 97, 108, 117, 101, 95, 120, 114, 0, 38, 99, 111,
109, 46, 103, 111, 111, 103, 108, 101, 46, 112, 114, 111, 116, 111,
98, 117, 102, 46, 71, 101, 110, 101, 114, 97, 116, 101, 100, 77,
101, 115, 115, 97, 103, 101, 86, 51, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0,
1, 76, 0, 13, 117, 110, 107, 110, 111, 119, 110, 70, 105, 101, 108,
100, 115, 116, 0, 37, 76, 99, 111, 109, 47, 103, 111, 111, 103, 108,
101, 47, 112, 114, 111, 116, 111, 98, 117, 102, 47, 85, 110, 107,
110, 111, 119, 110, 70, 105, 101, 108, 100, 83, 101, 116, 59, 120,
112, 116, 0, 30, 99, 111, 109, 46, 103, 111, 111, 103, 108, 101, 46,
112, 114, 111, 116, 111, 98, 117, 102, 46, 73, 110, 116, 51, 50, 86,
97, 108, 117, 101
};
ByteArrayInputStream bais = new ByteArrayInputStream(int32ValueBytes);
ObjectInputStream in = new ObjectInputStream(bais);
Int32Value int32Value = (Int32Value) in.readObject();
assertEquals(123, int32Value.getValue());
}
public void testEnumValues() { public void testEnumValues() {
assertEquals(TestAllTypes.NestedEnum.BAR_VALUE, TestAllTypes.NestedEnum.BAR.getNumber()); assertEquals(TestAllTypes.NestedEnum.BAR_VALUE, TestAllTypes.NestedEnum.BAR.getNumber());
assertEquals(TestAllTypes.NestedEnum.BAZ_VALUE, TestAllTypes.NestedEnum.BAZ.getNumber()); assertEquals(TestAllTypes.NestedEnum.BAZ_VALUE, TestAllTypes.NestedEnum.BAZ.getNumber());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment