diff options
Diffstat (limited to 'java')
-rw-r--r-- | java/core/pom.xml | 2 | ||||
-rw-r--r-- | java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java | 16 | ||||
-rw-r--r-- | java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java | 70 | ||||
-rw-r--r-- | java/pom.xml | 4 | ||||
-rw-r--r-- | java/util/pom.xml | 2 | ||||
-rw-r--r-- | java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java | 2 | ||||
-rw-r--r-- | java/util/src/main/java/com/google/protobuf/util/JsonFormat.java | 17 | ||||
-rw-r--r-- | java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java | 51 |
8 files changed, 150 insertions, 14 deletions
diff --git a/java/core/pom.xml b/java/core/pom.xml index a7d4ea37..0c0fd8ff 100644 --- a/java/core/pom.xml +++ b/java/core/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-parent</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> </parent> <artifactId>protobuf-java</artifactId> diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java index 35b31f15..ff670fd8 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java @@ -1406,7 +1406,7 @@ public abstract class GeneratedMessageLite< /** * 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 { @@ -1416,6 +1416,9 @@ public abstract class GeneratedMessageLite< 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 byte[] asBytes; @@ -1424,7 +1427,8 @@ public abstract class GeneratedMessageLite< * @param regularForm the message to serialize */ SerializedForm(MessageLite regularForm) { - messageClassName = regularForm.getClass().getName(); + messageClass = regularForm.getClass(); + messageClassName = messageClass.getName(); asBytes = regularForm.toByteArray(); } @@ -1436,7 +1440,7 @@ public abstract class GeneratedMessageLite< @SuppressWarnings("unchecked") protected Object readResolve() throws ObjectStreamException { try { - Class<?> messageClass = Class.forName(messageClassName); + Class<?> messageClass = resolveMessageClass(); java.lang.reflect.Field defaultInstanceField = messageClass.getDeclaredField("DEFAULT_INSTANCE"); defaultInstanceField.setAccessible(true); @@ -1463,7 +1467,7 @@ public abstract class GeneratedMessageLite< @Deprecated private Object readResolveFallback() throws ObjectStreamException { try { - Class<?> messageClass = Class.forName(messageClassName); + Class<?> messageClass = resolveMessageClass(); java.lang.reflect.Field defaultInstanceField = messageClass.getDeclaredField("defaultInstance"); defaultInstanceField.setAccessible(true); @@ -1483,6 +1487,10 @@ public abstract class GeneratedMessageLite< throw new RuntimeException("Unable to understand proto buffer", e); } } + + private Class<?> resolveMessageClass() throws ClassNotFoundException { + return messageClass != null ? messageClass : Class.forName(messageClassName); + } } /** diff --git a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java index a4143cd4..4489dace 100644 --- a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java +++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java @@ -32,6 +32,7 @@ package com.google.protobuf; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.Int32Value; import com.google.protobuf.test.UnittestImport; import protobuf_unittest.EnumWithNoOuter; import protobuf_unittest.MessageWithNoOuter; @@ -853,6 +854,75 @@ public class GeneratedMessageTest extends TestCase { 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() { assertEquals(TestAllTypes.NestedEnum.BAR_VALUE, TestAllTypes.NestedEnum.BAR.getNumber()); assertEquals(TestAllTypes.NestedEnum.BAZ_VALUE, TestAllTypes.NestedEnum.BAZ.getNumber()); diff --git a/java/pom.xml b/java/pom.xml index 35d653b4..6526b650 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -11,7 +11,7 @@ <groupId>com.google.protobuf</groupId> <artifactId>protobuf-parent</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> <packaging>pom</packaging> <name>Protocol Buffers [Parent]</name> @@ -92,7 +92,7 @@ <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> <configuration> <source>1.7</source> <target>1.7</target> diff --git a/java/util/pom.xml b/java/util/pom.xml index 8ea4a40d..f175cf15 100644 --- a/java/util/pom.xml +++ b/java/util/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-parent</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> </parent> <artifactId>protobuf-java-util</artifactId> diff --git a/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java b/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java index 7b4facc1..86f56ad9 100644 --- a/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java +++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java @@ -240,7 +240,7 @@ final class FieldMaskTree { "Field \"" + field.getFullName() + "\" is not a " - + "singluar message field and cannot have sub-fields."); + + "singular message field and cannot have sub-fields."); continue; } if (!source.hasField(field) && !destination.hasField(field)) { diff --git a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java index 973f1517..955dfd86 100644 --- a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java +++ b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java @@ -50,6 +50,7 @@ import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.EnumDescriptor; import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.Descriptors.FieldDescriptor.Type; import com.google.protobuf.Descriptors.FileDescriptor; import com.google.protobuf.Descriptors.OneofDescriptor; import com.google.protobuf.DoubleValue; @@ -1539,7 +1540,11 @@ public class JsonFormat { Object key = parseFieldValue(keyField, new JsonPrimitive(entry.getKey()), entryBuilder); Object value = parseFieldValue(valueField, entry.getValue(), entryBuilder); if (value == null) { - throw new InvalidProtocolBufferException("Map value cannot be null."); + if(ignoringUnknownFields && valueField.getType() == Type.ENUM) { + continue; + } else { + throw new InvalidProtocolBufferException("Map value cannot be null."); + } } entryBuilder.setField(keyField, key); entryBuilder.setField(valueField, value); @@ -1557,8 +1562,12 @@ public class JsonFormat { for (int i = 0; i < array.size(); ++i) { Object value = parseFieldValue(field, array.get(i), builder); if (value == null) { - throw new InvalidProtocolBufferException( - "Repeated field elements cannot be null in field: " + field.getFullName()); + if(ignoringUnknownFields && field.getType() == Type.ENUM) { + continue; + } else { + throw new InvalidProtocolBufferException( + "Repeated field elements cannot be null in field: " + field.getFullName()); + } } builder.addRepeatedField(field, value); } @@ -1748,7 +1757,7 @@ public class JsonFormat { // an exception later. } - if (result == null) { + if (result == null && !ignoringUnknownFields) { throw new InvalidProtocolBufferException( "Invalid enum value: " + value + " for enum type: " + enumDescriptor.getFullName()); } diff --git a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java index d9bbe587..7637c267 100644 --- a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java +++ b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java @@ -161,6 +161,10 @@ public class JsonFormatTest extends TestCase { JsonFormat.parser().merge(json, builder); } + private void mergeFromJsonIgnoringUnknownFields(String json, Message.Builder builder) throws IOException { + JsonFormat.parser().ignoringUnknownFields().merge(json, builder); + } + public void testAllFields() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); setAllFields(builder); @@ -668,10 +672,22 @@ public class JsonFormatTest extends TestCase { + "}", builder); fail(); + } catch (InvalidProtocolBufferException e) { // Exception expected. } } + + public void testMapEnumNullValueIsIgnored() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + mergeFromJsonIgnoringUnknownFields( + "{\n" + + " \"int32ToEnumMap\": {\"1\": null}\n" + + "}", + builder); + TestMap map = builder.build(); + assertEquals(0, map.getInt32ToEnumMapMap().entrySet().size()); + } public void testParserAcceptNonQuotedObjectKey() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); @@ -1172,7 +1188,40 @@ public class JsonFormatTest extends TestCase { String json = "{\n" + " \"unknownField\": \"XXX\"\n" + "}"; JsonFormat.parser().ignoringUnknownFields().merge(json, builder); } - + + public void testParserIgnoringUnknownEnums() throws Exception { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + String json = "{\n" + " \"optionalNestedEnum\": \"XXX\"\n" + "}"; + JsonFormat.parser().ignoringUnknownFields().merge(json, builder); + assertEquals(0, builder.getOptionalNestedEnumValue()); + } + + public void testUnknownEnumMap() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + JsonFormat.parser().ignoringUnknownFields().merge( + "{\n" + + " \"int32ToEnumMap\": {1: XXX, 2: FOO}" + + "}", + builder); + + assertEquals(NestedEnum.FOO, builder.getInt32ToEnumMapMap().get(2)); + assertEquals(1, builder.getInt32ToEnumMapMap().size()); + } + + public void testRepeatedUnknownEnum() throws Exception { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + JsonFormat.parser().ignoringUnknownFields().merge( + "{\n" + + " \"repeatedNestedEnum\": [XXX, FOO, BAR, BAZ]" + + "}", + builder); + + assertEquals(NestedEnum.FOO, builder.getRepeatedNestedEnum(0)); + assertEquals(NestedEnum.BAR, builder.getRepeatedNestedEnum(1)); + assertEquals(NestedEnum.BAZ, builder.getRepeatedNestedEnum(2)); + assertEquals(3, builder.getRepeatedNestedEnumList().size()); + } + public void testParserIntegerEnumValue() throws Exception { TestAllTypes.Builder actualBuilder = TestAllTypes.newBuilder(); mergeFromJson("{\n" + " \"optionalNestedEnum\": 2\n" + "}", actualBuilder); |