Browse Source

Merge pull request #1467 from pherl/master

Merge Google internal changes
Jisi Liu 9 năm trước cách đây
mục cha
commit
09f1757cf5
100 tập tin đã thay đổi với 6378 bổ sung2112 xóa
  1. 1 1
      BUILD
  2. 5 0
      cmake/tests.cmake
  3. 2 0
      csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
  4. 1 1
      csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs
  5. 34 14
      java/core/src/main/java/com/google/protobuf/AbstractMessage.java
  6. 51 28
      java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
  7. 45 40
      java/core/src/main/java/com/google/protobuf/AbstractParser.java
  8. 46 2
      java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java
  9. 44 25
      java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
  10. 258 456
      java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
  11. 145 36
      java/core/src/main/java/com/google/protobuf/Descriptors.java
  12. 43 22
      java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
  13. 36 4
      java/core/src/main/java/com/google/protobuf/DynamicMessage.java
  14. 1 0
      java/core/src/main/java/com/google/protobuf/Extension.java
  15. 19 0
      java/core/src/main/java/com/google/protobuf/FieldSet.java
  16. 42 22
      java/core/src/main/java/com/google/protobuf/FloatArrayList.java
  17. 152 103
      java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
  18. 926 141
      java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
  19. 42 22
      java/core/src/main/java/com/google/protobuf/IntArrayList.java
  20. 52 11
      java/core/src/main/java/com/google/protobuf/Internal.java
  21. 6 6
      java/core/src/main/java/com/google/protobuf/LazyField.java
  22. 41 0
      java/core/src/main/java/com/google/protobuf/LazyFieldLite.java
  23. 31 17
      java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java
  24. 42 22
      java/core/src/main/java/com/google/protobuf/LongArrayList.java
  25. 8 2
      java/core/src/main/java/com/google/protobuf/MapEntryLite.java
  26. 3 0
      java/core/src/main/java/com/google/protobuf/MapField.java
  27. 48 22
      java/core/src/main/java/com/google/protobuf/Message.java
  28. 21 0
      java/core/src/main/java/com/google/protobuf/MessageLite.java
  29. 95 56
      java/core/src/main/java/com/google/protobuf/MessageLiteToString.java
  30. 1 1
      java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java
  31. 74 33
      java/core/src/main/java/com/google/protobuf/MessageReflection.java
  32. 14 8
      java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java
  33. 1 0
      java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java
  34. 7 1
      java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
  35. 3 1
      java/core/src/main/java/com/google/protobuf/RpcUtil.java
  36. 1 1
      java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
  37. 79 27
      java/core/src/main/java/com/google/protobuf/SmallSortedMap.java
  38. 2 0
      java/core/src/main/java/com/google/protobuf/TextFormat.java
  39. 51 26
      java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
  40. 25 25
      java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
  41. 15 4
      java/core/src/main/java/com/google/protobuf/WireFormat.java
  42. 33 8
      java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
  43. 0 14
      java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java
  44. 2 0
      java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
  45. 503 273
      java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
  46. 0 14
      java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java
  47. 0 14
      java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java
  48. 1 1
      java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java
  49. 4 4
      java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
  50. 0 14
      java/core/src/test/java/com/google/protobuf/IntArrayListTest.java
  51. 660 32
      java/core/src/test/java/com/google/protobuf/LiteTest.java
  52. 0 14
      java/core/src/test/java/com/google/protobuf/LongArrayListTest.java
  53. 8 8
      java/core/src/test/java/com/google/protobuf/ParserTest.java
  54. 0 14
      java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java
  55. 13 7
      java/core/src/test/java/com/google/protobuf/ServiceTest.java
  56. 3 0
      java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java
  57. 2 407
      java/core/src/test/java/com/google/protobuf/TestUtil.java
  58. 559 0
      java/core/src/test/java/com/google/protobuf/TestUtilLite.java
  59. 4 1
      java/core/src/test/java/com/google/protobuf/TextFormatTest.java
  60. 1 0
      java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
  61. 5 5
      java/core/src/test/java/com/google/protobuf/WireFormatTest.java
  62. 0 3
      java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto
  63. 20 0
      java/lite/generate-sources-build.xml
  64. 43 0
      java/lite/generate-test-sources-build.xml
  65. 4 4
      java/lite/pom.xml
  66. 2 0
      java/pom.xml
  67. 553 0
      java/src/main/java/com/google/protobuf/AbstractMessage.java
  68. 386 0
      java/src/main/java/com/google/protobuf/AbstractMessageLite.java
  69. 258 0
      java/src/main/java/com/google/protobuf/AbstractParser.java
  70. 180 0
      java/src/main/java/com/google/protobuf/AbstractProtobufList.java
  71. 51 0
      java/src/main/java/com/google/protobuf/BlockingRpcChannel.java
  72. 64 0
      java/src/main/java/com/google/protobuf/BlockingService.java
  73. 5 1
      java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
  74. 37 8
      java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
  75. 20 0
      java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java
  76. 9 0
      java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java
  77. 50 0
      js/binary/utils.js
  78. 35 0
      js/binary/utils_test.js
  79. 2 0
      objectivec/google/protobuf/Any.pbobjc.h
  80. 1 1
      objectivec/google/protobuf/FieldMask.pbobjc.h
  81. 4 0
      php/tests/autoload.php
  82. 7 2
      python/google/protobuf/descriptor.py
  83. 3 1
      python/google/protobuf/descriptor_pool.py
  84. 6 0
      python/google/protobuf/internal/api_implementation.py
  85. 16 30
      python/google/protobuf/internal/descriptor_pool_test.py
  86. 1 0
      python/google/protobuf/internal/descriptor_pool_test2.proto
  87. 54 0
      python/google/protobuf/internal/message_factory_test.py
  88. 30 4
      python/google/protobuf/internal/message_test.py
  89. 1 0
      python/google/protobuf/internal/proto_builder_test.py
  90. 52 24
      python/google/protobuf/internal/python_message.py
  91. 9 3
      python/google/protobuf/internal/reflection_test.py
  92. 93 0
      python/google/protobuf/internal/text_format_test.py
  93. 17 6
      python/google/protobuf/internal/type_checkers.py
  94. 20 0
      python/google/protobuf/internal/unknown_fields_test.py
  95. 6 2
      python/google/protobuf/internal/well_known_types.py
  96. 8 0
      python/google/protobuf/internal/well_known_types_test.py
  97. 3 0
      python/google/protobuf/message.py
  98. 6 5
      python/google/protobuf/pyext/descriptor.cc
  99. 4 4
      python/google/protobuf/pyext/descriptor_pool.cc
  100. 7 4
      python/google/protobuf/pyext/descriptor_pool.h

+ 1 - 1
BUILD

@@ -464,8 +464,8 @@ cc_test(
         "src/google/protobuf/message_unittest.cc",
         "src/google/protobuf/no_field_presence_test.cc",
         "src/google/protobuf/preserve_unknown_enum_test.cc",
-        "src/google/protobuf/proto3_arena_unittest.cc",
         "src/google/protobuf/proto3_arena_lite_unittest.cc",
+        "src/google/protobuf/proto3_arena_unittest.cc",
         "src/google/protobuf/proto3_lite_unittest.cc",
         "src/google/protobuf/reflection_ops_unittest.cc",
         "src/google/protobuf/repeated_field_reflection_unittest.cc",

+ 5 - 0
cmake/tests.cmake

@@ -52,6 +52,8 @@ set(tests_protos
   google/protobuf/unittest_preserve_unknown_enum.proto
   google/protobuf/unittest_preserve_unknown_enum2.proto
   google/protobuf/unittest_proto3_arena.proto
+  google/protobuf/unittest_proto3_arena_lite.proto
+  google/protobuf/unittest_proto3_lite.proto
   google/protobuf/unittest_well_known_types.proto
   google/protobuf/util/internal/testdata/anys.proto
   google/protobuf/util/internal/testdata/books.proto
@@ -116,6 +118,7 @@ set(tests_files
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/metadata_test.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/importer_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc
@@ -140,7 +143,9 @@ set(tests_files
   ${protobuf_source_dir}/src/google/protobuf/message_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/no_field_presence_test.cc
   ${protobuf_source_dir}/src/google/protobuf/preserve_unknown_enum_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/proto3_arena_lite_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/proto3_arena_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/proto3_lite_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/reflection_ops_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/repeated_field_reflection_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/repeated_field_unittest.cc

+ 2 - 0
csharp/src/Google.Protobuf/WellKnownTypes/Any.cs

@@ -139,6 +139,8 @@ namespace Google.Protobuf.WellKnownTypes {
     ///  * If no schema is provided, `https` is assumed.
     ///  * The last segment of the URL's path must represent the fully
     ///    qualified name of the type (as in `path/google.protobuf.Duration`).
+    ///    The name should be in a canonical form (e.g., leading "." is
+    ///    not accepted).
     ///  * An HTTP GET on the URL must yield a [google.protobuf.Type][]
     ///    value in binary format, or produce an error.
     ///  * Applications are allowed to cache lookup results based on the

+ 1 - 1
csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs

@@ -86,7 +86,7 @@ namespace Google.Protobuf.WellKnownTypes {
   ///  operation applies to all fields (as if a FieldMask of all fields
   ///  had been specified).
   ///
-  ///  Note that a field mask does not necessarily applies to the
+  ///  Note that a field mask does not necessarily apply to the
   ///  top-level response message. In case of a REST get operation, the
   ///  field mask applies directly to the response, but in case of a REST
   ///  list operation, the mask instead applies to each individual message

+ 34 - 14
java/core/src/main/java/com/google/protobuf/AbstractMessage.java

@@ -50,17 +50,23 @@ import java.util.Map;
  *
  * @author kenton@google.com Kenton Varda
  */
-public abstract class AbstractMessage extends AbstractMessageLite
-                                      implements Message {
+public abstract class AbstractMessage
+    // TODO(dweis): Update GeneratedMessage to parameterize with MessageType and BuilderType.
+    extends AbstractMessageLite
+    implements Message {
+  
+  @Override
   public boolean isInitialized() {
     return MessageReflection.isInitialized(this);
   }
 
 
+  @Override
   public List<String> findInitializationErrors() {
     return MessageReflection.findMissingFields(this);
   }
 
+  @Override
   public String getInitializationErrorString() {
     return MessageReflection.delimitWithCommas(findInitializationErrors());
   }
@@ -83,12 +89,14 @@ public abstract class AbstractMessage extends AbstractMessageLite
     return TextFormat.printToString(this);
   }
 
+  @Override
   public void writeTo(final CodedOutputStream output) throws IOException {
     MessageReflection.writeMessageTo(this, getAllFields(), output, false);
   }
 
   protected int memoizedSize = -1;
 
+  @Override
   public int getSerializedSize() {
     int size = memoizedSize;
     if (size != -1) {
@@ -288,8 +296,8 @@ public abstract class AbstractMessage extends AbstractMessageLite
    * other methods.
    */
   @SuppressWarnings("unchecked")
-  public static abstract class Builder<BuilderType extends Builder>
-      extends AbstractMessageLite.Builder<BuilderType>
+  public static abstract class Builder<BuilderType extends Builder<BuilderType>>
+      extends AbstractMessageLite.Builder
       implements Message.Builder {
     // The compiler produces an error if this is not declared explicitly.
     @Override
@@ -314,6 +322,7 @@ public abstract class AbstractMessage extends AbstractMessageLite
       throw new UnsupportedOperationException("clearOneof() is not implemented.");
     }
 
+    @Override
     public BuilderType clear() {
       for (final Map.Entry<FieldDescriptor, Object> entry :
            getAllFields().entrySet()) {
@@ -322,14 +331,22 @@ public abstract class AbstractMessage extends AbstractMessageLite
       return (BuilderType) this;
     }
 
+    @Override
     public List<String> findInitializationErrors() {
       return MessageReflection.findMissingFields(this);
     }
 
+    @Override
     public String getInitializationErrorString() {
       return MessageReflection.delimitWithCommas(findInitializationErrors());
     }
+    
+    @Override
+    protected BuilderType internalMergeFrom(AbstractMessageLite other) {
+      return mergeFrom((Message) other);
+    }
 
+    @Override
     public BuilderType mergeFrom(final Message other) {
       if (other.getDescriptorForType() != getDescriptorForType()) {
         throw new IllegalArgumentException(
@@ -407,6 +424,7 @@ public abstract class AbstractMessage extends AbstractMessageLite
       return (BuilderType) this;
     }
 
+    @Override
     public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
       setUnknownFields(
         UnknownFieldSet.newBuilder(getUnknownFields())
@@ -415,17 +433,19 @@ public abstract class AbstractMessage extends AbstractMessageLite
       return (BuilderType) this;
     }
 
+    @Override
     public Message.Builder getFieldBuilder(final FieldDescriptor field) {
       throw new UnsupportedOperationException(
           "getFieldBuilder() called on an unsupported message type.");
     }
 
-    public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field,
-        int index) {
+    @Override
+    public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) {
       throw new UnsupportedOperationException(
           "getRepeatedFieldBuilder() called on an unsupported message type.");
     }
 
+    @Override
     public String toString() {
       return TextFormat.printToString(this);
     }
@@ -462,7 +482,7 @@ public abstract class AbstractMessage extends AbstractMessageLite
     @Override
     public BuilderType mergeFrom(final ByteString data)
         throws InvalidProtocolBufferException {
-      return super.mergeFrom(data);
+      return (BuilderType) super.mergeFrom(data);
     }
 
     @Override
@@ -470,20 +490,20 @@ public abstract class AbstractMessage extends AbstractMessageLite
         final ByteString data,
         final ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException {
-      return super.mergeFrom(data, extensionRegistry);
+      return (BuilderType) super.mergeFrom(data, extensionRegistry);
     }
 
     @Override
     public BuilderType mergeFrom(final byte[] data)
         throws InvalidProtocolBufferException {
-      return super.mergeFrom(data);
+      return (BuilderType) super.mergeFrom(data);
     }
 
     @Override
     public BuilderType mergeFrom(
         final byte[] data, final int off, final int len)
         throws InvalidProtocolBufferException {
-      return super.mergeFrom(data, off, len);
+      return (BuilderType) super.mergeFrom(data, off, len);
     }
 
     @Override
@@ -491,7 +511,7 @@ public abstract class AbstractMessage extends AbstractMessageLite
         final byte[] data,
         final ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException {
-      return super.mergeFrom(data, extensionRegistry);
+      return (BuilderType) super.mergeFrom(data, extensionRegistry);
     }
 
     @Override
@@ -499,13 +519,13 @@ public abstract class AbstractMessage extends AbstractMessageLite
         final byte[] data, final int off, final int len,
         final ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException {
-      return super.mergeFrom(data, off, len, extensionRegistry);
+      return (BuilderType) super.mergeFrom(data, off, len, extensionRegistry);
     }
 
     @Override
     public BuilderType mergeFrom(final InputStream input)
         throws IOException {
-      return super.mergeFrom(input);
+      return (BuilderType) super.mergeFrom(input);
     }
 
     @Override
@@ -513,7 +533,7 @@ public abstract class AbstractMessage extends AbstractMessageLite
         final InputStream input,
         final ExtensionRegistryLite extensionRegistry)
         throws IOException {
-      return super.mergeFrom(input, extensionRegistry);
+      return (BuilderType) super.mergeFrom(input, extensionRegistry);
     }
 
     @Override

+ 51 - 28
java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java

@@ -43,9 +43,13 @@ import java.util.Collection;
  *
  * @author kenton@google.com Kenton Varda
  */
-public abstract class AbstractMessageLite implements MessageLite {
+public abstract class AbstractMessageLite<
+    MessageType extends AbstractMessageLite<MessageType, BuilderType>,
+    BuilderType extends AbstractMessageLite.Builder<MessageType, BuilderType>> 
+        implements MessageLite {
   protected int memoizedHashCode = 0;
-
+  
+  @Override
   public ByteString toByteString() {
     try {
       final ByteString.CodedBuilder out =
@@ -59,6 +63,7 @@ public abstract class AbstractMessageLite implements MessageLite {
     }
   }
 
+  @Override
   public byte[] toByteArray() {
     try {
       final byte[] result = new byte[getSerializedSize()];
@@ -73,6 +78,7 @@ public abstract class AbstractMessageLite implements MessageLite {
     }
   }
 
+  @Override
   public void writeTo(final OutputStream output) throws IOException {
     final int bufferSize =
         CodedOutputStream.computePreferredBufferSize(getSerializedSize());
@@ -82,6 +88,7 @@ public abstract class AbstractMessageLite implements MessageLite {
     codedOutput.flush();
   }
 
+  @Override
   public void writeDelimitedTo(final OutputStream output) throws IOException {
     final int serialized = getSerializedSize();
     final int bufferSize = CodedOutputStream.computePreferredBufferSize(
@@ -120,25 +127,27 @@ public abstract class AbstractMessageLite implements MessageLite {
    * other methods.
    */
   @SuppressWarnings("unchecked")
-  public static abstract class Builder<BuilderType extends Builder>
+  public abstract static class Builder<
+      MessageType extends AbstractMessageLite<MessageType, BuilderType>,
+      BuilderType extends Builder<MessageType, BuilderType>>
       implements MessageLite.Builder {
     // The compiler produces an error if this is not declared explicitly.
     @Override
     public abstract BuilderType clone();
 
-    public BuilderType mergeFrom(final CodedInputStream input)
-                                 throws IOException {
+    @Override
+    public BuilderType mergeFrom(final CodedInputStream input) throws IOException {
       return mergeFrom(input, ExtensionRegistryLite.getEmptyRegistry());
     }
 
     // Re-defined here for return type covariance.
+    @Override
     public abstract BuilderType mergeFrom(
-        final CodedInputStream input,
-        final ExtensionRegistryLite extensionRegistry)
+        final CodedInputStream input, final ExtensionRegistryLite extensionRegistry)
         throws IOException;
 
-    public BuilderType mergeFrom(final ByteString data)
-        throws InvalidProtocolBufferException {
+    @Override
+    public BuilderType mergeFrom(final ByteString data) throws InvalidProtocolBufferException {
       try {
         final CodedInputStream input = data.newCodedInput();
         mergeFrom(input);
@@ -153,9 +162,9 @@ public abstract class AbstractMessageLite implements MessageLite {
       }
     }
 
+    @Override
     public BuilderType mergeFrom(
-        final ByteString data,
-        final ExtensionRegistryLite extensionRegistry)
+        final ByteString data, final ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException {
       try {
         final CodedInputStream input = data.newCodedInput();
@@ -171,14 +180,14 @@ public abstract class AbstractMessageLite implements MessageLite {
       }
     }
 
-    public BuilderType mergeFrom(final byte[] data)
-        throws InvalidProtocolBufferException {
+    @Override
+    public BuilderType mergeFrom(final byte[] data) throws InvalidProtocolBufferException {
       return mergeFrom(data, 0, data.length);
     }
 
-    public BuilderType mergeFrom(final byte[] data, final int off,
-                                 final int len)
-                                 throws InvalidProtocolBufferException {
+    @Override
+    public BuilderType mergeFrom(final byte[] data, final int off, final int len)
+        throws InvalidProtocolBufferException {
       try {
         final CodedInputStream input =
             CodedInputStream.newInstance(data, off, len);
@@ -194,15 +203,17 @@ public abstract class AbstractMessageLite implements MessageLite {
       }
     }
 
-    public BuilderType mergeFrom(
-        final byte[] data,
-        final ExtensionRegistryLite extensionRegistry)
+    @Override
+    public BuilderType mergeFrom(final byte[] data, final ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException {
       return mergeFrom(data, 0, data.length, extensionRegistry);
     }
 
+    @Override
     public BuilderType mergeFrom(
-        final byte[] data, final int off, final int len,
+        final byte[] data,
+        final int off,
+        final int len,
         final ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException {
       try {
@@ -220,6 +231,7 @@ public abstract class AbstractMessageLite implements MessageLite {
       }
     }
 
+    @Override
     public BuilderType mergeFrom(final InputStream input) throws IOException {
       final CodedInputStream codedInput = CodedInputStream.newInstance(input);
       mergeFrom(codedInput);
@@ -227,10 +239,9 @@ public abstract class AbstractMessageLite implements MessageLite {
       return (BuilderType) this;
     }
 
+    @Override
     public BuilderType mergeFrom(
-        final InputStream input,
-        final ExtensionRegistryLite extensionRegistry)
-        throws IOException {
+        final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
       final CodedInputStream codedInput = CodedInputStream.newInstance(input);
       mergeFrom(codedInput, extensionRegistry);
       codedInput.checkLastTagWas(0);
@@ -292,10 +303,9 @@ public abstract class AbstractMessageLite implements MessageLite {
       }
     }
 
+    @Override
     public boolean mergeDelimitedFrom(
-        final InputStream input,
-        final ExtensionRegistryLite extensionRegistry)
-        throws IOException {
+        final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
       final int firstByte = input.read();
       if (firstByte == -1) {
         return false;
@@ -306,11 +316,24 @@ public abstract class AbstractMessageLite implements MessageLite {
       return true;
     }
 
-    public boolean mergeDelimitedFrom(final InputStream input)
-        throws IOException {
+    @Override
+    public boolean mergeDelimitedFrom(final InputStream input) throws IOException {
       return mergeDelimitedFrom(input,
           ExtensionRegistryLite.getEmptyRegistry());
     }
+    
+    @Override
+    @SuppressWarnings("unchecked") // isInstance takes care of this
+    public BuilderType mergeFrom(final MessageLite other) {
+      if (!getDefaultInstanceForType().getClass().isInstance(other)) {
+        throw new IllegalArgumentException(
+            "mergeFrom(MessageLite) can only merge messages of the same type.");
+      }
+        
+      return internalMergeFrom((MessageType) other);
+    }
+    
+    protected abstract BuilderType internalMergeFrom(MessageType message);
 
     /**
      * Construct an UninitializedMessageException reporting missing fields in

+ 45 - 40
java/core/src/main/java/com/google/protobuf/AbstractParser.java

@@ -78,26 +78,27 @@ public abstract class AbstractParser<MessageType extends MessageLite>
   private static final ExtensionRegistryLite EMPTY_REGISTRY
       = ExtensionRegistryLite.getEmptyRegistry();
 
+  @Override
   public MessageType parsePartialFrom(CodedInputStream input)
       throws InvalidProtocolBufferException {
     return parsePartialFrom(input, EMPTY_REGISTRY);
   }
 
-  public MessageType parseFrom(CodedInputStream input,
-                               ExtensionRegistryLite extensionRegistry)
+  @Override
+  public MessageType parseFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
       throws InvalidProtocolBufferException {
     return checkMessageInitialized(
         parsePartialFrom(input, extensionRegistry));
   }
 
-  public MessageType parseFrom(CodedInputStream input)
-      throws InvalidProtocolBufferException {
+  @Override
+  public MessageType parseFrom(CodedInputStream input) throws InvalidProtocolBufferException {
     return parseFrom(input, EMPTY_REGISTRY);
   }
 
-  public MessageType parsePartialFrom(ByteString data,
-                                      ExtensionRegistryLite extensionRegistry)
-    throws InvalidProtocolBufferException {
+  @Override
+  public MessageType parsePartialFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
     MessageType message;
     try {
       CodedInputStream input = data.newCodedInput();
@@ -113,24 +114,25 @@ public abstract class AbstractParser<MessageType extends MessageLite>
     }
   }
 
-  public MessageType parsePartialFrom(ByteString data)
-      throws InvalidProtocolBufferException {
+  @Override
+  public MessageType parsePartialFrom(ByteString data) throws InvalidProtocolBufferException {
     return parsePartialFrom(data, EMPTY_REGISTRY);
   }
 
-  public MessageType parseFrom(ByteString data,
-                               ExtensionRegistryLite extensionRegistry)
+  @Override
+  public MessageType parseFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
       throws InvalidProtocolBufferException {
     return checkMessageInitialized(parsePartialFrom(data, extensionRegistry));
   }
 
-  public MessageType parseFrom(ByteString data)
-      throws InvalidProtocolBufferException {
+  @Override
+  public MessageType parseFrom(ByteString data) throws InvalidProtocolBufferException {
     return parseFrom(data, EMPTY_REGISTRY);
   }
 
-  public MessageType parsePartialFrom(byte[] data, int off, int len,
-                                      ExtensionRegistryLite extensionRegistry)
+  @Override
+  public MessageType parsePartialFrom(
+      byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
       throws InvalidProtocolBufferException {
     try {
       CodedInputStream input = CodedInputStream.newInstance(data, off, len);
@@ -146,47 +148,50 @@ public abstract class AbstractParser<MessageType extends MessageLite>
     }
   }
 
+  @Override
   public MessageType parsePartialFrom(byte[] data, int off, int len)
       throws InvalidProtocolBufferException {
     return parsePartialFrom(data, off, len, EMPTY_REGISTRY);
   }
 
-  public MessageType parsePartialFrom(byte[] data,
-                                      ExtensionRegistryLite extensionRegistry)
+  @Override
+  public MessageType parsePartialFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
       throws InvalidProtocolBufferException {
     return parsePartialFrom(data, 0, data.length, extensionRegistry);
   }
 
-  public MessageType parsePartialFrom(byte[] data)
-      throws InvalidProtocolBufferException {
+  @Override
+  public MessageType parsePartialFrom(byte[] data) throws InvalidProtocolBufferException {
     return parsePartialFrom(data, 0, data.length, EMPTY_REGISTRY);
   }
 
-  public MessageType parseFrom(byte[] data, int off, int len,
-                               ExtensionRegistryLite extensionRegistry)
+  @Override
+  public MessageType parseFrom(
+      byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
       throws InvalidProtocolBufferException {
     return checkMessageInitialized(
         parsePartialFrom(data, off, len, extensionRegistry));
   }
 
+  @Override
   public MessageType parseFrom(byte[] data, int off, int len)
       throws InvalidProtocolBufferException {
     return parseFrom(data, off, len, EMPTY_REGISTRY);
   }
 
-  public MessageType parseFrom(byte[] data,
-                               ExtensionRegistryLite extensionRegistry)
+  @Override
+  public MessageType parseFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
       throws InvalidProtocolBufferException {
     return parseFrom(data, 0, data.length, extensionRegistry);
   }
 
-  public MessageType parseFrom(byte[] data)
-      throws InvalidProtocolBufferException {
+  @Override
+  public MessageType parseFrom(byte[] data) throws InvalidProtocolBufferException {
     return parseFrom(data, EMPTY_REGISTRY);
   }
 
-  public MessageType parsePartialFrom(InputStream input,
-                                      ExtensionRegistryLite extensionRegistry)
+  @Override
+  public MessageType parsePartialFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
       throws InvalidProtocolBufferException {
     CodedInputStream codedInput = CodedInputStream.newInstance(input);
     MessageType message = parsePartialFrom(codedInput, extensionRegistry);
@@ -198,26 +203,26 @@ public abstract class AbstractParser<MessageType extends MessageLite>
     return message;
   }
 
-  public MessageType parsePartialFrom(InputStream input)
-      throws InvalidProtocolBufferException {
+  @Override
+  public MessageType parsePartialFrom(InputStream input) throws InvalidProtocolBufferException {
     return parsePartialFrom(input, EMPTY_REGISTRY);
   }
 
-  public MessageType parseFrom(InputStream input,
-                               ExtensionRegistryLite extensionRegistry)
+  @Override
+  public MessageType parseFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
       throws InvalidProtocolBufferException {
     return checkMessageInitialized(
         parsePartialFrom(input, extensionRegistry));
   }
 
-  public MessageType parseFrom(InputStream input)
-      throws InvalidProtocolBufferException {
+  @Override
+  public MessageType parseFrom(InputStream input) throws InvalidProtocolBufferException {
     return parseFrom(input, EMPTY_REGISTRY);
   }
 
+  @Override
   public MessageType parsePartialDelimitedFrom(
-      InputStream input,
-      ExtensionRegistryLite extensionRegistry)
+      InputStream input, ExtensionRegistryLite extensionRegistry)
       throws InvalidProtocolBufferException {
     int size;
     try {
@@ -233,21 +238,21 @@ public abstract class AbstractParser<MessageType extends MessageLite>
     return parsePartialFrom(limitedInput, extensionRegistry);
   }
 
+  @Override
   public MessageType parsePartialDelimitedFrom(InputStream input)
       throws InvalidProtocolBufferException {
     return parsePartialDelimitedFrom(input, EMPTY_REGISTRY);
   }
 
-  public MessageType parseDelimitedFrom(
-      InputStream input,
-      ExtensionRegistryLite extensionRegistry)
+  @Override
+  public MessageType parseDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
       throws InvalidProtocolBufferException {
     return checkMessageInitialized(
         parsePartialDelimitedFrom(input, extensionRegistry));
   }
 
-  public MessageType parseDelimitedFrom(InputStream input)
-      throws InvalidProtocolBufferException {
+  @Override
+  public MessageType parseDelimitedFrom(InputStream input) throws InvalidProtocolBufferException {
     return parseDelimitedFrom(input, EMPTY_REGISTRY);
   }
 }

+ 46 - 2
java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java

@@ -34,19 +34,25 @@ import com.google.protobuf.Internal.ProtobufList;
 
 import java.util.AbstractList;
 import java.util.Collection;
+import java.util.List;
+import java.util.RandomAccess;
 
 /**
  * An abstract implementation of {@link ProtobufList} which manages mutability semantics. All mutate
- * methods are check if the list is mutable before proceeding. Subclasses must invoke
+ * methods must check if the list is mutable before proceeding. Subclasses must invoke
  * {@link #ensureIsMutable()} manually when overriding those methods.
+ * <p>
+ * This implementation assumes all subclasses are array based, supporting random access.
  */
 abstract class AbstractProtobufList<E> extends AbstractList<E> implements ProtobufList<E> {
 
+  protected static final int DEFAULT_CAPACITY = 10;
+
   /**
    * Whether or not this list is modifiable.
    */
   private boolean isMutable;
-  
+
   /**
    * Constructs a mutable list by default.
    */
@@ -54,6 +60,44 @@ abstract class AbstractProtobufList<E> extends AbstractList<E> implements Protob
     isMutable = true;
   }
 
+  @Override
+  public boolean equals(Object o) {
+    if (o == this) {
+      return true;
+    }
+    if (!(o instanceof List)) {
+      return false;
+    }
+    // Handle lists that do not support RandomAccess as efficiently as possible by using an iterator
+    // based approach in our super class. Otherwise our index based approach will avoid those
+    // allocations.
+    if (!(o instanceof RandomAccess)) {
+      return super.equals(o);
+    }
+
+    List<?> other = (List<?>) o;
+    final int size = size();
+    if (size != other.size()) {
+      return false;
+    }
+    for (int i = 0; i < size; i++) {
+      if (!get(i).equals(other.get(i))) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    final int size = size();
+    int hashCode = 1;
+    for (int i = 0; i < size; i++) {
+      hashCode = (31 * hashCode) + get(i).hashCode();
+    }
+    return hashCode;
+  }
+
   @Override
   public boolean add(E e) {
     ensureIsMutable();

+ 44 - 25
java/core/src/main/java/com/google/protobuf/BooleanArrayList.java

@@ -34,7 +34,6 @@ import com.google.protobuf.Internal.BooleanList;
 
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.List;
 import java.util.RandomAccess;
 
 /**
@@ -45,8 +44,6 @@ import java.util.RandomAccess;
 final class BooleanArrayList
     extends AbstractProtobufList<Boolean> implements BooleanList, RandomAccess {
   
-  private static final int DEFAULT_CAPACITY = 10;
-  
   private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList();
   static {
     EMPTY_LIST.makeImmutable();
@@ -60,7 +57,7 @@ final class BooleanArrayList
    * The backing store for the list.
    */
   private boolean[] array;
-  
+
   /**
    * The size of the list distinct from the length of the array. That is, it is the number of
    * elements set in the list.
@@ -71,35 +68,57 @@ final class BooleanArrayList
    * Constructs a new mutable {@code BooleanArrayList} with default capacity.
    */
   BooleanArrayList() {
-    this(DEFAULT_CAPACITY);
+    this(new boolean[DEFAULT_CAPACITY], 0);
   }
 
   /**
-   * Constructs a new mutable {@code BooleanArrayList} with the provided capacity.
+   * Constructs a new mutable {@code BooleanArrayList}.
    */
-  BooleanArrayList(int capacity) {
-    array = new boolean[capacity];
-    size = 0;
+  private BooleanArrayList(boolean[] array, int size) {
+    this.array = array;
+    this.size = size;
   }
-
-  /**
-   * Constructs a new mutable {@code BooleanArrayList} containing the same elements as
-   * {@code other}.
-   */
-  BooleanArrayList(List<Boolean> other) {
-    if (other instanceof BooleanArrayList) {
-      BooleanArrayList list = (BooleanArrayList) other;
-      array = list.array.clone();
-      size = list.size;
-    } else {
-      size = other.size();
-      array = new boolean[size];
-      for (int i = 0; i < size; i++) {
-        array[i] = other.get(i);
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof BooleanArrayList)) {
+      return super.equals(o);
+    }
+    BooleanArrayList other = (BooleanArrayList) o;
+    if (size != other.size) {
+      return false;
+    }
+    
+    final boolean[] arr = other.array;
+    for (int i = 0; i < size; i++) {
+      if (array[i] != arr[i]) {
+        return false;
       }
     }
+    
+    return true;
   }
-  
+
+  @Override
+  public int hashCode() {
+    int result = 1;
+    for (int i = 0; i < size; i++) {
+      result = (31 * result) + Internal.hashBoolean(array[i]);
+    }
+    return result;
+  }
+
+  @Override
+  public BooleanList mutableCopyWithCapacity(int capacity) {
+    if (capacity < size) {
+      throw new IllegalArgumentException();
+    }
+    return new BooleanArrayList(Arrays.copyOf(array, capacity), size);
+  }
+
   @Override
   public Boolean get(int index) {
     return getBoolean(index);

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 258 - 456
java/core/src/main/java/com/google/protobuf/CodedOutputStream.java


+ 145 - 36
java/core/src/main/java/com/google/protobuf/Descriptors.java

@@ -74,16 +74,28 @@ public final class Descriptors {
    */
   public static final class FileDescriptor extends GenericDescriptor {
     /** Convert the descriptor to its protocol message representation. */
-    public FileDescriptorProto toProto() { return proto; }
+    @Override
+    public FileDescriptorProto toProto() {
+      return proto;
+    }
 
     /** Get the file name. */
-    public String getName() { return proto.getName(); }
+    @Override
+    public String getName() {
+      return proto.getName();
+    }
 
     /** Returns this object. */
-    public FileDescriptor getFile() { return this; }
+    @Override
+    public FileDescriptor getFile() {
+      return this;
+    }
 
     /** Returns the same as getName(). */
-    public String getFullName() { return proto.getName(); }
+    @Override
+    public String getFullName() {
+      return proto.getName();
+    }
 
     /**
      * Get the proto package name.  This is the package name given by the
@@ -582,10 +594,16 @@ public final class Descriptors {
     public int getIndex() { return index; }
 
     /** Convert the descriptor to its protocol message representation. */
-    public DescriptorProto toProto() { return proto; }
+    @Override
+    public DescriptorProto toProto() {
+      return proto;
+    }
 
     /** Get the type's unqualified name. */
-    public String getName() { return proto.getName(); }
+    @Override
+    public String getName() {
+      return proto.getName();
+    }
 
     /**
      * Get the type's fully-qualified name, within the proto language's
@@ -598,10 +616,16 @@ public final class Descriptors {
      * </pre>
      * {@code Baz}'s full name is "foo.bar.Baz".
      */
-    public String getFullName() { return fullName; }
+    @Override
+    public String getFullName() {
+      return fullName;
+    }
 
     /** Get the {@link FileDescriptor} containing this descriptor. */
-    public FileDescriptor getFile() { return file; }
+    @Override
+    public FileDescriptor getFile() {
+      return file;
+    }
 
     /** If this is a nested type, get the outer descriptor, otherwise null. */
     public Descriptor getContainingType() { return containingType; }
@@ -875,19 +899,31 @@ public final class Descriptors {
     public int getIndex() { return index; }
 
     /** Convert the descriptor to its protocol message representation. */
-    public FieldDescriptorProto toProto() { return proto; }
+    @Override
+    public FieldDescriptorProto toProto() {
+      return proto;
+    }
 
     /** Get the field's unqualified name. */
-    public String getName() { return proto.getName(); }
+    @Override
+    public String getName() {
+      return proto.getName();
+    }
 
     /** Get the field's number. */
-    public int getNumber() { return proto.getNumber(); }
+    @Override
+    public int getNumber() {
+      return proto.getNumber();
+    }
 
     /**
      * Get the field's fully-qualified name.
      * @see Descriptors.Descriptor#getFullName()
      */
-    public String getFullName() { return fullName; }
+    @Override
+    public String getFullName() {
+      return fullName;
+    }
 
     /** Get the JSON name of this field. */
     public String getJsonName() {
@@ -901,17 +937,22 @@ public final class Descriptors {
     public JavaType getJavaType() { return type.getJavaType(); }
 
     /** For internal use only. */
+    @Override
     public WireFormat.JavaType getLiteJavaType() {
       return getLiteType().getJavaType();
     }
 
     /** Get the {@code FileDescriptor} containing this descriptor. */
-    public FileDescriptor getFile() { return file; }
+    @Override
+    public FileDescriptor getFile() {
+      return file;
+    }
 
     /** Get the field's declared type. */
     public Type getType() { return type; }
 
     /** For internal use only. */
+    @Override
     public WireFormat.FieldType getLiteType() {
       return table[type.ordinal()];
     }
@@ -953,6 +994,7 @@ public final class Descriptors {
     }
 
     /** Is this field declared repeated? */
+    @Override
     public boolean isRepeated() {
       return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED;
     }
@@ -960,6 +1002,7 @@ public final class Descriptors {
     /** Does this field have the {@code [packed = true]} option or is this field
      *  packable in proto3 and not explicitly setted to unpacked?
      */
+    @Override
     public boolean isPacked() {
       if (!isPackable()) {
         return false;
@@ -1048,6 +1091,7 @@ public final class Descriptors {
     }
 
     /** For enum fields, gets the field's type. */
+    @Override
     public EnumDescriptor getEnumType() {
       if (getJavaType() != JavaType.ENUM) {
         throw new UnsupportedOperationException(
@@ -1066,6 +1110,7 @@ public final class Descriptors {
      * @return negative, zero, or positive if {@code this} is less than,
      *         equal to, or greater than {@code other}, respectively.
      */
+    @Override
     public int compareTo(final FieldDescriptor other) {
       if (other.containingType != containingType) {
         throw new IllegalArgumentException(
@@ -1466,8 +1511,8 @@ public final class Descriptors {
      * For internal use only.  This is to satisfy the FieldDescriptorLite
      * interface.
      */
-    public MessageLite.Builder internalMergeFrom(
-        MessageLite.Builder to, MessageLite from) {
+    @Override
+    public MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from) {
       // FieldDescriptors are only used with non-lite messages so we can just
       // down-cast and call mergeFrom directly.
       return ((Message.Builder) to).mergeFrom((Message) from);
@@ -1487,19 +1532,31 @@ public final class Descriptors {
     public int getIndex() { return index; }
 
     /** Convert the descriptor to its protocol message representation. */
-    public EnumDescriptorProto toProto() { return proto; }
+    @Override
+    public EnumDescriptorProto toProto() {
+      return proto;
+    }
 
     /** Get the type's unqualified name. */
-    public String getName() { return proto.getName(); }
+    @Override
+    public String getName() {
+      return proto.getName();
+    }
 
     /**
      * Get the type's fully-qualified name.
      * @see Descriptors.Descriptor#getFullName()
      */
-    public String getFullName() { return fullName; }
+    @Override
+    public String getFullName() {
+      return fullName;
+    }
 
     /** Get the {@link FileDescriptor} containing this descriptor. */
-    public FileDescriptor getFile() { return file; }
+    @Override
+    public FileDescriptor getFile() {
+      return file;
+    }
 
     /** If this is a nested type, get the outer descriptor, otherwise null. */
     public Descriptor getContainingType() { return containingType; }
@@ -1533,6 +1590,7 @@ public final class Descriptors {
      * @param number The value's number.
      * @return the value's descriptor, or {@code null} if not found.
      */
+    @Override
     public EnumValueDescriptor findValueByNumber(final int number) {
       return file.pool.enumValuesByNumber.get(
         new DescriptorPool.DescriptorIntPair(this, number));
@@ -1659,13 +1717,22 @@ public final class Descriptors {
     public int getIndex() { return index; }
 
     /** Convert the descriptor to its protocol message representation. */
-    public EnumValueDescriptorProto toProto() { return proto; }
+    @Override
+    public EnumValueDescriptorProto toProto() {
+      return proto;
+    }
 
     /** Get the value's unqualified name. */
-    public String getName() { return proto.getName(); }
+    @Override
+    public String getName() {
+      return proto.getName();
+    }
 
     /** Get the value's number. */
-    public int getNumber() { return proto.getNumber(); }
+    @Override
+    public int getNumber() {
+      return proto.getNumber();
+    }
 
     @Override
     public String toString() { return proto.getName(); }
@@ -1674,10 +1741,16 @@ public final class Descriptors {
      * Get the value's fully-qualified name.
      * @see Descriptors.Descriptor#getFullName()
      */
-    public String getFullName() { return fullName; }
+    @Override
+    public String getFullName() {
+      return fullName;
+    }
 
     /** Get the {@link FileDescriptor} containing this descriptor. */
-    public FileDescriptor getFile() { return file; }
+    @Override
+    public FileDescriptor getFile() {
+      return file;
+    }
 
     /** Get the value's enum type. */
     public EnumDescriptor getType() { return type; }
@@ -1745,19 +1818,31 @@ public final class Descriptors {
     public int getIndex() { return index; }
 
     /** Convert the descriptor to its protocol message representation. */
-    public ServiceDescriptorProto toProto() { return proto; }
+    @Override
+    public ServiceDescriptorProto toProto() {
+      return proto;
+    }
 
     /** Get the type's unqualified name. */
-    public String getName() { return proto.getName(); }
+    @Override
+    public String getName() {
+      return proto.getName();
+    }
 
     /**
      * Get the type's fully-qualified name.
      * @see Descriptors.Descriptor#getFullName()
      */
-    public String getFullName() { return fullName; }
+    @Override
+    public String getFullName() {
+      return fullName;
+    }
 
     /** Get the {@link FileDescriptor} containing this descriptor. */
-    public FileDescriptor getFile() { return file; }
+    @Override
+    public FileDescriptor getFile() {
+      return file;
+    }
 
     /** Get the {@code ServiceOptions}, defined in {@code descriptor.proto}. */
     public ServiceOptions getOptions() { return proto.getOptions(); }
@@ -1835,19 +1920,31 @@ public final class Descriptors {
     public int getIndex() { return index; }
 
     /** Convert the descriptor to its protocol message representation. */
-    public MethodDescriptorProto toProto() { return proto; }
+    @Override
+    public MethodDescriptorProto toProto() {
+      return proto;
+    }
 
     /** Get the method's unqualified name. */
-    public String getName() { return proto.getName(); }
+    @Override
+    public String getName() {
+      return proto.getName();
+    }
 
     /**
      * Get the method's fully-qualified name.
      * @see Descriptors.Descriptor#getFullName()
      */
-    public String getFullName() { return fullName; }
+    @Override
+    public String getFullName() {
+      return fullName;
+    }
 
     /** Get the {@link FileDescriptor} containing this descriptor. */
-    public FileDescriptor getFile() { return file; }
+    @Override
+    public FileDescriptor getFile() {
+      return file;
+    }
 
     /** Get the method's service type. */
     public ServiceDescriptor getService() { return service; }
@@ -2248,10 +2345,22 @@ public final class Descriptors {
      * that has the same name as an existing package.
      */
     private static final class PackageDescriptor extends GenericDescriptor {
-      public Message toProto()        { return file.toProto(); }
-      public String getName()         { return name;           }
-      public String getFullName()     { return fullName;       }
-      public FileDescriptor getFile() { return file;           }
+      @Override
+      public Message toProto() {
+        return file.toProto();
+      }
+      @Override
+      public String getName() {
+        return name;
+      }
+      @Override
+      public String getFullName() {
+        return fullName;
+      }
+      @Override
+      public FileDescriptor getFile() {
+        return file;
+      }
 
       PackageDescriptor(final String name, final String fullName,
                         final FileDescriptor file) {

+ 43 - 22
java/core/src/main/java/com/google/protobuf/DoubleArrayList.java

@@ -34,7 +34,6 @@ import com.google.protobuf.Internal.DoubleList;
 
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.List;
 import java.util.RandomAccess;
 
 /**
@@ -45,8 +44,6 @@ import java.util.RandomAccess;
 final class DoubleArrayList
     extends AbstractProtobufList<Double> implements DoubleList, RandomAccess {
   
-  private static final int DEFAULT_CAPACITY = 10;
-  
   private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList();
   static {
     EMPTY_LIST.makeImmutable();
@@ -71,32 +68,56 @@ final class DoubleArrayList
    * Constructs a new mutable {@code DoubleArrayList} with default capacity.
    */
   DoubleArrayList() {
-    this(DEFAULT_CAPACITY);
-  }
-
-  /**
-   * Constructs a new mutable {@code DoubleArrayList} with the provided capacity.
-   */
-  DoubleArrayList(int capacity) {
-    array = new double[capacity];
-    size = 0;
+    this(new double[DEFAULT_CAPACITY], 0);
   }
 
   /**
    * Constructs a new mutable {@code DoubleArrayList} containing the same elements as {@code other}.
    */
-  DoubleArrayList(List<Double> other) {
-    if (other instanceof DoubleArrayList) {
-      DoubleArrayList list = (DoubleArrayList) other;
-      array = list.array.clone();
-      size = list.size;
-    } else {
-      size = other.size();
-      array = new double[size];
-      for (int i = 0; i < size; i++) {
-        array[i] = other.get(i);
+  private DoubleArrayList(double[] array, int size) {
+    this.array = array;
+    this.size = size;
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof DoubleArrayList)) {
+      return super.equals(o);
+    }
+    DoubleArrayList other = (DoubleArrayList) o;
+    if (size != other.size) {
+      return false;
+    }
+    
+    final double[] arr = other.array;
+    for (int i = 0; i < size; i++) {
+      if (array[i] != arr[i]) {
+        return false;
       }
     }
+    
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = 1;
+    for (int i = 0; i < size; i++) {
+      long bits = Double.doubleToLongBits(array[i]);
+      result = (31 * result) + Internal.hashLong(bits);
+    }
+    return result;
+  }
+
+  @Override
+  public DoubleList mutableCopyWithCapacity(int capacity) {
+    if (capacity < size) {
+      throw new IllegalArgumentException();
+    }
+    return new DoubleArrayList(Arrays.copyOf(array, capacity), size);
   }
   
   @Override

+ 36 - 4
java/core/src/main/java/com/google/protobuf/DynamicMessage.java

@@ -156,18 +156,22 @@ public final class DynamicMessage extends AbstractMessage {
   // -----------------------------------------------------------------
   // Implementation of Message interface.
 
+  @Override
   public Descriptor getDescriptorForType() {
     return type;
   }
 
+  @Override
   public DynamicMessage getDefaultInstanceForType() {
     return getDefaultInstance(type);
   }
 
+  @Override
   public Map<FieldDescriptor, Object> getAllFields() {
     return fields.getAllFields();
   }
 
+  @Override
   public boolean hasOneof(OneofDescriptor oneof) {
     verifyOneofContainingType(oneof);
     FieldDescriptor field = oneofCases[oneof.getIndex()];
@@ -177,16 +181,19 @@ public final class DynamicMessage extends AbstractMessage {
     return true;
   }
 
+  @Override
   public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
     verifyOneofContainingType(oneof);
     return oneofCases[oneof.getIndex()];
   }
 
+  @Override
   public boolean hasField(FieldDescriptor field) {
     verifyContainingType(field);
     return fields.hasField(field);
   }
 
+  @Override
   public Object getField(FieldDescriptor field) {
     verifyContainingType(field);
     Object result = fields.getField(field);
@@ -202,16 +209,19 @@ public final class DynamicMessage extends AbstractMessage {
     return result;
   }
 
+  @Override
   public int getRepeatedFieldCount(FieldDescriptor field) {
     verifyContainingType(field);
     return fields.getRepeatedFieldCount(field);
   }
 
+  @Override
   public Object getRepeatedField(FieldDescriptor field, int index) {
     verifyContainingType(field);
     return fields.getRepeatedField(field, index);
   }
 
+  @Override
   public UnknownFieldSet getUnknownFields() {
     return unknownFields;
   }
@@ -264,19 +274,22 @@ public final class DynamicMessage extends AbstractMessage {
     return size;
   }
 
+  @Override
   public Builder newBuilderForType() {
     return new Builder(type);
   }
 
+  @Override
   public Builder toBuilder() {
     return newBuilderForType().mergeFrom(this);
   }
 
+  @Override
   public Parser<DynamicMessage> getParserForType() {
     return new AbstractParser<DynamicMessage>() {
+      @Override
       public DynamicMessage parsePartialFrom(
-          CodedInputStream input,
-          ExtensionRegistryLite extensionRegistry)
+          CodedInputStream input, ExtensionRegistryLite extensionRegistry)
           throws InvalidProtocolBufferException {
         Builder builder = newBuilder(type);
         try {
@@ -370,6 +383,7 @@ public final class DynamicMessage extends AbstractMessage {
       }
     }
 
+    @Override
     public DynamicMessage build() {
       if (!isInitialized()) {
         throw newUninitializedMessageException(
@@ -394,6 +408,7 @@ public final class DynamicMessage extends AbstractMessage {
       return buildPartial();
     }
 
+    @Override
     public DynamicMessage buildPartial() {
       fields.makeImmutable();
       DynamicMessage result =
@@ -411,22 +426,27 @@ public final class DynamicMessage extends AbstractMessage {
       return result;
     }
 
+    @Override
     public boolean isInitialized() {
       return DynamicMessage.isInitialized(type, fields);
     }
 
+    @Override
     public Descriptor getDescriptorForType() {
       return type;
     }
 
+    @Override
     public DynamicMessage getDefaultInstanceForType() {
       return getDefaultInstance(type);
     }
 
+    @Override
     public Map<FieldDescriptor, Object> getAllFields() {
       return fields.getAllFields();
     }
 
+    @Override
     public Builder newBuilderForField(FieldDescriptor field) {
       verifyContainingType(field);
 
@@ -438,6 +458,7 @@ public final class DynamicMessage extends AbstractMessage {
       return new Builder(field.getMessageType());
     }
 
+    @Override
     public boolean hasOneof(OneofDescriptor oneof) {
       verifyOneofContainingType(oneof);
       FieldDescriptor field = oneofCases[oneof.getIndex()];
@@ -447,11 +468,13 @@ public final class DynamicMessage extends AbstractMessage {
       return true;
     }
 
+    @Override
     public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
       verifyOneofContainingType(oneof);
       return oneofCases[oneof.getIndex()];
     }
 
+    @Override
     public Builder clearOneof(OneofDescriptor oneof) {
       verifyOneofContainingType(oneof);
       FieldDescriptor field = oneofCases[oneof.getIndex()];
@@ -461,11 +484,13 @@ public final class DynamicMessage extends AbstractMessage {
       return this;
     }
 
+    @Override
     public boolean hasField(FieldDescriptor field) {
       verifyContainingType(field);
       return fields.hasField(field);
     }
 
+    @Override
     public Object getField(FieldDescriptor field) {
       verifyContainingType(field);
       Object result = fields.getField(field);
@@ -481,6 +506,7 @@ public final class DynamicMessage extends AbstractMessage {
       return result;
     }
 
+    @Override
     public Builder setField(FieldDescriptor field, Object value) {
       verifyContainingType(field);
       ensureIsMutable();
@@ -505,6 +531,7 @@ public final class DynamicMessage extends AbstractMessage {
       return this;
     }
 
+    @Override
     public Builder clearField(FieldDescriptor field) {
       verifyContainingType(field);
       ensureIsMutable();
@@ -519,24 +546,27 @@ public final class DynamicMessage extends AbstractMessage {
       return this;
     }
 
+    @Override
     public int getRepeatedFieldCount(FieldDescriptor field) {
       verifyContainingType(field);
       return fields.getRepeatedFieldCount(field);
     }
 
+    @Override
     public Object getRepeatedField(FieldDescriptor field, int index) {
       verifyContainingType(field);
       return fields.getRepeatedField(field, index);
     }
 
-    public Builder setRepeatedField(FieldDescriptor field,
-                                    int index, Object value) {
+    @Override
+    public Builder setRepeatedField(FieldDescriptor field, int index, Object value) {
       verifyContainingType(field);
       ensureIsMutable();
       fields.setRepeatedField(field, index, value);
       return this;
     }
 
+    @Override
     public Builder addRepeatedField(FieldDescriptor field, Object value) {
       verifyContainingType(field);
       ensureIsMutable();
@@ -544,10 +574,12 @@ public final class DynamicMessage extends AbstractMessage {
       return this;
     }
 
+    @Override
     public UnknownFieldSet getUnknownFields() {
       return unknownFields;
     }
 
+    @Override
     public Builder setUnknownFields(UnknownFieldSet unknownFields) {
       if (getDescriptorForType().getFile().getSyntax()
           == Descriptors.FileDescriptor.Syntax.PROTO3) {

+ 1 - 0
java/core/src/main/java/com/google/protobuf/Extension.java

@@ -42,6 +42,7 @@ public abstract class Extension<ContainingType extends MessageLite, Type>
   public abstract Descriptors.FieldDescriptor getDescriptor();
 
   /** Returns whether or not this extension is a Lite Extension. */
+  @Override
   final boolean isLite() {
     return false;
   }

+ 19 - 0
java/core/src/main/java/com/google/protobuf/FieldSet.java

@@ -120,6 +120,25 @@ final class FieldSet<FieldDescriptorType extends
   public boolean isImmutable() {
     return isImmutable;
   }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    
+    if (!(o instanceof FieldSet)) {
+      return false;
+    }
+    
+    FieldSet<?> other = (FieldSet<?>) o;
+    return other.fields.equals(other.fields);
+  }
+  
+  @Override
+  public int hashCode() {
+    return fields.hashCode();
+  }
 
   /**
    * Clones the FieldSet. The returned FieldSet will be mutable even if the

+ 42 - 22
java/core/src/main/java/com/google/protobuf/FloatArrayList.java

@@ -34,7 +34,6 @@ import com.google.protobuf.Internal.FloatList;
 
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.List;
 import java.util.RandomAccess;
 
 /**
@@ -44,8 +43,6 @@ import java.util.RandomAccess;
  */
 final class FloatArrayList extends AbstractProtobufList<Float> implements FloatList, RandomAccess {
   
-  private static final int DEFAULT_CAPACITY = 10;
-  
   private static final FloatArrayList EMPTY_LIST = new FloatArrayList();
   static {
     EMPTY_LIST.makeImmutable();
@@ -70,32 +67,55 @@ final class FloatArrayList extends AbstractProtobufList<Float> implements FloatL
    * Constructs a new mutable {@code FloatArrayList} with default capacity.
    */
   FloatArrayList() {
-    this(DEFAULT_CAPACITY);
-  }
-
-  /**
-   * Constructs a new mutable {@code FloatArrayList} with the provided capacity.
-   */
-  FloatArrayList(int capacity) {
-    array = new float[capacity];
-    size = 0;
+    this(new float[DEFAULT_CAPACITY], 0);
   }
 
   /**
    * Constructs a new mutable {@code FloatArrayList} containing the same elements as {@code other}.
    */
-  FloatArrayList(List<Float> other) {
-    if (other instanceof FloatArrayList) {
-      FloatArrayList list = (FloatArrayList) other;
-      array = list.array.clone();
-      size = list.size;
-    } else {
-      size = other.size();
-      array = new float[size];
-      for (int i = 0; i < size; i++) {
-        array[i] = other.get(i);
+  private FloatArrayList(float[] array, int size) {
+    this.array = array;
+    this.size = size;
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof FloatArrayList)) {
+      return super.equals(o);
+    }
+    FloatArrayList other = (FloatArrayList) o;
+    if (size != other.size) {
+      return false;
+    }
+    
+    final float[] arr = other.array;
+    for (int i = 0; i < size; i++) {
+      if (array[i] != arr[i]) {
+        return false;
       }
     }
+    
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = 1;
+    for (int i = 0; i < size; i++) {
+      result = (31 * result) + Float.floatToIntBits(array[i]);
+    }
+    return result;
+  }
+
+  @Override
+  public FloatList mutableCopyWithCapacity(int capacity) {
+    if (capacity < size) {
+      throw new IllegalArgumentException();
+    }
+    return new FloatArrayList(Arrays.copyOf(array, capacity), size);
   }
   
   @Override

+ 152 - 103
java/core/src/main/java/com/google/protobuf/GeneratedMessage.java

@@ -80,6 +80,7 @@ public abstract class GeneratedMessage extends AbstractMessage
     unknownFields = builder.getUnknownFields();
   }
 
+  @Override
   public Parser<? extends GeneratedMessage> getParserForType() {
     throw new UnsupportedOperationException(
         "This is supposed to be overridden by subclasses.");
@@ -102,7 +103,7 @@ public abstract class GeneratedMessage extends AbstractMessage
    */
   protected abstract FieldAccessorTable internalGetFieldAccessorTable();
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public Descriptor getDescriptorForType() {
     return internalGetFieldAccessorTable().descriptor;
   }
@@ -191,7 +192,7 @@ public abstract class GeneratedMessage extends AbstractMessage
     return true;
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public Map<FieldDescriptor, Object> getAllFields() {
     return Collections.unmodifiableMap(
         getAllFieldsMutable(/* getBytesForString = */ false));
@@ -212,22 +213,22 @@ public abstract class GeneratedMessage extends AbstractMessage
         getAllFieldsMutable(/* getBytesForString = */ true));
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public boolean hasOneof(final OneofDescriptor oneof) {
     return internalGetFieldAccessorTable().getOneof(oneof).has(this);
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) {
     return internalGetFieldAccessorTable().getOneof(oneof).get(this);
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public boolean hasField(final FieldDescriptor field) {
     return internalGetFieldAccessorTable().getField(field).has(this);
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public Object getField(final FieldDescriptor field) {
     return internalGetFieldAccessorTable().getField(field).get(this);
   }
@@ -244,19 +245,19 @@ public abstract class GeneratedMessage extends AbstractMessage
     return internalGetFieldAccessorTable().getField(field).getRaw(this);
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public int getRepeatedFieldCount(final FieldDescriptor field) {
     return internalGetFieldAccessorTable().getField(field)
       .getRepeatedCount(this);
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public Object getRepeatedField(final FieldDescriptor field, final int index) {
     return internalGetFieldAccessorTable().getField(field)
       .getRepeated(this, index);
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public UnknownFieldSet getUnknownFields() {
     throw new UnsupportedOperationException(
         "This is supposed to be overridden by subclasses.");
@@ -380,7 +381,7 @@ public abstract class GeneratedMessage extends AbstractMessage
   }
 
   @SuppressWarnings("unchecked")
-  public abstract static class Builder <BuilderType extends Builder>
+  public abstract static class Builder <BuilderType extends Builder<BuilderType>>
       extends AbstractMessage.Builder<BuilderType> {
 
     private BuilderParent builderParent;
@@ -444,6 +445,7 @@ public abstract class GeneratedMessage extends AbstractMessage
      * Called by the initialization and clear code paths to allow subclasses to
      * reset any of their builtin fields back to the initial values.
      */
+    @Override
     public BuilderType clear() {
       unknownFields = UnknownFieldSet.getDefaultInstance();
       onChanged();
@@ -457,12 +459,12 @@ public abstract class GeneratedMessage extends AbstractMessage
      */
     protected abstract FieldAccessorTable internalGetFieldAccessorTable();
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public Descriptor getDescriptorForType() {
       return internalGetFieldAccessorTable().descriptor;
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public Map<FieldDescriptor, Object> getAllFields() {
       return Collections.unmodifiableMap(getAllFieldsMutable());
     }
@@ -510,39 +512,38 @@ public abstract class GeneratedMessage extends AbstractMessage
       return result;
     }
 
-    public Message.Builder newBuilderForField(
-        final FieldDescriptor field) {
+    @Override
+    public Message.Builder newBuilderForField(final FieldDescriptor field) {
       return internalGetFieldAccessorTable().getField(field).newBuilder();
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public Message.Builder getFieldBuilder(final FieldDescriptor field) {
       return internalGetFieldAccessorTable().getField(field).getBuilder(this);
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
-    public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field,
-        int index) {
+    @Override
+    public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) {
       return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder(
           this, index);
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public boolean hasOneof(final OneofDescriptor oneof) {
       return internalGetFieldAccessorTable().getOneof(oneof).has(this);
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) {
       return internalGetFieldAccessorTable().getOneof(oneof).get(this);
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public boolean hasField(final FieldDescriptor field) {
       return internalGetFieldAccessorTable().getField(field).has(this);
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public Object getField(final FieldDescriptor field) {
       Object object = internalGetFieldAccessorTable().getField(field).get(this);
       if (field.isRepeated()) {
@@ -554,52 +555,52 @@ public abstract class GeneratedMessage extends AbstractMessage
       }
     }
 
-    public BuilderType setField(final FieldDescriptor field,
-                                final Object value) {
+    @Override
+    public BuilderType setField(final FieldDescriptor field, final Object value) {
       internalGetFieldAccessorTable().getField(field).set(this, value);
       return (BuilderType) this;
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public BuilderType clearField(final FieldDescriptor field) {
       internalGetFieldAccessorTable().getField(field).clear(this);
       return (BuilderType) this;
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public BuilderType clearOneof(final OneofDescriptor oneof) {
       internalGetFieldAccessorTable().getOneof(oneof).clear(this);
       return (BuilderType) this;
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public int getRepeatedFieldCount(final FieldDescriptor field) {
       return internalGetFieldAccessorTable().getField(field)
           .getRepeatedCount(this);
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
-    public Object getRepeatedField(final FieldDescriptor field,
-                                   final int index) {
+    @Override
+    public Object getRepeatedField(final FieldDescriptor field, final int index) {
       return internalGetFieldAccessorTable().getField(field)
           .getRepeated(this, index);
     }
 
-    public BuilderType setRepeatedField(final FieldDescriptor field,
-                                        final int index, final Object value) {
+    @Override
+    public BuilderType setRepeatedField(
+        final FieldDescriptor field, final int index, final Object value) {
       internalGetFieldAccessorTable().getField(field)
         .setRepeated(this, index, value);
       return (BuilderType) this;
     }
 
-    public BuilderType addRepeatedField(final FieldDescriptor field,
-                                        final Object value) {
+    @Override
+    public BuilderType addRepeatedField(final FieldDescriptor field, final Object value) {
       internalGetFieldAccessorTable().getField(field).addRepeated(this, value);
       return (BuilderType) this;
     }
 
-    public BuilderType setUnknownFields(
-        final UnknownFieldSet unknownFields) {
+    @Override
+    public BuilderType setUnknownFields(final UnknownFieldSet unknownFields) {
       this.unknownFields = unknownFields;
       onChanged();
       return (BuilderType) this;
@@ -616,7 +617,7 @@ public abstract class GeneratedMessage extends AbstractMessage
       return (BuilderType) this;
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public boolean isInitialized() {
       for (final FieldDescriptor field : getDescriptorForType().getFields()) {
         // Check that all required fields are present.
@@ -646,7 +647,7 @@ public abstract class GeneratedMessage extends AbstractMessage
       return true;
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public final UnknownFieldSet getUnknownFields() {
       return unknownFields;
     }
@@ -670,7 +671,7 @@ public abstract class GeneratedMessage extends AbstractMessage
      */
     private class BuilderParentImpl implements BuilderParent {
 
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
+      @Override
       public void markDirty() {
         onChanged();
       }
@@ -735,6 +736,7 @@ public abstract class GeneratedMessage extends AbstractMessage
   public interface ExtendableMessageOrBuilder<
       MessageType extends ExtendableMessage> extends MessageOrBuilder {
     // Re-define for return type covariance.
+    @Override
     Message getDefaultInstanceForType();
 
     /** Check if a singular extension is present. */
@@ -823,9 +825,8 @@ public abstract class GeneratedMessage extends AbstractMessage
     }
 
     /** Check if a singular extension is present. */
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
-    public final <Type> boolean hasExtension(
-        final ExtensionLite<MessageType, Type> extensionLite) {
+    @Override
+    public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
       Extension<MessageType, Type> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
@@ -833,7 +834,7 @@ public abstract class GeneratedMessage extends AbstractMessage
     }
 
     /** Get the number of elements in a repeated extension. */
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public final <Type> int getExtensionCount(
         final ExtensionLite<MessageType, List<Type>> extensionLite) {
       Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
@@ -844,10 +845,9 @@ public abstract class GeneratedMessage extends AbstractMessage
     }
 
     /** Get the value of an extension. */
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     @SuppressWarnings("unchecked")
-    public final <Type> Type getExtension(
-        final ExtensionLite<MessageType, Type> extensionLite) {
+    public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
       Extension<MessageType, Type> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
@@ -869,11 +869,10 @@ public abstract class GeneratedMessage extends AbstractMessage
     }
 
     /** Get one element of a repeated extension. */
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     @SuppressWarnings("unchecked")
     public final <Type> Type getExtension(
-        final ExtensionLite<MessageType, List<Type>> extensionLite,
-        final int index) {
+        final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
       Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
@@ -1107,7 +1106,7 @@ public abstract class GeneratedMessage extends AbstractMessage
   @SuppressWarnings("unchecked")
   public abstract static class ExtendableBuilder<
         MessageType extends ExtendableMessage,
-        BuilderType extends ExtendableBuilder>
+        BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
       extends Builder<BuilderType>
       implements ExtendableMessageOrBuilder<MessageType> {
 
@@ -1159,9 +1158,8 @@ public abstract class GeneratedMessage extends AbstractMessage
     }
 
     /** Check if a singular extension is present. */
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
-    public final <Type> boolean hasExtension(
-        final ExtensionLite<MessageType, Type> extensionLite) {
+    @Override
+    public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
       Extension<MessageType, Type> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
@@ -1169,7 +1167,7 @@ public abstract class GeneratedMessage extends AbstractMessage
     }
 
     /** Get the number of elements in a repeated extension. */
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public final <Type> int getExtensionCount(
         final ExtensionLite<MessageType, List<Type>> extensionLite) {
       Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
@@ -1180,9 +1178,8 @@ public abstract class GeneratedMessage extends AbstractMessage
     }
 
     /** Get the value of an extension. */
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
-    public final <Type> Type getExtension(
-        final ExtensionLite<MessageType, Type> extensionLite) {
+    @Override
+    public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
       Extension<MessageType, Type> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
@@ -1204,10 +1201,9 @@ public abstract class GeneratedMessage extends AbstractMessage
     }
 
     /** Get one element of a repeated extension. */
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public final <Type> Type getExtension(
-        final ExtensionLite<MessageType, List<Type>> extensionLite,
-        final int index) {
+        final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
       Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
@@ -1460,10 +1456,9 @@ public abstract class GeneratedMessage extends AbstractMessage
     // obtained.
     return new GeneratedExtension<ContainingType, Type>(
         new CachedDescriptorRetriever() {
-          //@Override (Java 1.6 override semantics, but we must support 1.5)
+          @Override
           public FieldDescriptor loadDescriptor() {
-            return scope.getDescriptorForType().getExtensions()
-                .get(descriptorIndex);
+            return scope.getDescriptorForType().getExtensions().get(descriptorIndex);
           }
         },
         singularType,
@@ -1491,6 +1486,7 @@ public abstract class GeneratedMessage extends AbstractMessage
     private volatile FieldDescriptor descriptor;
     protected abstract FieldDescriptor loadDescriptor();
 
+    @Override
     public FieldDescriptor getDescriptor() {
       if (descriptor == null) {
         synchronized (this) {
@@ -1520,6 +1516,7 @@ public abstract class GeneratedMessage extends AbstractMessage
     // obtained.
     return new GeneratedExtension<ContainingType, Type>(
         new CachedDescriptorRetriever() {
+          @Override
           protected FieldDescriptor loadDescriptor() {
             return scope.getDescriptorForType().findFieldByName(name);
           }
@@ -1546,17 +1543,18 @@ public abstract class GeneratedMessage extends AbstractMessage
     // used to obtain the extension's FieldDescriptor.
     return new GeneratedExtension<ContainingType, Type>(
         new CachedDescriptorRetriever() {
+          @Override
           protected FieldDescriptor loadDescriptor() {
             try {
-              Class clazz =
-                  singularType.getClassLoader().loadClass(descriptorOuterClass);
-              FileDescriptor file =
-                  (FileDescriptor) clazz.getField("descriptor").get(null);
+              Class clazz = singularType.getClassLoader().loadClass(descriptorOuterClass);
+              FileDescriptor file = (FileDescriptor) clazz.getField("descriptor").get(null);
               return file.findExtensionByName(extensionName);
             } catch (Exception e) {
               throw new RuntimeException(
-                  "Cannot load descriptors: " + descriptorOuterClass +
-                  " is not a valid descriptor class name", e);
+                  "Cannot load descriptors: "
+                      + descriptorOuterClass
+                      + " is not a valid descriptor class name",
+                  e);
             }
           }
         },
@@ -1638,12 +1636,13 @@ public abstract class GeneratedMessage extends AbstractMessage
       if (descriptorRetriever != null) {
         throw new IllegalStateException("Already initialized.");
       }
-      descriptorRetriever = new ExtensionDescriptorRetriever() {
-          //@Override (Java 1.6 override semantics, but we must support 1.5)
-          public FieldDescriptor getDescriptor() {
-            return descriptor;
-          }
-        };
+      descriptorRetriever =
+          new ExtensionDescriptorRetriever() {
+            @Override
+            public FieldDescriptor getDescriptor() {
+              return descriptor;
+            }
+          };
     }
 
     private ExtensionDescriptorRetriever descriptorRetriever;
@@ -1653,6 +1652,7 @@ public abstract class GeneratedMessage extends AbstractMessage
     private final Method enumGetValueDescriptor;
     private final ExtensionType extensionType;
 
+    @Override
     public FieldDescriptor getDescriptor() {
       if (descriptorRetriever == null) {
         throw new IllegalStateException(
@@ -1665,10 +1665,12 @@ public abstract class GeneratedMessage extends AbstractMessage
      * If the extension is an embedded message or group, returns the default
      * instance of the message.
      */
+    @Override
     public Message getMessageDefaultInstance() {
       return messageDefaultInstance;
     }
 
+    @Override
     protected ExtensionType getExtensionType() {
       return extensionType;
     }
@@ -1679,7 +1681,7 @@ public abstract class GeneratedMessage extends AbstractMessage
      * EnumValueDescriptors but the native accessors use the generated enum
      * type.
      */
-    // @Override
+    @Override
     @SuppressWarnings("unchecked")
     protected Object fromReflectionType(final Object value) {
       FieldDescriptor descriptor = getDescriptor();
@@ -1704,7 +1706,7 @@ public abstract class GeneratedMessage extends AbstractMessage
      * Like {@link #fromReflectionType(Object)}, but if the type is a repeated
      * type, this converts a single element.
      */
-    // @Override
+    @Override
     protected Object singularFromReflectionType(final Object value) {
       FieldDescriptor descriptor = getDescriptor();
       switch (descriptor.getJavaType()) {
@@ -1728,7 +1730,7 @@ public abstract class GeneratedMessage extends AbstractMessage
      * EnumValueDescriptors but the native accessors use the generated enum
      * type.
      */
-    // @Override
+    @Override
     @SuppressWarnings("unchecked")
     protected Object toReflectionType(final Object value) {
       FieldDescriptor descriptor = getDescriptor();
@@ -1752,7 +1754,7 @@ public abstract class GeneratedMessage extends AbstractMessage
      * Like {@link #toReflectionType(Object)}, but if the type is a repeated
      * type, this converts a single element.
      */
-    // @Override
+    @Override
     protected Object singularToReflectionType(final Object value) {
       FieldDescriptor descriptor = getDescriptor();
       switch (descriptor.getJavaType()) {
@@ -1763,22 +1765,22 @@ public abstract class GeneratedMessage extends AbstractMessage
       }
     }
 
-    // @Override
+    @Override
     public int getNumber() {
       return getDescriptor().getNumber();
     }
 
-    // @Override
+    @Override
     public WireFormat.FieldType getLiteType() {
       return getDescriptor().getLiteType();
     }
 
-    // @Override
+    @Override
     public boolean isRepeated() {
       return getDescriptor().isRepeated();
     }
 
-    // @Override
+    @Override
     @SuppressWarnings("unchecked")
     public Type getDefaultValue() {
       if (isRepeated()) {
@@ -2128,49 +2130,57 @@ public abstract class GeneratedMessage extends AbstractMessage
         return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
       }
 
+      @Override
       public Object get(final GeneratedMessage message) {
         return invokeOrDie(getMethod, message);
       }
+      @Override
       public Object get(GeneratedMessage.Builder builder) {
         return invokeOrDie(getMethodBuilder, builder);
       }
+      @Override
       public Object getRaw(final GeneratedMessage message) {
         return get(message);
       }
+      @Override
       public Object getRaw(GeneratedMessage.Builder builder) {
         return get(builder);
       }
+      @Override
       public void set(final Builder builder, final Object value) {
         invokeOrDie(setMethod, builder, value);
       }
-      public Object getRepeated(final GeneratedMessage message,
-                                final int index) {
+      @Override
+      public Object getRepeated(final GeneratedMessage message, final int index) {
         throw new UnsupportedOperationException(
           "getRepeatedField() called on a singular field.");
       }
-      public Object getRepeatedRaw(final GeneratedMessage message,
-                                final int index) {
+      @Override
+      public Object getRepeatedRaw(final GeneratedMessage message, final int index) {
         throw new UnsupportedOperationException(
           "getRepeatedFieldRaw() called on a singular field.");
       }
+      @Override
       public Object getRepeated(GeneratedMessage.Builder builder, int index) {
         throw new UnsupportedOperationException(
           "getRepeatedField() called on a singular field.");
       }
-      public Object getRepeatedRaw(GeneratedMessage.Builder builder,
-          int index) {
+      @Override
+      public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) {
         throw new UnsupportedOperationException(
           "getRepeatedFieldRaw() called on a singular field.");
       }
-      public void setRepeated(final Builder builder, final int index,
-          final Object value) {
+      @Override
+      public void setRepeated(final Builder builder, final int index, final Object value) {
         throw new UnsupportedOperationException(
           "setRepeatedField() called on a singular field.");
       }
+      @Override
       public void addRepeated(final Builder builder, final Object value) {
         throw new UnsupportedOperationException(
           "addRepeatedField() called on a singular field.");
       }
+      @Override
       public boolean has(final GeneratedMessage message) {
         if (!hasHasMethod) {
           if (isOneofField) {
@@ -2180,6 +2190,7 @@ public abstract class GeneratedMessage extends AbstractMessage
         }
         return (Boolean) invokeOrDie(hasMethod, message);
       }
+      @Override
       public boolean has(GeneratedMessage.Builder builder) {
         if (!hasHasMethod) {
           if (isOneofField) {
@@ -2189,27 +2200,32 @@ public abstract class GeneratedMessage extends AbstractMessage
         }
         return (Boolean) invokeOrDie(hasMethodBuilder, builder);
       }
+      @Override
       public int getRepeatedCount(final GeneratedMessage message) {
         throw new UnsupportedOperationException(
           "getRepeatedFieldSize() called on a singular field.");
       }
+      @Override
       public int getRepeatedCount(GeneratedMessage.Builder builder) {
         throw new UnsupportedOperationException(
           "getRepeatedFieldSize() called on a singular field.");
       }
+      @Override
       public void clear(final Builder builder) {
         invokeOrDie(clearMethod, builder);
       }
+      @Override
       public Message.Builder newBuilder() {
         throw new UnsupportedOperationException(
           "newBuilderForField() called on a non-Message type.");
       }
+      @Override
       public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
         throw new UnsupportedOperationException(
           "getFieldBuilder() called on a non-Message type.");
       }
-      public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder,
-          int index) {
+      @Override
+      public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) {
         throw new UnsupportedOperationException(
           "getRepeatedFieldBuilder() called on a non-Message type.");
       }
@@ -2253,18 +2269,23 @@ public abstract class GeneratedMessage extends AbstractMessage
         clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
       }
 
+      @Override
       public Object get(final GeneratedMessage message) {
         return invokeOrDie(getMethod, message);
       }
+      @Override
       public Object get(GeneratedMessage.Builder builder) {
         return invokeOrDie(getMethodBuilder, builder);
       }
+      @Override
       public Object getRaw(final GeneratedMessage message) {
         return get(message);
       }
+      @Override
       public Object getRaw(GeneratedMessage.Builder builder) {
         return get(builder);
       }
+      @Override
       public void set(final Builder builder, final Object value) {
         // Add all the elements individually.  This serves two purposes:
         // 1) Verifies that each element has the correct type.
@@ -2275,54 +2296,64 @@ public abstract class GeneratedMessage extends AbstractMessage
           addRepeated(builder, element);
         }
       }
-      public Object getRepeated(final GeneratedMessage message,
-                                final int index) {
+      @Override
+      public Object getRepeated(final GeneratedMessage message, final int index) {
         return invokeOrDie(getRepeatedMethod, message, index);
       }
+      @Override
       public Object getRepeated(GeneratedMessage.Builder builder, int index) {
         return invokeOrDie(getRepeatedMethodBuilder, builder, index);
       }
+      @Override
       public Object getRepeatedRaw(GeneratedMessage message, int index) {
         return getRepeated(message, index);
       }
-      public Object getRepeatedRaw(GeneratedMessage.Builder builder,
-          int index) {
+      @Override
+      public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) {
         return getRepeated(builder, index);
       }
-      public void setRepeated(final Builder builder,
-                              final int index, final Object value) {
+      @Override
+      public void setRepeated(final Builder builder, final int index, final Object value) {
         invokeOrDie(setRepeatedMethod, builder, index, value);
       }
+      @Override
       public void addRepeated(final Builder builder, final Object value) {
         invokeOrDie(addRepeatedMethod, builder, value);
       }
+      @Override
       public boolean has(final GeneratedMessage message) {
         throw new UnsupportedOperationException(
           "hasField() called on a repeated field.");
       }
+      @Override
       public boolean has(GeneratedMessage.Builder builder) {
         throw new UnsupportedOperationException(
           "hasField() called on a repeated field.");
       }
+      @Override
       public int getRepeatedCount(final GeneratedMessage message) {
         return (Integer) invokeOrDie(getCountMethod, message);
       }
+      @Override
       public int getRepeatedCount(GeneratedMessage.Builder builder) {
         return (Integer) invokeOrDie(getCountMethodBuilder, builder);
       }
+      @Override
       public void clear(final Builder builder) {
         invokeOrDie(clearMethod, builder);
       }
+      @Override
       public Message.Builder newBuilder() {
         throw new UnsupportedOperationException(
           "newBuilderForField() called on a non-Message type.");
       }
+      @Override
       public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
         throw new UnsupportedOperationException(
           "getFieldBuilder() called on a non-Message type.");
       }
-      public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder,
-          int index) {
+      @Override
+      public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) {
         throw new UnsupportedOperationException(
           "getRepeatedFieldBuilder() called on a non-Message type.");
       }
@@ -2359,6 +2390,7 @@ public abstract class GeneratedMessage extends AbstractMessage
             field.getNumber());
       }
 
+      @Override
       public Object get(GeneratedMessage message) {
         List result = new ArrayList();
         for (int i = 0; i < getRepeatedCount(message); i++) {
@@ -2367,6 +2399,7 @@ public abstract class GeneratedMessage extends AbstractMessage
         return Collections.unmodifiableList(result);
       }
 
+      @Override
       public Object get(Builder builder) {
         List result = new ArrayList();
         for (int i = 0; i < getRepeatedCount(builder); i++) {
@@ -2375,14 +2408,17 @@ public abstract class GeneratedMessage extends AbstractMessage
         return Collections.unmodifiableList(result);
       }
 
+      @Override
       public Object getRaw(GeneratedMessage message) {
         return get(message);
       }
 
+      @Override
       public Object getRaw(GeneratedMessage.Builder builder) {
         return get(builder);
       }
 
+      @Override
       public void set(Builder builder, Object value) {
         clear(builder);
         for (Object entry : (List) value) {
@@ -2390,63 +2426,76 @@ public abstract class GeneratedMessage extends AbstractMessage
         }
       }
 
+      @Override
       public Object getRepeated(GeneratedMessage message, int index) {
         return getMapField(message).getList().get(index);
       }
 
+      @Override
       public Object getRepeated(Builder builder, int index) {
         return getMapField(builder).getList().get(index);
       }
 
+      @Override
       public Object getRepeatedRaw(GeneratedMessage message, int index) {
         return getRepeated(message, index);
       }
 
+      @Override
       public Object getRepeatedRaw(Builder builder, int index) {
         return getRepeated(builder, index);
       }
 
+      @Override
       public void setRepeated(Builder builder, int index, Object value) {
         getMutableMapField(builder).getMutableList().set(index, (Message) value);
       }
 
+      @Override
       public void addRepeated(Builder builder, Object value) {
         getMutableMapField(builder).getMutableList().add((Message) value);
       }
 
+      @Override
       public boolean has(GeneratedMessage message) {
         throw new UnsupportedOperationException(
             "hasField() is not supported for repeated fields.");
       }
 
+      @Override
       public boolean has(Builder builder) {
         throw new UnsupportedOperationException(
             "hasField() is not supported for repeated fields.");
       }
 
+      @Override
       public int getRepeatedCount(GeneratedMessage message) {
         return getMapField(message).getList().size();
       }
 
+      @Override
       public int getRepeatedCount(Builder builder) {
         return getMapField(builder).getList().size();
       }
 
+      @Override
       public void clear(Builder builder) {
         getMutableMapField(builder).getMutableList().clear();
       }
 
+      @Override
       public com.google.protobuf.Message.Builder newBuilder() {
         return mapEntryMessageDefaultInstance.newBuilderForType();
       }
 
+      @Override
       public com.google.protobuf.Message.Builder getBuilder(Builder builder) {
         throw new UnsupportedOperationException(
             "Nested builder not supported for map fields.");
       }
 
-      public com.google.protobuf.Message.Builder getRepeatedBuilder(
-          Builder builder, int index) {
+      @Override
+      public com.google.protobuf.Message.Builder getRepeatedBuilder(Builder builder, int index) {
         throw new UnsupportedOperationException(
             "Nested builder not supported for map fields.");
       }

+ 926 - 141
java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java

@@ -31,6 +31,7 @@
 package com.google.protobuf;
 
 import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
+import com.google.protobuf.GeneratedMessageLite.EqualsVisitor.NotEqualsException;
 import com.google.protobuf.Internal.BooleanList;
 import com.google.protobuf.Internal.DoubleList;
 import com.google.protobuf.Internal.FloatList;
@@ -59,24 +60,27 @@ import java.util.Map;
 public abstract class GeneratedMessageLite<
     MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
     BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>> 
-        extends AbstractMessageLite {
+        extends AbstractMessageLite<MessageType, BuilderType> {
 
   /** For use by generated code only. Lazily initialized to reduce allocations. */
-  protected UnknownFieldSetLite unknownFields = null;
+  protected UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance();
   
   /** For use by generated code only.  */
   protected int memoizedSerializedSize = -1;
   
+  @Override
   @SuppressWarnings("unchecked") // Guaranteed by runtime.
   public final Parser<MessageType> getParserForType() {
     return (Parser<MessageType>) dynamicMethod(MethodToInvoke.GET_PARSER);
   }
 
+  @Override
   @SuppressWarnings("unchecked") // Guaranteed by runtime.
   public final MessageType getDefaultInstanceForType() {
     return (MessageType) dynamicMethod(MethodToInvoke.GET_DEFAULT_INSTANCE);
   }
 
+  @Override
   @SuppressWarnings("unchecked") // Guaranteed by runtime.
   public final BuilderType newBuilderForType() {
     return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
@@ -99,7 +103,65 @@ public abstract class GeneratedMessageLite<
     return MessageLiteToString.toString(this, super.toString());
   }
 
+  @SuppressWarnings("unchecked") // Guaranteed by runtime
+  @Override
+  public int hashCode() {
+    if (memoizedHashCode == 0) {
+      HashCodeVisitor visitor = new HashCodeVisitor();
+      visit(visitor, (MessageType) this);
+      memoizedHashCode = visitor.hashCode;
+    }
+    return memoizedHashCode;
+  }
+  
+  @SuppressWarnings("unchecked") // Guaranteed by runtime
+  int hashCode(HashCodeVisitor visitor) {
+    if (memoizedHashCode == 0) {
+      int inProgressHashCode = visitor.hashCode;
+      visitor.hashCode = 0;
+      visit(visitor, (MessageType) this);
+      memoizedHashCode = visitor.hashCode;
+      visitor.hashCode = inProgressHashCode;
+    }
+    return memoizedHashCode;
+  }
+  
+  @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime
+  @Override
+  public boolean equals(Object other) {
+    if (this == other) {
+      return true;
+    }
+    
+    if (!getDefaultInstanceForType().getClass().isInstance(other)) {
+      return false;
+    }
+    
+    try {
+      visit(EqualsVisitor.INSTANCE, (MessageType) other);
+    } catch (NotEqualsException e) {
+      return false;
+    }
+    return true;
+  }
+  
+  /**
+   * Same as {@link #equals(Object)} but throws {@code NotEqualsException}.
+   */
+  @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime
+  boolean equals(EqualsVisitor visitor, MessageLite other) {
+    if (this == other) {
+      return true;
+    }
+    
+    if (!getDefaultInstanceForType().getClass().isInstance(other)) {
+      return false;
+    }
 
+    visit(visitor, (MessageType) other);
+    return true;
+  }
+  
   // The general strategy for unknown fields is to use an UnknownFieldSetLite that is treated as
   // mutable during the parsing constructor and immutable after. This allows us to avoid
   // any unnecessary intermediary allocations while reducing the generated code size.
@@ -108,7 +170,7 @@ public abstract class GeneratedMessageLite<
    * Lazily initializes unknown fields.
    */
   private final void ensureUnknownFieldsInitialized() {
-    if (unknownFields == null) {
+    if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
       unknownFields = UnknownFieldSetLite.newInstance();
     }
   }
@@ -147,18 +209,18 @@ public abstract class GeneratedMessageLite<
   /**
    * Called by subclasses to complete parsing. For use by generated code only.
    */
-  protected void doneParsing() {
-    if (unknownFields == null) {
-      unknownFields = UnknownFieldSetLite.getDefaultInstance();
-    } else {
-      unknownFields.makeImmutable();
-    }
+  protected void makeImmutable() {
+    dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
+
+    unknownFields.makeImmutable();
   }
 
+  @Override
   public final boolean isInitialized() {
     return dynamicMethod(MethodToInvoke.IS_INITIALIZED, Boolean.TRUE) != null;
   }
 
+  @Override
   public final BuilderType toBuilder() {
     BuilderType builder = (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
     builder.mergeFrom((MessageType) this);
@@ -172,11 +234,14 @@ public abstract class GeneratedMessageLite<
    * For use by generated code only.
    */
   public static enum MethodToInvoke {
+    // Rely on/modify instance state
     IS_INITIALIZED,
-    PARSE_PARTIAL_FROM,
-    MERGE_FROM,
+    VISIT,
+    MERGE_FROM_STREAM,
     MAKE_IMMUTABLE,
-    NEW_INSTANCE,
+
+    // Rely on static state
+    NEW_MUTABLE_INSTANCE,
     NEW_BUILDER,
     GET_DEFAULT_INSTANCE,
     GET_PARSER;
@@ -188,17 +253,18 @@ public abstract class GeneratedMessageLite<
    * builders in the runtime. This method bundles those operations to reduce the generated methods
    * count.
    * <ul>
-   * <li>{@code PARSE_PARTIAL_FROM} is parameterized with an {@link CodedInputStream} and
+   * <li>{@code MERGE_FROM_STREAM} is parameterized with an {@link CodedInputStream} and
    * {@link ExtensionRegistryLite}. It consumes the input stream, parsing the contents into the
    * returned protocol buffer. If parsing throws an {@link InvalidProtocolBufferException}, the
-   * implementation wraps it in a RuntimeException
-   * <li>{@code NEW_INSTANCE} returns a new instance of the protocol buffer
+   * implementation wraps it in a RuntimeException.
+   * <li>{@code NEW_INSTANCE} returns a new instance of the protocol buffer that has not yet been
+   * made immutable. See {@code MAKE_IMMUTABLE}.
    * <li>{@code IS_INITIALIZED} is parameterized with a {@code Boolean} detailing whether to
    * memoize. It returns {@code null} for false and the default instance for true. We optionally
    * memoize to support the Builder case, where memoization is not desired.
    * <li>{@code NEW_BUILDER} returns a {@code BuilderType} instance.
-   * <li>{@code MERGE_FROM} is parameterized with a {@code MessageType} and merges the fields from
-   * that instance into this instance.
+   * <li>{@code VISIT} is parameterized with a {@code Visitor} and a {@code MessageType} and
+   * recursively iterates through the fields side by side between this and the instance.
    * <li>{@code MAKE_IMMUTABLE} sets all internal fields to an immutable state.
    * </ul>
    * This method, plus the implementation of the Builder, enables the Builder class to be proguarded
@@ -222,6 +288,11 @@ public abstract class GeneratedMessageLite<
     return dynamicMethod(method, null, null);
   }
 
+  void visit(Visitor visitor, MessageType other) {
+    dynamicMethod(MethodToInvoke.VISIT, visitor, other);
+    unknownFields = visitor.visitUnknownFields(unknownFields, other.unknownFields);
+  }
+  
   /**
    * Merge some unknown fields into the {@link UnknownFieldSetLite} for this
    * message.
@@ -236,7 +307,7 @@ public abstract class GeneratedMessageLite<
   public abstract static class Builder<
       MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
       BuilderType extends Builder<MessageType, BuilderType>>
-          extends AbstractMessageLite.Builder<BuilderType> {
+          extends AbstractMessageLite.Builder<MessageType, BuilderType> {
 
     private final MessageType defaultInstance;
     protected MessageType instance;
@@ -244,7 +315,8 @@ public abstract class GeneratedMessageLite<
 
     protected Builder(MessageType defaultInstance) {
       this.defaultInstance = defaultInstance;
-      this.instance = (MessageType) defaultInstance.dynamicMethod(MethodToInvoke.NEW_INSTANCE);
+      this.instance =
+          (MessageType) defaultInstance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
       isBuilt = false;
     }
 
@@ -254,26 +326,27 @@ public abstract class GeneratedMessageLite<
      */
     protected void copyOnWrite() {
       if (isBuilt) {
-        MessageType newInstance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_INSTANCE);
-        newInstance.dynamicMethod(MethodToInvoke.MERGE_FROM, instance);
+        MessageType newInstance =
+            (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
+        newInstance.visit(MergeFromVisitor.INSTANCE, instance);
         instance = newInstance;
         isBuilt = false;
       }
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public final boolean isInitialized() {
       return GeneratedMessageLite.isInitialized(instance, false /* shouldMemoize */);
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public final BuilderType clear() {
       // No need to copy on write since we're dropping the instance anyways.
-      instance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_INSTANCE);
+      instance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
       return (BuilderType) this;
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public BuilderType clone() {
       BuilderType builder =
           (BuilderType) getDefaultInstanceForType().newBuilderForType();
@@ -281,20 +354,19 @@ public abstract class GeneratedMessageLite<
       return builder;
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public MessageType buildPartial() {
       if (isBuilt) {
         return instance;
       }
       
-      instance.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
-      instance.unknownFields.makeImmutable();
+      instance.makeImmutable();
       
       isBuilt = true;
       return instance;
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public final MessageType build() {
       MessageType result = buildPartial();
       if (!result.isInitialized()) {
@@ -303,32 +375,36 @@ public abstract class GeneratedMessageLite<
       return result;
     }
     
+    @Override
+    protected BuilderType internalMergeFrom(MessageType message) {
+      return mergeFrom(message);
+    }
+    
     /** All subclasses implement this. */
     public BuilderType mergeFrom(MessageType message) {
       copyOnWrite();
-      instance.dynamicMethod(MethodToInvoke.MERGE_FROM, message);
+      instance.visit(MergeFromVisitor.INSTANCE, message);
       return (BuilderType) this;
     }
     
+    @Override
     public MessageType getDefaultInstanceForType() {
       return defaultInstance;
     }
     
+    @Override
     public BuilderType mergeFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      MessageType parsedMessage = null;
+        throws IOException {
+      copyOnWrite();
       try {
-        parsedMessage = parsePartialFrom(
-            (MessageType) getDefaultInstanceForType(), input, extensionRegistry);
-      } catch (InvalidProtocolBufferException e) {
-        parsedMessage = (MessageType) e.getUnfinishedMessage();
-        throw e;
-      } finally {
-        if (parsedMessage != null) {
-          mergeFrom(parsedMessage);
+        instance.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry);
+      } catch (RuntimeException e) {
+        if (e.getCause() instanceof IOException) {
+          throw (IOException) e.getCause();
         }
+        throw e;
       }
       return (BuilderType) this;
     }
@@ -384,6 +460,12 @@ public abstract class GeneratedMessageLite<
       }
       extensions.mergeFrom(((ExtendableMessage) other).extensions);
     }
+
+    @Override
+    final void visit(Visitor visitor, MessageType other) {
+      super.visit(visitor, other);
+      extensions = visitor.visitExtensions(extensions, other.extensions);
+    }
     
     /**
      * Parse an unknown field or an extension. For use by generated code only.
@@ -521,9 +603,8 @@ public abstract class GeneratedMessageLite<
     }
 
     /** Check if a singular extension is present. */
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
-    public final <Type> boolean hasExtension(
-        final ExtensionLite<MessageType, Type> extension) {
+    @Override
+    public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extension) {
       GeneratedExtension<MessageType, Type> extensionLite =
           checkIsLite(extension);
       
@@ -532,7 +613,7 @@ public abstract class GeneratedMessageLite<
     }
 
     /** Get the number of elements in a repeated extension. */
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public final <Type> int getExtensionCount(
         final ExtensionLite<MessageType, List<Type>> extension) {
       GeneratedExtension<MessageType, List<Type>> extensionLite =
@@ -543,10 +624,9 @@ public abstract class GeneratedMessageLite<
     }
 
     /** Get the value of an extension. */
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     @SuppressWarnings("unchecked")
-    public final <Type> Type getExtension(
-        final ExtensionLite<MessageType, Type> extension) {
+    public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extension) {
       GeneratedExtension<MessageType, Type> extensionLite =
           checkIsLite(extension);
       
@@ -560,11 +640,10 @@ public abstract class GeneratedMessageLite<
     }
 
     /** Get one element of a repeated extension. */
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     @SuppressWarnings("unchecked")
     public final <Type> Type getExtension(
-        final ExtensionLite<MessageType, List<Type>> extension,
-        final int index) {
+        final ExtensionLite<MessageType, List<Type>> extension, final int index) {
       GeneratedExtension<MessageType, List<Type>> extensionLite =
           checkIsLite(extension);
 
@@ -579,8 +658,8 @@ public abstract class GeneratedMessageLite<
     }
 
     @Override
-    protected final void doneParsing() {
-      super.doneParsing();
+    protected final void makeImmutable() {
+      super.makeImmutable();
       
       extensions.makeImmutable();
     }
@@ -669,7 +748,7 @@ public abstract class GeneratedMessageLite<
       instance.extensions = extensions;
     }
 
-    // @Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     protected void copyOnWrite() {
       if (!isBuilt) {
         return;
@@ -679,7 +758,7 @@ public abstract class GeneratedMessageLite<
       instance.extensions = instance.extensions.clone();
     }
 
-    // @Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public final MessageType buildPartial() {
       if (isBuilt) {
         return instance;
@@ -701,33 +780,30 @@ public abstract class GeneratedMessageLite<
     }
 
     /** Check if a singular extension is present. */
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
-    public final <Type> boolean hasExtension(
-        final ExtensionLite<MessageType, Type> extension) {
+    @Override
+    public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extension) {
       return instance.hasExtension(extension);
     }
 
     /** Get the number of elements in a repeated extension. */
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public final <Type> int getExtensionCount(
         final ExtensionLite<MessageType, List<Type>> extension) {
       return instance.getExtensionCount(extension);
     }
 
     /** Get the value of an extension. */
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     @SuppressWarnings("unchecked")
-    public final <Type> Type getExtension(
-        final ExtensionLite<MessageType, Type> extension) {
+    public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extension) {
       return instance.getExtension(extension);
     }
 
     /** Get one element of a repeated extension. */
+    @Override
     @SuppressWarnings("unchecked")
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
     public final <Type> Type getExtension(
-        final ExtensionLite<MessageType, List<Type>> extension,
-        final int index) {
+        final ExtensionLite<MessageType, List<Type>> extension, final int index) {
       return instance.getExtension(extension, index);
     }
 
@@ -859,37 +935,44 @@ public abstract class GeneratedMessageLite<
     final boolean isRepeated;
     final boolean isPacked;
 
+    @Override
     public int getNumber() {
       return number;
     }
 
+    @Override
     public WireFormat.FieldType getLiteType() {
       return type;
     }
 
+    @Override
     public WireFormat.JavaType getLiteJavaType() {
       return type.getJavaType();
     }
 
+    @Override
     public boolean isRepeated() {
       return isRepeated;
     }
 
+    @Override
     public boolean isPacked() {
       return isPacked;
     }
 
+    @Override
     public Internal.EnumLiteMap<?> getEnumType() {
       return enumTypeMap;
     }
 
+    @Override
     @SuppressWarnings("unchecked")
-    public MessageLite.Builder internalMergeFrom(
-        MessageLite.Builder to, MessageLite from) {
+    public MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from) {
       return ((Builder) to).mergeFrom((GeneratedMessageLite) from);
     }
 
 
+    @Override
     public int compareTo(ExtensionDescriptor other) {
       return number - other.number;
     }
@@ -984,6 +1067,7 @@ public abstract class GeneratedMessageLite<
     }
 
     /** Get the field number. */
+    @Override
     public int getNumber() {
       return descriptor.getNumber();
     }
@@ -993,6 +1077,7 @@ public abstract class GeneratedMessageLite<
      * If the extension is an embedded message or group, returns the default
      * instance of the message.
      */
+    @Override
     public MessageLite getMessageDefaultInstance() {
       return messageDefaultInstance;
     }
@@ -1047,14 +1132,17 @@ public abstract class GeneratedMessageLite<
       }
     }
 
+    @Override
     public FieldType getLiteType() {
       return descriptor.getLiteType();
     }
 
+    @Override
     public boolean isRepeated() {
       return descriptor.isRepeated;
     }
 
+    @Override
     public Type getDefaultValue() {
       return defaultValue;
     }
@@ -1139,112 +1227,72 @@ public abstract class GeneratedMessageLite<
   protected static final <T extends GeneratedMessageLite<T, ?>> boolean isInitialized(
       T message, boolean shouldMemoize) {
     return message.dynamicMethod(MethodToInvoke.IS_INITIALIZED, shouldMemoize) != null;
-  }
+  } 
   
   protected static final <T extends GeneratedMessageLite<T, ?>> void makeImmutable(T message) {
     message.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
   }
-  
-  protected static IntList newIntList() {
-    return new IntArrayList();
-  }
-  
-  protected static IntList newIntListWithCapacity(int capacity) {
-    return new IntArrayList(capacity);
-  }
-  
-  protected static IntList newIntList(List<Integer> toCopy) {
-    return new IntArrayList(toCopy);
-  }
-  
+
   protected static IntList emptyIntList() {
     return IntArrayList.emptyList();
   }
 
-  protected static LongList newLongList() {
-    return new LongArrayList();
+  protected static IntList mutableCopy(IntList list) {
+    int size = list.size();
+    return list.mutableCopyWithCapacity(
+        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
   }
 
-  protected static LongList newLongListWithCapacity(int capacity) {
-    return new LongArrayList(capacity);
-  }
-  
-  protected static LongList newLongList(List<Long> toCopy) {
-    return new LongArrayList(toCopy);
-  }
-  
   protected static LongList emptyLongList() {
     return LongArrayList.emptyList();
   }
   
-  protected static FloatList newFloatList() {
-    return new FloatArrayList();
+  protected static LongList mutableCopy(LongList list) {
+    int size = list.size();
+    return list.mutableCopyWithCapacity(
+        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
   }
-  
-  protected static FloatList newFloatListWithCapacity(int capacity) {
-    return new FloatArrayList(capacity);
-  }
-  
-  protected static FloatList newFloatList(List<Float> toCopy) {
-    return new FloatArrayList(toCopy);
-  }
-  
+
   protected static FloatList emptyFloatList() {
     return FloatArrayList.emptyList();
   }
   
-  protected static DoubleList newDoubleList() {
-    return new DoubleArrayList();
+  protected static FloatList mutableCopy(FloatList list) {
+    int size = list.size();
+    return list.mutableCopyWithCapacity(
+        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
   }
-  
-  protected static DoubleList newDoubleListWithCapacity(int capacity) {
-    return new DoubleArrayList(capacity);
-  }
-  
-  protected static DoubleList newDoubleList(List<Double> toCopy) {
-    return new DoubleArrayList(toCopy);
-  }
-  
+
   protected static DoubleList emptyDoubleList() {
     return DoubleArrayList.emptyList();
   }
   
-  protected static BooleanList newBooleanList() {
-    return new BooleanArrayList();
-  }
-  
-  protected static BooleanList newBooleanListWithCapacity(int capacity) {
-    return new BooleanArrayList(capacity);
+  protected static DoubleList mutableCopy(DoubleList list) {
+    int size = list.size();
+    return list.mutableCopyWithCapacity(
+        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
   }
-  
-  protected static BooleanList newBooleanList(List<Boolean> toCopy) {
-    return new BooleanArrayList(toCopy);
-  }
-  
+
   protected static BooleanList emptyBooleanList() {
     return BooleanArrayList.emptyList();
   }
   
-  protected static <E> ProtobufList<E> newProtobufList() {
-    return new ProtobufArrayList<E>();
-  }
-  
-  protected static <E> ProtobufList<E> newProtobufList(List<E> toCopy) {
-    return new ProtobufArrayList<E>(toCopy);
-  }
-  
-  protected static <E> ProtobufList<E> newProtobufListWithCapacity(int capacity) {
-    return new ProtobufArrayList<E>(capacity);
+  protected static BooleanList mutableCopy(BooleanList list) {
+    int size = list.size();
+    return list.mutableCopyWithCapacity(
+        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
   }
-  
+
   protected static <E> ProtobufList<E> emptyProtobufList() {
     return ProtobufArrayList.emptyList();
   }
-
-  protected static LazyStringArrayList emptyLazyStringArrayList() {
-    return LazyStringArrayList.emptyList();
-  }
   
+  protected static <E> ProtobufList<E> mutableCopy(ProtobufList<E> list) {
+    int size = list.size();
+    return list.mutableCopyWithCapacity(
+        size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+  }
+
   /**
    * A {@link Parser} implementation that delegates to the default instance.
    * <p>
@@ -1274,10 +1322,11 @@ public abstract class GeneratedMessageLite<
   static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
       T instance, CodedInputStream input, ExtensionRegistryLite extensionRegistry)
           throws InvalidProtocolBufferException {
-    T result;
+    @SuppressWarnings("unchecked") // Guaranteed by protoc
+    T result = (T) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
     try {
-      result = (T) instance.dynamicMethod(
-          MethodToInvoke.PARSE_PARTIAL_FROM, input, extensionRegistry);
+      result.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry);
+      result.makeImmutable();
     } catch (RuntimeException e) {
       if (e.getCause() instanceof InvalidProtocolBufferException) {
         throw (InvalidProtocolBufferException) e.getCause();
@@ -1454,4 +1503,740 @@ public abstract class GeneratedMessageLite<
     }
     return message;
   }
+
+  /**
+   * An abstract visitor that the generated code calls into that we use to implement various
+   * features. Fields that are not members of oneofs are always visited. Members of a oneof are only
+   * visited when they are the set oneof case value on the "other" proto. The visitOneofNotSet
+   * method is invoked if other's oneof case is not set.
+   */
+  protected interface Visitor {
+    boolean visitBoolean(boolean minePresent, boolean mine, boolean otherPresent, boolean other);
+    int visitInt(boolean minePresent, int mine, boolean otherPresent, int other);
+    double visitDouble(boolean minePresent, double mine, boolean otherPresent, double other);
+    float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other);
+    long visitLong(boolean minePresent, long mine, boolean otherPresent, long other);
+    String visitString(boolean minePresent, String mine, boolean otherPresent, String other);
+    ByteString visitByteString(
+        boolean minePresent, ByteString mine, boolean otherPresent, ByteString other);
+
+    Object visitOneofBoolean(boolean minePresent, Object mine, Object other);
+    Object visitOneofInt(boolean minePresent, Object mine, Object other);
+    Object visitOneofDouble(boolean minePresent, Object mine, Object other);
+    Object visitOneofFloat(boolean minePresent, Object mine, Object other);
+    Object visitOneofLong(boolean minePresent, Object mine, Object other);
+    Object visitOneofString(boolean minePresent, Object mine, Object other);
+    Object visitOneofByteString(boolean minePresent, Object mine, Object other);
+    Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other);
+    Object visitOneofMessage(boolean minePresent, Object mine, Object other);
+    void visitOneofNotSet(boolean minePresent);
+    
+    /**
+     * Message fields use null sentinals.
+     */
+    <T extends MessageLite> T visitMessage(T mine, T other);
+    LazyFieldLite visitLazyMessage(
+        boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other);
+
+    <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other);
+    BooleanList visitBooleanList(BooleanList mine, BooleanList other);
+    IntList visitIntList(IntList mine, IntList other);
+    DoubleList visitDoubleList(DoubleList mine, DoubleList other);
+    FloatList visitFloatList(FloatList mine, FloatList other);
+    LongList visitLongList(LongList mine, LongList other);
+    FieldSet<ExtensionDescriptor> visitExtensions(
+        FieldSet<ExtensionDescriptor> mine, FieldSet<ExtensionDescriptor> other);
+    UnknownFieldSetLite visitUnknownFields(UnknownFieldSetLite mine, UnknownFieldSetLite other);
+    <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other);
+  }
+
+  /**
+   * Implements equals. Throws a {@link NotEqualsException} when not equal.
+   */
+  static class EqualsVisitor implements Visitor {
+
+    static final class NotEqualsException extends RuntimeException {}
+
+    static final EqualsVisitor INSTANCE = new EqualsVisitor();
+
+    static final NotEqualsException NOT_EQUALS = new NotEqualsException();
+
+    private EqualsVisitor() {}
+
+    @Override
+    public boolean visitBoolean(
+        boolean minePresent, boolean mine, boolean otherPresent, boolean other) {
+      if (minePresent != otherPresent || mine != other) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public int visitInt(boolean minePresent, int mine, boolean otherPresent, int other) {
+      if (minePresent != otherPresent || mine != other) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public double visitDouble(
+        boolean minePresent, double mine, boolean otherPresent, double other) {
+      if (minePresent != otherPresent || mine != other) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other) {
+      if (minePresent != otherPresent || mine != other) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public long visitLong(boolean minePresent, long mine, boolean otherPresent, long other) {
+      if (minePresent != otherPresent || mine != other) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public String visitString(
+        boolean minePresent, String mine, boolean otherPresent, String other) {
+      if (minePresent != otherPresent || !mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public ByteString visitByteString(
+        boolean minePresent, ByteString mine, boolean otherPresent, ByteString other) {
+      if (minePresent != otherPresent || !mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofBoolean(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public Object visitOneofInt(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public Object visitOneofDouble(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public Object visitOneofFloat(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public Object visitOneofLong(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public Object visitOneofString(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public Object visitOneofByteString(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
+      if (minePresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+    
+    @Override
+    public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
+      if (minePresent && ((GeneratedMessageLite<?, ?>) mine).equals(this, (MessageLite) other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+    
+    @Override
+    public void visitOneofNotSet(boolean minePresent) {
+      if (minePresent) {
+        throw NOT_EQUALS;
+      }
+    }
+
+    @Override
+    public <T extends MessageLite> T visitMessage(T mine, T other) {
+      if (mine == null && other == null) {
+        return null;
+      }
+
+      if (mine == null || other == null) {
+        throw NOT_EQUALS;
+      }
+
+      ((GeneratedMessageLite<?, ?>) mine).equals(this, other);
+
+      return mine;
+    }
+    
+    @Override
+    public LazyFieldLite visitLazyMessage(
+        boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other) {
+      if (!minePresent && !otherPresent) {
+        return mine;
+      } else if (minePresent && otherPresent && mine.equals(other)) {
+        return mine;
+      }
+      throw NOT_EQUALS;
+    }
+
+    @Override
+    public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public BooleanList visitBooleanList(BooleanList mine, BooleanList other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public IntList visitIntList(IntList mine, IntList other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public DoubleList visitDoubleList(DoubleList mine, DoubleList other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public FloatList visitFloatList(FloatList mine, FloatList other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public LongList visitLongList(LongList mine, LongList other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public FieldSet<ExtensionDescriptor> visitExtensions(
+        FieldSet<ExtensionDescriptor> mine,
+        FieldSet<ExtensionDescriptor> other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public UnknownFieldSetLite visitUnknownFields(
+        UnknownFieldSetLite mine,
+        UnknownFieldSetLite other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+
+    @Override
+    public <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other) {
+      if (!mine.equals(other)) {
+        throw NOT_EQUALS;
+      }
+      return mine;
+    }
+  }
+
+  /**
+   * Implements hashCode by accumulating state.
+   */
+  private static class HashCodeVisitor implements Visitor {
+
+    // The caller must ensure that the visitor is invoked parameterized with this and this such that
+    // other is this. This is required due to how oneof cases are handled. See the class comment
+    // on Visitor for more information.
+    
+    private int hashCode = 0;
+
+    @Override
+    public boolean visitBoolean(
+        boolean minePresent, boolean mine, boolean otherPresent, boolean other) {
+      hashCode = (53 * hashCode) + Internal.hashBoolean(mine);
+      return mine;
+    }
+
+    @Override
+    public int visitInt(boolean minePresent, int mine, boolean otherPresent, int other) {
+      hashCode = (53 * hashCode) + mine;
+      return mine;
+    }
+
+    @Override
+    public double visitDouble(
+        boolean minePresent, double mine, boolean otherPresent, double other) {
+      hashCode = (53 * hashCode) + Internal.hashLong(Double.doubleToLongBits(mine));
+      return mine;
+    }
+
+    @Override
+    public float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other) {
+      hashCode = (53 * hashCode) + Float.floatToIntBits(mine);
+      return mine;
+    }
+
+    @Override
+    public long visitLong(boolean minePresent, long mine, boolean otherPresent, long other) {
+      hashCode = (53 * hashCode) + Internal.hashLong(mine);
+      return mine;
+    }
+
+    @Override
+    public String visitString(
+        boolean minePresent, String mine, boolean otherPresent, String other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public ByteString visitByteString(
+        boolean minePresent, ByteString mine, boolean otherPresent, ByteString other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofBoolean(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + Internal.hashBoolean(((Boolean) mine));
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofInt(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + (Integer) mine;
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofDouble(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + Internal.hashLong(Double.doubleToLongBits((Double) mine));
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofFloat(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + Float.floatToIntBits((Float) mine);
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofLong(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + Internal.hashLong((Long) mine);
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofString(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofByteString(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+    
+    @Override
+    public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
+      return visitMessage((MessageLite) mine, (MessageLite) other);
+    }
+
+    @Override
+    public void visitOneofNotSet(boolean minePresent) {
+      if (minePresent) {
+        throw new IllegalStateException(); // Can't happen if other == this. 
+      }
+    }
+
+    @Override
+    public <T extends MessageLite> T visitMessage(T mine, T other) {
+      final int protoHash;
+      if (mine != null) {
+        if (mine instanceof GeneratedMessageLite) {
+          protoHash = ((GeneratedMessageLite) mine).hashCode(this);
+        } else {
+          protoHash = mine.hashCode();
+        }
+      } else {
+        protoHash = 37;
+      }
+      hashCode = (53 * hashCode) + protoHash;
+      return mine;
+    }
+
+    @Override
+    public LazyFieldLite visitLazyMessage(
+        boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public BooleanList visitBooleanList(BooleanList mine, BooleanList other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public IntList visitIntList(IntList mine, IntList other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public DoubleList visitDoubleList(DoubleList mine, DoubleList other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public FloatList visitFloatList(FloatList mine, FloatList other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public LongList visitLongList(LongList mine, LongList other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public FieldSet<ExtensionDescriptor> visitExtensions(
+        FieldSet<ExtensionDescriptor> mine,
+        FieldSet<ExtensionDescriptor> other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+
+    @Override
+    public UnknownFieldSetLite visitUnknownFields(
+        UnknownFieldSetLite mine,
+        UnknownFieldSetLite other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+    
+    @Override
+    public <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other) {
+      hashCode = (53 * hashCode) + mine.hashCode();
+      return mine;
+    }
+  }
+
+  /**
+   * Implements field merging semantics over the visitor interface.
+   */
+  protected static class MergeFromVisitor implements Visitor {
+
+    public static final MergeFromVisitor INSTANCE = new MergeFromVisitor();
+
+    private MergeFromVisitor() {}
+
+    @Override
+    public boolean visitBoolean(
+        boolean minePresent, boolean mine, boolean otherPresent, boolean other) {
+      return otherPresent ? other : mine;
+    }
+
+    @Override
+    public int visitInt(boolean minePresent, int mine, boolean otherPresent, int other) {
+      return otherPresent ? other : mine;
+    }
+
+    @Override
+    public double visitDouble(
+        boolean minePresent, double mine, boolean otherPresent, double other) {
+      return otherPresent ? other : mine;
+    }
+
+    @Override
+    public float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other) {
+      return otherPresent ? other : mine;
+    }
+
+    @Override
+    public long visitLong(boolean minePresent, long mine, boolean otherPresent, long other) {
+      return otherPresent ? other : mine;
+    }
+
+    @Override
+    public String visitString(
+        boolean minePresent, String mine, boolean otherPresent, String other) {
+      return otherPresent ? other : mine;
+    }
+
+    @Override
+    public ByteString visitByteString(
+        boolean minePresent, ByteString mine, boolean otherPresent, ByteString other) {
+      return otherPresent ? other : mine;
+    }
+
+    @Override
+    public Object visitOneofBoolean(boolean minePresent, Object mine, Object other) {
+      return other;
+    }
+
+    @Override
+    public Object visitOneofInt(boolean minePresent, Object mine, Object other) {
+      return other;
+    }
+
+    @Override
+    public Object visitOneofDouble(boolean minePresent, Object mine, Object other) {
+      return other;      
+    }
+
+    @Override
+    public Object visitOneofFloat(boolean minePresent, Object mine, Object other) {
+      return other;
+    }
+
+    @Override
+    public Object visitOneofLong(boolean minePresent, Object mine, Object other) {
+      return other;      
+    }
+
+    @Override
+    public Object visitOneofString(boolean minePresent, Object mine, Object other) {
+      return other;      
+    }
+
+    @Override
+    public Object visitOneofByteString(boolean minePresent, Object mine, Object other) {
+      return other;      
+    }
+
+    @Override
+    public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
+      if (minePresent) {
+        LazyFieldLite lazy = (LazyFieldLite) mine;
+        lazy.merge((LazyFieldLite) other);
+        return lazy;
+      }
+      return other;
+    }
+    
+    @Override
+    public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
+      if (minePresent) {
+        return visitMessage((MessageLite) mine, (MessageLite) other);
+      }
+      return other;
+    }
+    
+    @Override
+    public void visitOneofNotSet(boolean minePresent) {
+      return;
+    }
+
+    @SuppressWarnings("unchecked") // Guaranteed by runtime.
+    @Override
+    public <T extends MessageLite> T visitMessage(T mine, T other) {
+      if (mine != null && other != null) {
+        return (T) mine.toBuilder().mergeFrom(other).build();
+      }
+
+      return mine != null ? mine : other;
+    }
+
+    @Override
+    public LazyFieldLite visitLazyMessage(
+        boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other) {
+      // LazyFieldLite's are never null so we can just copy across. Necessary to avoid leakage
+      // from builder into immutable message.
+      // TODO(dweis): Change to null sentinels?
+      mine.merge(other);
+      return mine;
+    }
+
+    @Override
+    public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
+      int size = mine.size();
+      int otherSize = other.size();
+      if (size > 0 && otherSize > 0) {
+        if (!mine.isModifiable()) {
+          mine = mine.mutableCopyWithCapacity(size + otherSize);
+        }
+        mine.addAll(other);
+      }
+      
+      return size > 0 ? mine : other;
+    }
+
+    @Override
+    public BooleanList visitBooleanList(BooleanList mine, BooleanList other) {
+      int size = mine.size();
+      int otherSize = other.size();
+      if (size > 0 && otherSize > 0) {
+        if (!mine.isModifiable()) {
+          mine = mine.mutableCopyWithCapacity(size + otherSize);
+        }
+        mine.addAll(other);
+      }
+      
+      return size > 0 ? mine : other;
+    }
+
+    @Override
+    public IntList visitIntList(IntList mine, IntList other) {
+      int size = mine.size();
+      int otherSize = other.size();
+      if (size > 0 && otherSize > 0) {
+        if (!mine.isModifiable()) {
+          mine = mine.mutableCopyWithCapacity(size + otherSize);
+        }
+        mine.addAll(other);
+      }
+      
+      return size > 0 ? mine : other;
+    }
+
+    @Override
+    public DoubleList visitDoubleList(DoubleList mine, DoubleList other) {
+      int size = mine.size();
+      int otherSize = other.size();
+      if (size > 0 && otherSize > 0) {
+        if (!mine.isModifiable()) {
+          mine = mine.mutableCopyWithCapacity(size + otherSize);
+        }
+        mine.addAll(other);
+      }
+      
+      return size > 0 ? mine : other;
+    }
+
+    @Override
+    public FloatList visitFloatList(FloatList mine, FloatList other) {
+      int size = mine.size();
+      int otherSize = other.size();
+      if (size > 0 && otherSize > 0) {
+        if (!mine.isModifiable()) {
+          mine = mine.mutableCopyWithCapacity(size + otherSize);
+        }
+        mine.addAll(other);
+      }
+      
+      return size > 0 ? mine : other;
+    }
+
+    @Override
+    public LongList visitLongList(LongList mine, LongList other) {
+      int size = mine.size();
+      int otherSize = other.size();
+      if (size > 0 && otherSize > 0) {
+        if (!mine.isModifiable()) {
+          mine = mine.mutableCopyWithCapacity(size + otherSize);
+        }
+        mine.addAll(other);
+      }
+      
+      return size > 0 ? mine : other;
+    }
+
+    @Override
+    public FieldSet<ExtensionDescriptor> visitExtensions(
+        FieldSet<ExtensionDescriptor> mine,
+        FieldSet<ExtensionDescriptor> other) {
+      if (mine.isImmutable()) {
+        mine = mine.clone();
+      }
+      mine.mergeFrom(other);
+      return mine;
+    }
+
+    @Override
+    public UnknownFieldSetLite visitUnknownFields(
+        UnknownFieldSetLite mine,
+        UnknownFieldSetLite other) {
+      return other == UnknownFieldSetLite.getDefaultInstance()
+          ? mine : UnknownFieldSetLite.mutableCopyOf(mine, other);
+    }
+    
+    @Override
+    public <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other) {
+      mine.mergeFrom(other);
+      return mine;
+    }
+  }
 }

+ 42 - 22
java/core/src/main/java/com/google/protobuf/IntArrayList.java

@@ -34,7 +34,6 @@ import com.google.protobuf.Internal.IntList;
 
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.List;
 import java.util.RandomAccess;
 
 /**
@@ -44,8 +43,6 @@ import java.util.RandomAccess;
  */
 final class IntArrayList extends AbstractProtobufList<Integer> implements IntList, RandomAccess {
   
-  private static final int DEFAULT_CAPACITY = 10;
-  
   private static final IntArrayList EMPTY_LIST = new IntArrayList();
   static {
     EMPTY_LIST.makeImmutable();
@@ -70,32 +67,55 @@ final class IntArrayList extends AbstractProtobufList<Integer> implements IntLis
    * Constructs a new mutable {@code IntArrayList} with default capacity.
    */
   IntArrayList() {
-    this(DEFAULT_CAPACITY);
-  }
-
-  /**
-   * Constructs a new mutable {@code IntArrayList} with the provided capacity.
-   */
-  IntArrayList(int capacity) {
-    array = new int[capacity];
-    size = 0;
+    this(new int[DEFAULT_CAPACITY], 0);
   }
 
   /**
    * Constructs a new mutable {@code IntArrayList} containing the same elements as {@code other}.
    */
-  IntArrayList(List<Integer> other) {
-    if (other instanceof IntArrayList) {
-      IntArrayList list = (IntArrayList) other;
-      array = list.array.clone();
-      size = list.size;
-    } else {
-      size = other.size();
-      array = new int[size];
-      for (int i = 0; i < size; i++) {
-        array[i] = other.get(i);
+  private IntArrayList(int[] array, int size) {
+    this.array = array;
+    this.size = size;
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof IntArrayList)) {
+      return super.equals(o);
+    }
+    IntArrayList other = (IntArrayList) o;
+    if (size != other.size) {
+      return false;
+    }
+    
+    final int[] arr = other.array;
+    for (int i = 0; i < size; i++) {
+      if (array[i] != arr[i]) {
+        return false;
       }
     }
+    
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = 1;
+    for (int i = 0; i < size; i++) {
+      result = (31 * result) + array[i];
+    }
+    return result;
+  }
+
+  @Override
+  public IntList mutableCopyWithCapacity(int capacity) {
+    if (capacity < size) {
+      throw new IllegalArgumentException();
+    }
+    return new IntArrayList(Arrays.copyOf(array, capacity), size);
   }
   
   @Override

+ 52 - 11
java/core/src/main/java/com/google/protobuf/Internal.java

@@ -41,6 +41,7 @@ import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.RandomAccess;
 import java.util.Set;
 
 /**
@@ -457,10 +458,13 @@ public final class Internal {
     public static <T extends EnumLite> Converter<Integer, T> newEnumConverter(
         final EnumLiteMap<T> enumMap, final T unrecognizedValue) {
       return new Converter<Integer, T>() {
+        @Override
         public T doForward(Integer value) {
           T result = enumMap.findValueByNumber(value);
           return result == null ? unrecognizedValue : result;
         }
+
+        @Override
         public Integer doBackward(T value) {
           return value.getNumber();
         }
@@ -573,8 +577,10 @@ public final class Internal {
   /**
    * Extends {@link List} to add the capability to make the list immutable and inspect if it is
    * modifiable.
+   * <p>
+   * All implementations must support efficient random access.
    */
-  public static interface ProtobufList<E> extends List<E> {
+  public static interface ProtobufList<E> extends List<E>, RandomAccess {
 
     /**
      * Makes this list immutable. All subsequent modifications will throw an
@@ -586,6 +592,11 @@ public final class Internal {
      * Returns whether this list can be modified via the publicly accessible {@link List} methods.
      */
     boolean isModifiable();
+
+    /**
+     * Returns a mutable clone of this list with the specified capacity.
+     */
+    ProtobufList<E> mutableCopyWithCapacity(int capacity);
   }
 
   /**
@@ -600,14 +611,20 @@ public final class Internal {
     int getInt(int index);
 
     /**
-     * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
+     * Like {@link #add(Integer)} but more efficient in that it doesn't box the element.
      */
     void addInt(int element);
 
     /**
-     * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
+     * Like {@link #set(int, Integer)} but more efficient in that it doesn't box the element.
      */
     int setInt(int index, int element);
+
+    /**
+     * Returns a mutable clone of this list with the specified capacity.
+     */
+    @Override
+    IntList mutableCopyWithCapacity(int capacity);
   }
 
   /**
@@ -622,14 +639,20 @@ public final class Internal {
     boolean getBoolean(int index);
 
     /**
-     * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
+     * Like {@link #add(Boolean)} but more efficient in that it doesn't box the element.
      */
     void addBoolean(boolean element);
 
     /**
-     * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
+     * Like {@link #set(int, Boolean)} but more efficient in that it doesn't box the element.
      */
     boolean setBoolean(int index, boolean element);
+
+    /**
+     * Returns a mutable clone of this list with the specified capacity.
+     */
+    @Override
+    BooleanList mutableCopyWithCapacity(int capacity);
   }
 
   /**
@@ -644,14 +667,20 @@ public final class Internal {
     long getLong(int index);
 
     /**
-     * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
+     * Like {@link #add(Long)} but more efficient in that it doesn't box the element.
      */
     void addLong(long element);
 
     /**
-     * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
+     * Like {@link #set(int, Long)} but more efficient in that it doesn't box the element.
      */
     long setLong(int index, long element);
+
+    /**
+     * Returns a mutable clone of this list with the specified capacity.
+     */
+    @Override
+    LongList mutableCopyWithCapacity(int capacity);
   }
 
   /**
@@ -666,14 +695,20 @@ public final class Internal {
     double getDouble(int index);
 
     /**
-     * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
+     * Like {@link #add(Double)} but more efficient in that it doesn't box the element.
      */
     void addDouble(double element);
 
     /**
-     * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
+     * Like {@link #set(int, Double)} but more efficient in that it doesn't box the element.
      */
     double setDouble(int index, double element);
+
+    /**
+     * Returns a mutable clone of this list with the specified capacity.
+     */
+    @Override
+    DoubleList mutableCopyWithCapacity(int capacity);
   }
 
   /**
@@ -688,13 +723,19 @@ public final class Internal {
     float getFloat(int index);
 
     /**
-     * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
+     * Like {@link #add(Float)} but more efficient in that it doesn't box the element.
      */
     void addFloat(float element);
 
     /**
-     * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
+     * Like {@link #set(int, Float)} but more efficient in that it doesn't box the element.
      */
     float setFloat(int index, float element);
+
+    /**
+     * Returns a mutable clone of this list with the specified capacity.
+     */
+    @Override
+    FloatList mutableCopyWithCapacity(int capacity);
   }
 }

+ 6 - 6
java/core/src/main/java/com/google/protobuf/LazyField.java

@@ -95,12 +95,12 @@ public class LazyField extends LazyFieldLite {
       this.entry = entry;
     }
 
-    // @Override
+    @Override
     public K getKey() {
       return entry.getKey();
     }
 
-    // @Override
+    @Override
     public Object getValue() {
       LazyField field = entry.getValue();
       if (field == null) {
@@ -113,7 +113,7 @@ public class LazyField extends LazyFieldLite {
       return entry.getValue();
     }
 
-    // @Override
+    @Override
     public Object setValue(Object value) {
       if (!(value instanceof MessageLite)) {
         throw new IllegalArgumentException(
@@ -131,13 +131,13 @@ public class LazyField extends LazyFieldLite {
       this.iterator = iterator;
     }
 
-    // @Override
+    @Override
     public boolean hasNext() {
       return iterator.hasNext();
     }
 
+    @Override
     @SuppressWarnings("unchecked")
-    // @Override
     public Entry<K, Object> next() {
       Entry<K, ?> entry = iterator.next();
       if (entry.getValue() instanceof LazyField) {
@@ -146,7 +146,7 @@ public class LazyField extends LazyFieldLite {
       return (Entry<K, Object>) entry;
     }
 
-    // @Override
+    @Override
     public void remove() {
       iterator.remove();
     }

+ 41 - 0
java/core/src/main/java/com/google/protobuf/LazyFieldLite.java

@@ -135,6 +135,43 @@ public class LazyFieldLite {
     return lf;
   }
 
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    
+    if (!(o instanceof LazyFieldLite)) {
+      return false;
+    }
+
+    LazyFieldLite other = (LazyFieldLite) o;
+    
+    // Lazy fields do not work well with equals... If both are delayedBytes, we do not have a
+    // mechanism to deserialize them so we rely on bytes equality. Otherwise we coerce into an
+    // actual message (if necessary) and call equals on the message itself. This implies that two
+    // messages can by unequal but then be turned equal simply be invoking a getter on a lazy field.
+    MessageLite value1 = value;
+    MessageLite value2 = other.value;
+    if (value1 == null && value2 == null) {
+      return toByteString().equals(other.toByteString());
+    } else if (value1 != null && value2 != null) {
+      return value1.equals(value2);
+    } else if (value1 != null) {
+      return value1.equals(other.getValue(value1.getDefaultInstanceForType()));
+    } else {
+      return getValue(value2.getDefaultInstanceForType()).equals(value2);
+    }
+  }
+  
+  @Override
+  public int hashCode() {
+    // We can't provide a memoizable hash code for lazy fields. The byte strings may have different
+    // hash codes but evaluate to equivalent messages. And we have no facility for constructing
+    // a message here if we were not already holding a value.
+    return 1;
+  }
+  
   /**
    * Determines whether this LazyFieldLite instance represents the default instance of this type.
    */
@@ -340,6 +377,8 @@ public class LazyFieldLite {
    * parsed. Be careful when using this method.
    */
   public int getSerializedSize() {
+    // We *must* return delayed bytes size if it was ever set because the dependent messages may
+    // have memoized serialized size based off of it.
     if (memoizedBytes != null) {
       return memoizedBytes.size();
     } else if (delayedBytes != null) {
@@ -358,6 +397,8 @@ public class LazyFieldLite {
     if (memoizedBytes != null) {
       return memoizedBytes;
     }
+    // We *must* return delayed bytes if it was set because the dependent messages may have
+    // memoized serialized size based off of it.
     if (delayedBytes != null) {
       return delayedBytes;
     }

+ 31 - 17
java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java

@@ -64,7 +64,7 @@ import java.util.RandomAccess;
  */
 public class LazyStringArrayList extends AbstractProtobufList<String>
     implements LazyStringList, RandomAccess {
-  
+
   private static final LazyStringArrayList EMPTY_LIST = new LazyStringArrayList();
   static {
     EMPTY_LIST.makeImmutable();
@@ -80,11 +80,11 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
   private final List<Object> list;
 
   public LazyStringArrayList() {
-    list = new ArrayList<Object>();
+    this(DEFAULT_CAPACITY);
   }
 
   public LazyStringArrayList(int intialCapacity) {
-    list = new ArrayList<Object>(intialCapacity);
+    this(new ArrayList<Object>(intialCapacity));
   }
 
   public LazyStringArrayList(LazyStringList from) {
@@ -93,7 +93,21 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
   }
 
   public LazyStringArrayList(List<String> from) {
-    list = new ArrayList<Object>(from);
+    this(new ArrayList<Object>(from));
+  }
+  
+  private LazyStringArrayList(ArrayList<Object> list) {
+    this.list = list;
+  }
+
+  @Override
+  public LazyStringArrayList mutableCopyWithCapacity(int capacity) {
+    if (capacity < size()) {
+      throw new IllegalArgumentException();
+    }
+    ArrayList<Object> newList = new ArrayList<Object>(capacity);
+    newList.addAll(list);
+    return new LazyStringArrayList(newList);
   }
 
   @Override
@@ -170,7 +184,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
     return ret;
   }
 
-  // @Override
+  @Override
   public boolean addAllByteString(Collection<? extends ByteString> values) {
     ensureIsMutable();
     boolean ret = list.addAll(values);
@@ -178,7 +192,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
     return ret;
   }
 
-  // @Override
+  @Override
   public boolean addAllByteArray(Collection<byte[]> c) {
     ensureIsMutable();
     boolean ret = list.addAll(c);
@@ -201,14 +215,14 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
     modCount++;
   }
 
-  // @Override
+  @Override
   public void add(ByteString element) {
     ensureIsMutable();
     list.add(element);
     modCount++;
   }
   
-  // @Override
+  @Override
   public void add(byte[] element) {
     ensureIsMutable();
     list.add(element);
@@ -220,7 +234,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
     return list.get(index);
   }
   
-  // @Override
+  @Override
   public ByteString getByteString(int index) {
     Object o = list.get(index);
     ByteString b = asByteString(o);
@@ -230,7 +244,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
     return b;
   }
   
-  // @Override
+  @Override
   public byte[] getByteArray(int index) {
     Object o = list.get(index);
     byte[] b = asByteArray(o);
@@ -240,7 +254,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
     return b;
   }
 
-  // @Override
+  @Override
   public void set(int index, ByteString s) {
     setAndReturn(index, s);
   }
@@ -250,7 +264,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
     return list.set(index, s);
   }
 
-  // @Override
+  @Override
   public void set(int index, byte[] s) {
     setAndReturn(index, s);
   }
@@ -290,12 +304,12 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
     }
   }
 
-  // @Override
+  @Override
   public List<?> getUnderlyingElements() {
     return Collections.unmodifiableList(list);
   }
 
-  // @Override
+  @Override
   public void mergeFrom(LazyStringList other) {
     ensureIsMutable();
     for (Object o : other.getUnderlyingElements()) {
@@ -349,7 +363,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
     }
   }
   
-  // @Override
+  @Override
   public List<byte[]> asByteArrayList() {
     return new ByteArrayListView(this);
   }
@@ -393,12 +407,12 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
     }
   }
 
-  // @Override
+  @Override
   public List<ByteString> asByteStringList() {
     return new ByteStringListView(this);
   }
 
-  // @Override
+  @Override
   public LazyStringList getUnmodifiableView() {
     if (isModifiable()) {
       return new UnmodifiableLazyStringList(this);

+ 42 - 22
java/core/src/main/java/com/google/protobuf/LongArrayList.java

@@ -34,7 +34,6 @@ import com.google.protobuf.Internal.LongList;
 
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.List;
 import java.util.RandomAccess;
 
 /**
@@ -44,8 +43,6 @@ import java.util.RandomAccess;
  */
 final class LongArrayList extends AbstractProtobufList<Long> implements LongList, RandomAccess {
   
-  private static final int DEFAULT_CAPACITY = 10;
-  
   private static final LongArrayList EMPTY_LIST = new LongArrayList();
   static {
     EMPTY_LIST.makeImmutable();
@@ -70,32 +67,55 @@ final class LongArrayList extends AbstractProtobufList<Long> implements LongList
    * Constructs a new mutable {@code LongArrayList} with default capacity.
    */
   LongArrayList() {
-    this(DEFAULT_CAPACITY);
-  }
-
-  /**
-   * Constructs a new mutable {@code LongArrayList} with the provided capacity.
-   */
-  LongArrayList(int capacity) {
-    array = new long[capacity];
-    size = 0;
+    this(new long[DEFAULT_CAPACITY], 0);
   }
 
   /**
    * Constructs a new mutable {@code LongArrayList} containing the same elements as {@code other}.
    */
-  LongArrayList(List<Long> other) {
-    if (other instanceof LongArrayList) {
-      LongArrayList list = (LongArrayList) other;
-      array = list.array.clone();
-      size = list.size;
-    } else {
-      size = other.size();
-      array = new long[size];
-      for (int i = 0; i < size; i++) {
-        array[i] = other.get(i);
+  private LongArrayList(long[] array, int size) {
+    this.array = array;
+    this.size = size;
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof IntArrayList)) {
+      return super.equals(o);
+    }
+    LongArrayList other = (LongArrayList) o;
+    if (size != other.size) {
+      return false;
+    }
+    
+    final long[] arr = other.array;
+    for (int i = 0; i < size; i++) {
+      if (array[i] != arr[i]) {
+        return false;
       }
     }
+    
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = 1;
+    for (int i = 0; i < size; i++) {
+      result = (31 * result) + Internal.hashLong(array[i]);
+    }
+    return result;
+  }
+
+  @Override
+  public LongList mutableCopyWithCapacity(int capacity) {
+    if (capacity < size) {
+      throw new IllegalArgumentException();
+    }
+    return new LongArrayList(Arrays.copyOf(array, capacity), size);
   }
   
   @Override

+ 8 - 2
java/core/src/main/java/com/google/protobuf/MapEntryLite.java

@@ -41,7 +41,8 @@ import java.io.IOException;
  * 
  * Protobuf internal. Users shouldn't use.
  */
-public class MapEntryLite<K, V> extends AbstractMessageLite {
+public class MapEntryLite<K, V>
+    extends AbstractMessageLite<MapEntryLite<K, V>, MapEntryLite.Builder<K, V>> {
   private static class Metadata<K, V> {
     public final MapEntryLite<K, V> defaultInstance;
     public final WireFormat.FieldType keyType;
@@ -233,7 +234,7 @@ public class MapEntryLite<K, V> extends AbstractMessageLite {
    * Builder used to create {@link MapEntryLite} messages.
    */
   public static class Builder<K, V>
-      extends AbstractMessageLite.Builder<Builder<K, V>> {
+      extends AbstractMessageLite.Builder<MapEntryLite<K, V>, Builder<K, V>> {
     private final Metadata<K, V> metadata;
     private K key;
     private V value;
@@ -327,5 +328,10 @@ public class MapEntryLite<K, V> extends AbstractMessageLite {
       this.value = entry.value;
       return this;
     }
+
+    @Override
+    protected Builder<K, V> internalMergeFrom(MapEntryLite<K, V> message) {
+      throw new UnsupportedOperationException();
+    }
   }
 }

+ 3 - 0
java/core/src/main/java/com/google/protobuf/MapField.java

@@ -93,15 +93,18 @@ public class MapField<K, V> implements MutabilityOracle {
       this.defaultEntry = defaultEntry;
     }
     
+    @Override
     public Message convertKeyAndValueToMessage(K key, V value) {
       return defaultEntry.newBuilderForType().setKey(key).setValue(value).buildPartial();
     }
     
+    @Override
     public void convertMessageToKeyAndValue(Message message, Map<K, V> map) {
       MapEntry<K, V> entry = (MapEntry<K, V>) message;
       map.put(entry.getKey(), entry.getValue());
     }
 
+    @Override
     public Message getMessageDefaultInstance() {
       return defaultEntry;
     }

+ 48 - 22
java/core/src/main/java/com/google/protobuf/Message.java

@@ -51,6 +51,7 @@ import java.util.Map;
 public interface Message extends MessageLite, MessageOrBuilder {
 
   // (From MessageLite, re-declared here only for return type covariance.)
+  @Override
   Parser<? extends Message> getParserForType();
 
 
@@ -97,7 +98,10 @@ public interface Message extends MessageLite, MessageOrBuilder {
   // Builders
 
   // (From MessageLite, re-declared here only for return type covariance.)
+  @Override
   Builder newBuilderForType();
+
+  @Override
   Builder toBuilder();
 
   /**
@@ -106,6 +110,7 @@ public interface Message extends MessageLite, MessageOrBuilder {
   interface Builder extends MessageLite.Builder, MessageOrBuilder {
     // (From MessageLite.Builder, re-declared here only for return type
     // covariance.)
+    @Override
     Builder clear();
 
     /**
@@ -131,18 +136,27 @@ public interface Message extends MessageLite, MessageOrBuilder {
 
     // (From MessageLite.Builder, re-declared here only for return type
     // covariance.)
+    @Override
     Message build();
+
+    @Override
     Message buildPartial();
+
+    @Override
     Builder clone();
+
+    @Override
     Builder mergeFrom(CodedInputStream input) throws IOException;
-    Builder mergeFrom(CodedInputStream input,
-                      ExtensionRegistryLite extensionRegistry)
-                      throws IOException;
+
+    @Override
+    Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+        throws IOException;
 
     /**
      * Get the message's type's descriptor.
      * See {@link Message#getDescriptorForType()}.
      */
+    @Override
     Descriptors.Descriptor getDescriptorForType();
 
     /**
@@ -240,27 +254,39 @@ public interface Message extends MessageLite, MessageOrBuilder {
 
     // (From MessageLite.Builder, re-declared here only for return type
     // covariance.)
+    @Override
     Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
-    Builder mergeFrom(ByteString data,
-                      ExtensionRegistryLite extensionRegistry)
-                      throws InvalidProtocolBufferException;
+
+    @Override
+    Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException;
+
+    @Override
     Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
-    Builder mergeFrom(byte[] data, int off, int len)
-                      throws InvalidProtocolBufferException;
-    Builder mergeFrom(byte[] data,
-                      ExtensionRegistryLite extensionRegistry)
-                      throws InvalidProtocolBufferException;
-    Builder mergeFrom(byte[] data, int off, int len,
-                      ExtensionRegistryLite extensionRegistry)
-                      throws InvalidProtocolBufferException;
+
+    @Override
+    Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException;
+
+    @Override
+    Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException;
+
+    @Override
+    Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException;
+
+    @Override
     Builder mergeFrom(InputStream input) throws IOException;
-    Builder mergeFrom(InputStream input,
-                      ExtensionRegistryLite extensionRegistry)
-                      throws IOException;
-    boolean mergeDelimitedFrom(InputStream input)
-                               throws IOException;
-    boolean mergeDelimitedFrom(InputStream input,
-                               ExtensionRegistryLite extensionRegistry)
-                               throws IOException;
+
+    @Override
+    Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+        throws IOException;
+
+    @Override
+    boolean mergeDelimitedFrom(InputStream input) throws IOException;
+
+    @Override
+    boolean mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+        throws IOException;
   }
 }

+ 21 - 0
java/core/src/main/java/com/google/protobuf/MessageLite.java

@@ -295,6 +295,27 @@ public interface MessageLite extends MessageLiteOrBuilder {
     Builder mergeFrom(InputStream input,
                       ExtensionRegistryLite extensionRegistry)
                       throws IOException;
+    
+    /**
+     * Merge {@code other} into the message being built.  {@code other} must
+     * have the exact same type as {@code this} (i.e.
+     * {@code getClass().equals(getDefaultInstanceForType().getClass())}).
+     *
+     * Merging occurs as follows.  For each field:<br>
+     * * For singular primitive fields, if the field is set in {@code other},
+     *   then {@code other}'s value overwrites the value in this message.<br>
+     * * For singular message fields, if the field is set in {@code other},
+     *   it is merged into the corresponding sub-message of this message
+     *   using the same merging rules.<br>
+     * * For repeated fields, the elements in {@code other} are concatenated
+     *   with the elements in this message.
+     * * For oneof groups, if the other message has one of the fields set,
+     *   the group of this message is cleared and replaced by the field
+     *   of the other message, so that the oneof constraint is preserved.
+     *
+     * This is equivalent to the {@code Message::MergeFrom} method in C++.
+     */
+    Builder mergeFrom(MessageLite other);
 
     /**
      * Like {@link #mergeFrom(InputStream)}, but does not read until EOF.

+ 95 - 56
java/core/src/main/java/com/google/protobuf/MessageLiteToString.java

@@ -30,23 +30,24 @@
 
 package com.google.protobuf;
 
-import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
 
 /**
  * Helps generate {@link String} representations of {@link MessageLite} protos.
  */
+// TODO(dweis): Fix map fields.
 final class MessageLiteToString {
-  /**
-   * Suffix for *_FIELD_NUMBER fields. This is used to reflectively detect proto fields that should
-   * be toString()ed.
-   */
-  private static final String FIELD_NUMBER_NAME_SUFFIX = "_FIELD_NUMBER";
 
+  private static final String LIST_SUFFIX = "List";
+  private static final String BUILDER_LIST_SUFFIX = "OrBuilderList";
+  private static final String BYTES_SUFFIX = "Bytes";
+  
   /**
    * Returns a {@link String} representation of the {@link MessageLite} object.  The first line of
    * the {@code String} representation representation includes a comment string to uniquely identify
@@ -73,52 +74,70 @@ final class MessageLiteToString {
     // Build a map of method name to method. We're looking for methods like getFoo(), hasFoo(), and
     // getFooList() which might be useful for building an object's string representation.
     Map<String, Method> nameToNoArgMethod = new HashMap<String, Method>();
+    Map<String, Method> nameToMethod = new HashMap<String, Method>();
+    Set<String> getters = new TreeSet<String>();
     for (Method method : messageLite.getClass().getDeclaredMethods()) {
+      nameToMethod.put(method.getName(), method);
       if (method.getParameterTypes().length == 0) {
         nameToNoArgMethod.put(method.getName(), method);
+
+        if (method.getName().startsWith("get")) {
+          getters.add(method.getName());
+        }
       }
     }
 
-    for (Field field : messageLite.getClass().getDeclaredFields()) {
-      String fieldName = field.getName();
-      // Skip all fields that aren't in a format like "FOO_BAR_FIELD_NUMBER"
-      if (!fieldName.endsWith(FIELD_NUMBER_NAME_SUFFIX)) {
-        continue;
+    for (String getter : getters) {
+      String suffix = getter.replaceFirst("get", "");
+      if (suffix.endsWith(LIST_SUFFIX) && !suffix.endsWith(BUILDER_LIST_SUFFIX)) {
+        String camelCase = suffix.substring(0, 1).toLowerCase()
+            + suffix.substring(1, suffix.length() - LIST_SUFFIX.length());
+        // Try to reflectively get the value and toString() the field as if it were repeated. This
+        // only works if the method names have not be proguarded out or renamed.
+        Method listMethod = nameToNoArgMethod.get("get" + suffix);
+        if (listMethod != null) {
+          printField(
+              buffer,
+              indent,
+              camelCaseToSnakeCase(camelCase),
+              GeneratedMessageLite.invokeOrDie(listMethod, messageLite));
+          continue;
+        }
       }
 
-      // For "FOO_BAR_FIELD_NUMBER" his would be "FOO_BAR"
-      String upperUnderscore =
-          fieldName.substring(0, fieldName.length() - FIELD_NUMBER_NAME_SUFFIX.length());
-
-      // For "FOO_BAR_FIELD_NUMBER" his would be "FooBar"
-      String upperCamelCaseName = upperUnderscoreToUpperCamel(upperUnderscore);
+      Method setter = nameToMethod.get("set" + suffix);
+      if (setter == null) {
+        continue;
+      }
+      if (suffix.endsWith(BYTES_SUFFIX)
+          && nameToNoArgMethod.containsKey(
+              "get" + suffix.substring(0, suffix.length() - "Bytes".length()))) {
+        // Heuristic to skip bytes based accessors for string fields.
+        continue;
+      }
+      
+      String camelCase = suffix.substring(0, 1).toLowerCase() + suffix.substring(1);
 
       // Try to reflectively get the value and toString() the field as if it were optional. This
       // only works if the method names have not be proguarded out or renamed.
-      Method getMethod = nameToNoArgMethod.get("get" + upperCamelCaseName);
-      Method hasMethod = nameToNoArgMethod.get("has" + upperCamelCaseName);
-      if (getMethod != null && hasMethod != null) {
-        if ((Boolean) GeneratedMessageLite.invokeOrDie(hasMethod, messageLite)) {
+      Method getMethod = nameToNoArgMethod.get("get" + suffix);
+      Method hasMethod = nameToNoArgMethod.get("has" + suffix);
+      // TODO(dweis): Fix proto3 semantics.
+      if (getMethod != null) {
+        Object value = GeneratedMessageLite.invokeOrDie(getMethod, messageLite);
+        final boolean hasValue = hasMethod == null
+            ? !isDefaultValue(value)
+            : (Boolean) GeneratedMessageLite.invokeOrDie(hasMethod, messageLite);
+         // TODO(dweis): This doesn't stop printing oneof case twice: value and enum style.
+        if (hasValue) {
           printField(
               buffer,
               indent,
-              upperUnderscore.toLowerCase(),
-              GeneratedMessageLite.invokeOrDie(getMethod, messageLite));
+              camelCaseToSnakeCase(camelCase),
+              value);
         }
         continue;
       }
-
-      // Try to reflectively get the value and toString() the field as if it were repeated. This
-      // only works if the method names have not be proguarded out or renamed.
-      Method listMethod = nameToNoArgMethod.get("get" + upperCamelCaseName + "List");
-      if (listMethod != null) {
-        printField(
-            buffer,
-            indent,
-            upperUnderscore.toLowerCase(),
-            GeneratedMessageLite.invokeOrDie(listMethod, messageLite));
-        continue;
-      }
     }
 
     if (messageLite instanceof GeneratedMessageLite.ExtendableMessage) {
@@ -130,10 +149,39 @@ final class MessageLiteToString {
       }
     }
 
-    if (((GeneratedMessageLite) messageLite).unknownFields != null) {
-      ((GeneratedMessageLite) messageLite).unknownFields.printWithIndent(buffer, indent);
+    if (((GeneratedMessageLite<?, ?>) messageLite).unknownFields != null) {
+      ((GeneratedMessageLite<?, ?>) messageLite).unknownFields.printWithIndent(buffer, indent);
     }
   }
+  
+  private static boolean isDefaultValue(Object o) {
+    if (o instanceof Boolean) {
+      return !((Boolean) o);
+    }
+    if (o instanceof Integer) {
+      return ((Integer) o) == 0;
+    }
+    if (o instanceof Float) {
+      return ((Float) o) == 0f;
+    }
+    if (o instanceof Double) {
+      return ((Double) o) == 0d;
+    }
+    if (o instanceof String) {
+      return o.equals("");
+    }
+    if (o instanceof ByteString) {
+      return o.equals(ByteString.EMPTY);
+    }
+    if (o instanceof MessageLite) { // Can happen in oneofs.
+      return o == ((MessageLite) o).getDefaultInstanceForType();
+    }
+    if (o instanceof java.lang.Enum<?>) { // Catches oneof enums.
+      return ((java.lang.Enum<?>) o).ordinal() == 0;
+    }
+    
+    return false;
+  }
 
   /**
    * Formats a text proto field.
@@ -166,7 +214,7 @@ final class MessageLiteToString {
       buffer.append(": \"").append(TextFormatEscaper.escapeBytes((ByteString) object)).append('"');
     } else if (object instanceof GeneratedMessageLite) {
       buffer.append(" {");
-      reflectivePrintWithIndent((GeneratedMessageLite) object, buffer, indent + 2);
+      reflectivePrintWithIndent((GeneratedMessageLite<?, ?>) object, buffer, indent + 2);
       buffer.append("\n");
       for (int i = 0; i < indent; i++) {
         buffer.append(' ');
@@ -176,25 +224,16 @@ final class MessageLiteToString {
       buffer.append(": ").append(object.toString());
     }
   }
-
-  /**
-   * A Guava-less implementation of:
-   * {@code CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, upperUnderscore)}
-   */
-  private static String upperUnderscoreToUpperCamel(String upperUnderscore) {
-    String upperCamelCaseName = "";
-    boolean nextCharacterShouldBeUpper = true;
-    for (int i = 0; i < upperUnderscore.length(); i++) {
-      char ch = upperUnderscore.charAt(i);
-      if (ch == '_') {
-        nextCharacterShouldBeUpper = true;
-      } else if (nextCharacterShouldBeUpper){
-        upperCamelCaseName += Character.toUpperCase(ch);
-        nextCharacterShouldBeUpper = false;
-      } else {
-        upperCamelCaseName += Character.toLowerCase(ch);
+  
+  private static final String camelCaseToSnakeCase(String camelCase) {
+    StringBuilder builder = new StringBuilder();
+    for (int i = 0; i < camelCase.length(); i++) {
+      char ch = camelCase.charAt(i);
+      if (Character.isUpperCase(ch)) {
+        builder.append("_");
       }
+      builder.append(Character.toLowerCase(ch));
     }
-    return upperCamelCaseName;
+    return builder.toString();
   }
 }

+ 1 - 1
java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java

@@ -42,7 +42,7 @@ import java.util.Map;
 public interface MessageOrBuilder extends MessageLiteOrBuilder {
 
   // (From MessageLite, re-declared here only for return type covariance.)
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   Message getDefaultInstanceForType();
 
   /**

+ 74 - 33
java/core/src/main/java/com/google/protobuf/MessageReflection.java

@@ -364,12 +364,14 @@ class MessageReflection {
      * Finishes the merge and returns the underlying object.
      */
     Object finish();
+    
   }
 
   static class BuilderAdapter implements MergeTarget {
 
     private final Message.Builder builder;
 
+    @Override
     public Descriptors.Descriptor getDescriptorForType() {
       return builder.getDescriptorForType();
     }
@@ -378,6 +380,7 @@ class MessageReflection {
       this.builder = builder;
     }
 
+    @Override
     public Object getField(Descriptors.FieldDescriptor field) {
       return builder.getField(field);
     }
@@ -387,25 +390,27 @@ class MessageReflection {
       return builder.hasField(field);
     }
 
-    public MergeTarget setField(Descriptors.FieldDescriptor field,
-        Object value) {
+    @Override
+    public MergeTarget setField(Descriptors.FieldDescriptor field, Object value) {
       builder.setField(field, value);
       return this;
     }
 
+    @Override
     public MergeTarget clearField(Descriptors.FieldDescriptor field) {
       builder.clearField(field);
       return this;
     }
 
+    @Override
     public MergeTarget setRepeatedField(
         Descriptors.FieldDescriptor field, int index, Object value) {
       builder.setRepeatedField(field, index, value);
       return this;
     }
 
-    public MergeTarget addRepeatedField(
-        Descriptors.FieldDescriptor field, Object value) {
+    @Override
+    public MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, Object value) {
       builder.addRepeatedField(field, value);
       return this;
     }
@@ -426,25 +431,30 @@ class MessageReflection {
       return builder.getOneofFieldDescriptor(oneof);
     }
 
+    @Override
     public ContainerType getContainerType() {
       return ContainerType.MESSAGE;
     }
 
+    @Override
     public ExtensionRegistry.ExtensionInfo findExtensionByName(
         ExtensionRegistry registry, String name) {
       return registry.findImmutableExtensionByName(name);
     }
 
+    @Override
     public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
-        ExtensionRegistry registry, Descriptors.Descriptor containingType,
-        int fieldNumber) {
+        ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber) {
       return registry.findImmutableExtensionByNumber(containingType,
           fieldNumber);
     }
 
-    public Object parseGroup(CodedInputStream input,
+    @Override
+    public Object parseGroup(
+        CodedInputStream input,
         ExtensionRegistryLite extensionRegistry,
-        Descriptors.FieldDescriptor field, Message defaultInstance)
+        Descriptors.FieldDescriptor field,
+        Message defaultInstance)
         throws IOException {
       Message.Builder subBuilder;
       // When default instance is not null. The field is an extension field.
@@ -463,9 +473,12 @@ class MessageReflection {
       return subBuilder.buildPartial();
     }
 
-    public Object parseMessage(CodedInputStream input,
+    @Override
+    public Object parseMessage(
+        CodedInputStream input,
         ExtensionRegistryLite extensionRegistry,
-        Descriptors.FieldDescriptor field, Message defaultInstance)
+        Descriptors.FieldDescriptor field,
+        Message defaultInstance)
         throws IOException {
       Message.Builder subBuilder;
       // When default instance is not null. The field is an extension field.
@@ -484,9 +497,12 @@ class MessageReflection {
       return subBuilder.buildPartial();
     }
 
-    public Object parseMessageFromBytes(ByteString bytes,
+    @Override
+    public Object parseMessageFromBytes(
+        ByteString bytes,
         ExtensionRegistryLite extensionRegistry,
-        Descriptors.FieldDescriptor field, Message defaultInstance)
+        Descriptors.FieldDescriptor field,
+        Message defaultInstance)
         throws IOException {
       Message.Builder subBuilder;
       // When default instance is not null. The field is an extension field.
@@ -505,8 +521,9 @@ class MessageReflection {
       return subBuilder.buildPartial();
     }
 
-    public MergeTarget newMergeTargetForField(Descriptors.FieldDescriptor field,
-        Message defaultInstance) {
+    @Override
+    public MergeTarget newMergeTargetForField(
+        Descriptors.FieldDescriptor field, Message defaultInstance) {
       if (defaultInstance != null) {
         return new BuilderAdapter(
             defaultInstance.newBuilderForType());
@@ -515,8 +532,8 @@ class MessageReflection {
       }
     }
 
-    public WireFormat.Utf8Validation
-        getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
+    @Override
+    public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
       if (descriptor.needsUtf8Check()) {
         return WireFormat.Utf8Validation.STRICT;
       }
@@ -528,9 +545,11 @@ class MessageReflection {
       return WireFormat.Utf8Validation.LOOSE;
     }
 
+    @Override
     public Object finish() {
       return builder.buildPartial();
     }
+    
   }
 
 
@@ -542,38 +561,43 @@ class MessageReflection {
       this.extensions = extensions;
     }
 
+    @Override
     public Descriptors.Descriptor getDescriptorForType() {
       throw new UnsupportedOperationException(
           "getDescriptorForType() called on FieldSet object");
     }
 
+    @Override
     public Object getField(Descriptors.FieldDescriptor field) {
       return extensions.getField(field);
     }
 
+    @Override
     public boolean hasField(Descriptors.FieldDescriptor field) {
       return extensions.hasField(field);
     }
 
-    public MergeTarget setField(Descriptors.FieldDescriptor field,
-        Object value) {
+    @Override
+    public MergeTarget setField(Descriptors.FieldDescriptor field, Object value) {
       extensions.setField(field, value);
       return this;
     }
 
+    @Override
     public MergeTarget clearField(Descriptors.FieldDescriptor field) {
       extensions.clearField(field);
       return this;
     }
 
+    @Override
     public MergeTarget setRepeatedField(
         Descriptors.FieldDescriptor field, int index, Object value) {
       extensions.setRepeatedField(field, index, value);
       return this;
     }
 
-    public MergeTarget addRepeatedField(
-        Descriptors.FieldDescriptor field, Object value) {
+    @Override
+    public MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, Object value) {
       extensions.addRepeatedField(field, value);
       return this;
     }
@@ -594,25 +618,31 @@ class MessageReflection {
       return null;
     }
 
+    @Override
     public ContainerType getContainerType() {
       return ContainerType.EXTENSION_SET;
     }
 
+    @Override
     public ExtensionRegistry.ExtensionInfo findExtensionByName(
         ExtensionRegistry registry, String name) {
       return registry.findImmutableExtensionByName(name);
     }
 
+    @Override
     public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
-        ExtensionRegistry registry, Descriptors.Descriptor containingType,
-        int fieldNumber) {
+        ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber) {
       return registry.findImmutableExtensionByNumber(containingType,
           fieldNumber);
     }
 
-    public Object parseGroup(CodedInputStream input,
-        ExtensionRegistryLite registry, Descriptors.FieldDescriptor field,
-        Message defaultInstance) throws IOException {
+    @Override
+    public Object parseGroup(
+        CodedInputStream input,
+        ExtensionRegistryLite registry,
+        Descriptors.FieldDescriptor field,
+        Message defaultInstance)
+        throws IOException {
       Message.Builder subBuilder =
           defaultInstance.newBuilderForType();
       if (!field.isRepeated()) {
@@ -625,9 +655,13 @@ class MessageReflection {
       return subBuilder.buildPartial();
     }
 
-    public Object parseMessage(CodedInputStream input,
-        ExtensionRegistryLite registry, Descriptors.FieldDescriptor field,
-        Message defaultInstance) throws IOException {
+    @Override
+    public Object parseMessage(
+        CodedInputStream input,
+        ExtensionRegistryLite registry,
+        Descriptors.FieldDescriptor field,
+        Message defaultInstance)
+        throws IOException {
       Message.Builder subBuilder =
           defaultInstance.newBuilderForType();
       if (!field.isRepeated()) {
@@ -640,9 +674,13 @@ class MessageReflection {
       return subBuilder.buildPartial();
     }
 
-    public Object parseMessageFromBytes(ByteString bytes,
-        ExtensionRegistryLite registry, Descriptors.FieldDescriptor field,
-        Message defaultInstance) throws IOException {
+    @Override
+    public Object parseMessageFromBytes(
+        ByteString bytes,
+        ExtensionRegistryLite registry,
+        Descriptors.FieldDescriptor field,
+        Message defaultInstance)
+        throws IOException {
       Message.Builder subBuilder =  defaultInstance.newBuilderForType();
       if (!field.isRepeated()) {
         Message originalMessage = (Message) getField(field);
@@ -654,14 +692,15 @@ class MessageReflection {
       return subBuilder.buildPartial();
     }
 
+    @Override
     public MergeTarget newMergeTargetForField(
         Descriptors.FieldDescriptor descriptor, Message defaultInstance) {
       throw new UnsupportedOperationException(
           "newMergeTargetForField() called on FieldSet object");
     }
 
-    public WireFormat.Utf8Validation
-        getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
+    @Override
+    public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
       if (descriptor.needsUtf8Check()) {
         return WireFormat.Utf8Validation.STRICT;
       }
@@ -669,10 +708,12 @@ class MessageReflection {
       return WireFormat.Utf8Validation.LOOSE;
     }
 
+    @Override
     public Object finish() {
       throw new UnsupportedOperationException(
           "finish() called on FieldSet object");
     }
+    
   }
 
   /**

+ 14 - 8
java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java

@@ -38,7 +38,7 @@ import java.util.List;
 /**
  * Implements {@link ProtobufList} for non-primitive and {@link String} types.
  */
-class ProtobufArrayList<E> extends AbstractProtobufList<E> {
+final class ProtobufArrayList<E> extends AbstractProtobufList<E> {
 
   private static final ProtobufArrayList<Object> EMPTY_LIST = new ProtobufArrayList<Object>();
   static {
@@ -51,17 +51,23 @@ class ProtobufArrayList<E> extends AbstractProtobufList<E> {
   }
   
   private final List<E> list;
-  
+
   ProtobufArrayList() {
-    list = new ArrayList<E>();
+    this(new ArrayList<E>(DEFAULT_CAPACITY));
   }
   
-  ProtobufArrayList(List<E> toCopy) {
-    list = new ArrayList<E>(toCopy);
+  private ProtobufArrayList(List<E> list) {
+    this.list = list;
   }
-  
-  ProtobufArrayList(int capacity) {
-    list = new ArrayList<E>(capacity);
+
+  @Override
+  public ProtobufArrayList<E> mutableCopyWithCapacity(int capacity) {
+    if (capacity < size()) {
+      throw new IllegalArgumentException();
+    }
+    List<E> newList = new ArrayList<E>(capacity);
+    newList.addAll(list);
+    return new ProtobufArrayList<E>(newList);
   }
   
   @Override

+ 1 - 0
java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java

@@ -42,6 +42,7 @@ public interface ProtocolMessageEnum extends Internal.EnumLite {
   /**
    * Return the value's numeric value as defined in the .proto file.
    */
+  @Override
   int getNumber();
 
   /**

+ 7 - 1
java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java

@@ -579,7 +579,7 @@ public class RepeatedFieldBuilder
     }
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public void markDirty() {
     onChanged();
   }
@@ -621,10 +621,12 @@ public class RepeatedFieldBuilder
       this.builder = builder;
     }
 
+    @Override
     public int size() {
       return this.builder.getCount();
     }
 
+    @Override
     public MType get(int index) {
       return builder.getMessage(index);
     }
@@ -654,10 +656,12 @@ public class RepeatedFieldBuilder
       this.builder = builder;
     }
 
+    @Override
     public int size() {
       return this.builder.getCount();
     }
 
+    @Override
     public BType get(int index) {
       return builder.getBuilder(index);
     }
@@ -687,10 +691,12 @@ public class RepeatedFieldBuilder
       this.builder = builder;
     }
 
+    @Override
     public int size() {
       return this.builder.getCount();
     }
 
+    @Override
     public IType get(int index) {
       return builder.getMessageOrBuilder(index);
     }

+ 3 - 1
java/core/src/main/java/com/google/protobuf/RpcUtil.java

@@ -71,6 +71,7 @@ public final class RpcUtil {
       final Class<Type> originalClass,
       final Type defaultInstance) {
     return new RpcCallback<Message>() {
+      @Override
       public void run(final Message parameter) {
         Type typedParameter;
         try {
@@ -107,8 +108,9 @@ public final class RpcUtil {
     return new RpcCallback<ParameterType>() {
       private boolean alreadyCalled = false;
 
+      @Override
       public void run(final ParameterType parameter) {
-        synchronized(this) {
+        synchronized (this) {
           if (alreadyCalled) {
             throw new AlreadyCalledException();
           }

+ 1 - 1
java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java

@@ -234,7 +234,7 @@ public class SingleFieldBuilder
     }
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public void markDirty() {
     onChanged();
   }

+ 79 - 27
java/core/src/main/java/com/google/protobuf/SmallSortedMap.java

@@ -411,22 +411,22 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
       this.value = value;
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public K getKey() {
       return key;
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public V getValue() {
       return value;
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public int compareTo(Entry other) {
       return getKey().compareTo(other.getKey());
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public V setValue(V newValue) {
       checkMutable();
       final V oldValue = this.value;
@@ -535,13 +535,13 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
     private boolean nextCalledBeforeRemove;
     private Iterator<Map.Entry<K, V>> lazyOverflowIterator;
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public boolean hasNext() {
       return (pos + 1) < entryList.size() ||
           getOverflowIterator().hasNext();
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public Map.Entry<K, V> next() {
       nextCalledBeforeRemove = true;
       // Always increment pos so that we know whether the last returned value
@@ -552,7 +552,7 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
       return getOverflowIterator().next();
     }
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public void remove() {
       if (!nextCalledBeforeRemove) {
         throw new IllegalStateException("remove() was called before next()");
@@ -588,31 +588,83 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
    */
   private static class EmptySet {
 
-    private static final Iterator<Object> ITERATOR = new Iterator<Object>() {
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
-      public boolean hasNext() {
-        return false;
-      }
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
-      public Object next() {
-        throw new NoSuchElementException();
-      }
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
-      public void remove() {
-        throw new UnsupportedOperationException();
-      }
-    };
+    private static final Iterator<Object> ITERATOR =
+        new Iterator<Object>() {
+          @Override
+          public boolean hasNext() {
+            return false;
+          }
+          @Override
+          public Object next() {
+            throw new NoSuchElementException();
+          }
+          @Override
+          public void remove() {
+            throw new UnsupportedOperationException();
+          }
+        };
 
-    private static final Iterable<Object> ITERABLE = new Iterable<Object>() {
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
-      public Iterator<Object> iterator() {
-        return ITERATOR;
-      }
-    };
+    private static final Iterable<Object> ITERABLE =
+        new Iterable<Object>() {
+          @Override
+          public Iterator<Object> iterator() {
+            return ITERATOR;
+          }
+        };
 
     @SuppressWarnings("unchecked")
     static <T> Iterable<T> iterable() {
       return (Iterable<T>) ITERABLE;
     }
   }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    
+    if (!(o instanceof SmallSortedMap)) {
+      return super.equals(o);
+    }
+    
+    SmallSortedMap<?, ?> other = (SmallSortedMap<?, ?>) o;
+    final int size = size();
+    if (size != other.size()) {
+      return false;
+    }
+    
+    // Best effort try to avoid allocating an entry set.
+    final int numArrayEntries = getNumArrayEntries();
+    if (numArrayEntries != other.getNumArrayEntries()) {
+      return entrySet().equals(other.entrySet());
+    }
+    
+    for (int i = 0; i < numArrayEntries; i++) {
+      if (!getArrayEntryAt(i).equals(other.getArrayEntryAt(i))) {
+        return false;
+      }
+    }
+    
+    if (numArrayEntries != size) {
+      return overflowEntries.equals(other.overflowEntries);
+    }
+    
+    
+    return true;
+  }
+  
+  @Override
+  public int hashCode() {
+    int h = 0;
+    final int listSize = getNumArrayEntries();
+    for (int i = 0; i < listSize; i++) {
+      h += entryList.get(i).hashCode();
+    }
+    // Avoid the iterator allocation if possible.
+    if (getNumOverflowEntries() > 0) {
+      h += overflowEntries.hashCode();
+    }
+    return h;
+  }
 }

+ 2 - 0
java/core/src/main/java/com/google/protobuf/TextFormat.java

@@ -965,11 +965,13 @@ public final class TextFormat {
      */
     public boolean consumeBoolean() throws ParseException {
       if (currentToken.equals("true")
+          || currentToken.equals("True")
           || currentToken.equals("t")
           || currentToken.equals("1")) {
         nextToken();
         return true;
       } else if (currentToken.equals("false")
+          || currentToken.equals("False")
           || currentToken.equals("f")
           || currentToken.equals("0")) {
         nextToken();

+ 51 - 26
java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java

@@ -76,6 +76,7 @@ public final class UnknownFieldSet implements MessageLite {
   public static UnknownFieldSet getDefaultInstance() {
     return defaultInstance;
   }
+  @Override
   public UnknownFieldSet getDefaultInstanceForType() {
     return defaultInstance;
   }
@@ -126,6 +127,7 @@ public final class UnknownFieldSet implements MessageLite {
   }
 
   /** Serializes the set and writes it to {@code output}. */
+  @Override
   public void writeTo(final CodedOutputStream output) throws IOException {
     for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
       entry.getValue().writeTo(entry.getKey(), output);
@@ -146,6 +148,7 @@ public final class UnknownFieldSet implements MessageLite {
    * Serializes the message to a {@code ByteString} and returns it. This is
    * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
    */
+  @Override
   public ByteString toByteString() {
     try {
       final ByteString.CodedBuilder out =
@@ -163,6 +166,7 @@ public final class UnknownFieldSet implements MessageLite {
    * Serializes the message to a {@code byte} array and returns it.  This is
    * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
    */
+  @Override
   public byte[] toByteArray() {
     try {
       final byte[] result = new byte[getSerializedSize()];
@@ -181,12 +185,14 @@ public final class UnknownFieldSet implements MessageLite {
    * Serializes the message and writes it to {@code output}.  This is just a
    * trivial wrapper around {@link #writeTo(CodedOutputStream)}.
    */
+  @Override
   public void writeTo(final OutputStream output) throws IOException {
     final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
     writeTo(codedOutput);
     codedOutput.flush();
   }
 
+  @Override
   public void writeDelimitedTo(OutputStream output) throws IOException {
     final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
     codedOutput.writeRawVarint32(getSerializedSize());
@@ -195,6 +201,7 @@ public final class UnknownFieldSet implements MessageLite {
   }
 
   /** Get the number of bytes required to encode this set. */
+  @Override
   public int getSerializedSize() {
     int result = 0;
     for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
@@ -228,6 +235,7 @@ public final class UnknownFieldSet implements MessageLite {
     return result;
   }
 
+  @Override
   public boolean isInitialized() {
     // UnknownFieldSets do not have required fields, so they are always
     // initialized.
@@ -258,10 +266,12 @@ public final class UnknownFieldSet implements MessageLite {
     return newBuilder().mergeFrom(input).build();
   }
 
+  @Override
   public Builder newBuilderForType() {
     return newBuilder();
   }
 
+  @Override
   public Builder toBuilder() {
     return newBuilder().mergeFrom(this);
   }
@@ -329,6 +339,7 @@ public final class UnknownFieldSet implements MessageLite {
      * in undefined behavior and can cause a {@code NullPointerException} to be
      * thrown.
      */
+    @Override
     public UnknownFieldSet build() {
       getFieldBuilder(0);  // Force lastField to be built.
       final UnknownFieldSet result;
@@ -341,6 +352,7 @@ public final class UnknownFieldSet implements MessageLite {
       return result;
     }
 
+    @Override
     public UnknownFieldSet buildPartial() {
       // No required fields, so this is the same as build().
       return build();
@@ -353,6 +365,7 @@ public final class UnknownFieldSet implements MessageLite {
           new UnknownFieldSet(fields));
     }
 
+    @Override
     public UnknownFieldSet getDefaultInstanceForType() {
       return UnknownFieldSet.getDefaultInstance();
     }
@@ -364,6 +377,7 @@ public final class UnknownFieldSet implements MessageLite {
     }
 
     /** Reset the builder to an empty set. */
+    @Override
     public Builder clear() {
       reinitialize();
       return this;
@@ -487,6 +501,7 @@ public final class UnknownFieldSet implements MessageLite {
      * Parse an entire message from {@code input} and merge its fields into
      * this set.
      */
+    @Override
     public Builder mergeFrom(final CodedInputStream input) throws IOException {
       while (true) {
         final int tag = input.readTag();
@@ -536,8 +551,8 @@ public final class UnknownFieldSet implements MessageLite {
      * set being built.  This is just a small wrapper around
      * {@link #mergeFrom(CodedInputStream)}.
      */
-    public Builder mergeFrom(final ByteString data)
-        throws InvalidProtocolBufferException {
+    @Override
+    public Builder mergeFrom(final ByteString data) throws InvalidProtocolBufferException {
       try {
         final CodedInputStream input = data.newCodedInput();
         mergeFrom(input);
@@ -557,8 +572,8 @@ public final class UnknownFieldSet implements MessageLite {
      * set being built.  This is just a small wrapper around
      * {@link #mergeFrom(CodedInputStream)}.
      */
-    public Builder mergeFrom(final byte[] data)
-        throws InvalidProtocolBufferException {
+    @Override
+    public Builder mergeFrom(final byte[] data) throws InvalidProtocolBufferException {
       try {
         final CodedInputStream input = CodedInputStream.newInstance(data);
         mergeFrom(input);
@@ -578,6 +593,7 @@ public final class UnknownFieldSet implements MessageLite {
      * set being built.  This is just a small wrapper around
      * {@link #mergeFrom(CodedInputStream)}.
      */
+    @Override
     public Builder mergeFrom(final InputStream input) throws IOException {
       final CodedInputStream codedInput = CodedInputStream.newInstance(input);
       mergeFrom(codedInput);
@@ -585,8 +601,8 @@ public final class UnknownFieldSet implements MessageLite {
       return this;
     }
 
-    public boolean mergeDelimitedFrom(InputStream input)
-        throws IOException {
+    @Override
+    public boolean mergeDelimitedFrom(InputStream input) throws IOException {
       final int firstByte = input.read();
       if (firstByte == -1) {
         return false;
@@ -597,30 +613,29 @@ public final class UnknownFieldSet implements MessageLite {
       return true;
     }
 
-    public boolean mergeDelimitedFrom(
-        InputStream input,
-        ExtensionRegistryLite extensionRegistry) throws IOException {
+    @Override
+    public boolean mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+        throws IOException {
       // UnknownFieldSet has no extensions.
       return mergeDelimitedFrom(input);
     }
 
-    public Builder mergeFrom(
-        CodedInputStream input,
-        ExtensionRegistryLite extensionRegistry) throws IOException {
+    @Override
+    public Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+        throws IOException {
       // UnknownFieldSet has no extensions.
       return mergeFrom(input);
     }
 
-    public Builder mergeFrom(
-        ByteString data,
-        ExtensionRegistryLite extensionRegistry)
+    @Override
+    public Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException {
       // UnknownFieldSet has no extensions.
       return mergeFrom(data);
     }
 
-    public Builder mergeFrom(byte[] data, int off, int len)
-        throws InvalidProtocolBufferException {
+    @Override
+    public Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException {
       try {
         final CodedInputStream input =
             CodedInputStream.newInstance(data, off, len);
@@ -636,29 +651,37 @@ public final class UnknownFieldSet implements MessageLite {
       }
     }
 
-    public Builder mergeFrom(
-        byte[] data,
-        ExtensionRegistryLite extensionRegistry)
+    @Override
+    public Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException {
       // UnknownFieldSet has no extensions.
       return mergeFrom(data);
     }
 
-    public Builder mergeFrom(
-        byte[] data, int off, int len,
-        ExtensionRegistryLite extensionRegistry)
+    @Override
+    public Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException {
       // UnknownFieldSet has no extensions.
       return mergeFrom(data, off, len);
     }
 
-    public Builder mergeFrom(
-        InputStream input,
-        ExtensionRegistryLite extensionRegistry) throws IOException {
+    @Override
+    public Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+        throws IOException {
       // UnknownFieldSet has no extensions.
       return mergeFrom(input);
     }
 
+    @Override
+    public Builder mergeFrom(MessageLite m) {
+      if (m instanceof UnknownFieldSet) {
+        return mergeFrom((UnknownFieldSet) m);
+      }
+      throw new IllegalArgumentException(
+          "mergeFrom(MessageLite) can only merge messages of the same type.");
+    }
+
+    @Override
     public boolean isInitialized() {
       // UnknownFieldSets do not have required fields, so they are always
       // initialized.
@@ -987,6 +1010,7 @@ public final class UnknownFieldSet implements MessageLite {
    * Parser to implement MessageLite interface.
    */
   public static final class Parser extends AbstractParser<UnknownFieldSet> {
+    @Override
     public UnknownFieldSet parsePartialFrom(
         CodedInputStream input, ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException {
@@ -1004,6 +1028,7 @@ public final class UnknownFieldSet implements MessageLite {
   }
 
   private static final Parser PARSER = new Parser();
+  @Override
   public final Parser getParserForType() {
     return PARSER;
   }

+ 25 - 25
java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java

@@ -68,42 +68,42 @@ public class UnmodifiableLazyStringList extends AbstractList<String>
     return list.size();
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public ByteString getByteString(int index) {
     return list.getByteString(index);
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public void add(ByteString element) {
     throw new UnsupportedOperationException();
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public void set(int index, ByteString element) {
     throw new UnsupportedOperationException();
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public boolean addAllByteString(Collection<? extends ByteString> element) {
     throw new UnsupportedOperationException();
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public byte[] getByteArray(int index) {
     return list.getByteArray(index);
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public void add(byte[] element) {
     throw new UnsupportedOperationException();
   }
   
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public void set(int index, byte[] element) {
     throw new UnsupportedOperationException();
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public boolean addAllByteArray(Collection<byte[]> element) {
     throw new UnsupportedOperationException();
   }
@@ -113,47 +113,47 @@ public class UnmodifiableLazyStringList extends AbstractList<String>
     return new ListIterator<String>() {
       ListIterator<String> iter = list.listIterator(index);
 
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
+      @Override
       public boolean hasNext() {
         return iter.hasNext();
       }
 
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
+      @Override
       public String next() {
         return iter.next();
       }
 
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
+      @Override
       public boolean hasPrevious() {
         return iter.hasPrevious();
       }
 
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
+      @Override
       public String previous() {
         return iter.previous();
       }
 
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
+      @Override
       public int nextIndex() {
         return iter.nextIndex();
       }
 
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
+      @Override
       public int previousIndex() {
         return iter.previousIndex();
       }
 
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
+      @Override
       public void remove() {
         throw new UnsupportedOperationException();
       }
 
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
+      @Override
       public void set(String o) {
         throw new UnsupportedOperationException();
       }
 
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
+      @Override
       public void add(String o) {
         throw new UnsupportedOperationException();
       }
@@ -165,45 +165,45 @@ public class UnmodifiableLazyStringList extends AbstractList<String>
     return new Iterator<String>() {
       Iterator<String> iter = list.iterator();
 
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
+      @Override
       public boolean hasNext() {
         return iter.hasNext();
       }
 
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
+      @Override
       public String next() {
         return iter.next();
       }
 
-      //@Override (Java 1.6 override semantics, but we must support 1.5)
+      @Override
       public void remove() {
         throw new UnsupportedOperationException();
       }
     };
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public List<?> getUnderlyingElements() {
     // The returned value is already unmodifiable.
     return list.getUnderlyingElements();
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public void mergeFrom(LazyStringList other) {
     throw new UnsupportedOperationException();
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public List<byte[]> asByteArrayList() {
     return Collections.unmodifiableList(list.asByteArrayList());
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public List<ByteString> asByteStringList() {
     return Collections.unmodifiableList(list.asByteStringList());
   }
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public LazyStringList getUnmodifiableView() {
     return this;
   }

+ 15 - 4
java/core/src/main/java/com/google/protobuf/WireFormat.java

@@ -116,16 +116,24 @@ public final class WireFormat {
     FIXED32 (JavaType.INT        , WIRETYPE_FIXED32         ),
     BOOL    (JavaType.BOOLEAN    , WIRETYPE_VARINT          ),
     STRING  (JavaType.STRING     , WIRETYPE_LENGTH_DELIMITED) {
-      public boolean isPackable() { return false; }
+      @Override
+      public boolean isPackable() {
+        return false; }
     },
     GROUP   (JavaType.MESSAGE    , WIRETYPE_START_GROUP     ) {
-      public boolean isPackable() { return false; }
+      @Override
+      public boolean isPackable() {
+        return false; }
     },
     MESSAGE (JavaType.MESSAGE    , WIRETYPE_LENGTH_DELIMITED) {
-      public boolean isPackable() { return false; }
+      @Override
+      public boolean isPackable() {
+        return false; }
     },
     BYTES   (JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED) {
-      public boolean isPackable() { return false; }
+      @Override
+      public boolean isPackable() {
+        return false; }
     },
     UINT32  (JavaType.INT        , WIRETYPE_VARINT          ),
     ENUM    (JavaType.ENUM       , WIRETYPE_VARINT          ),
@@ -170,18 +178,21 @@ public final class WireFormat {
   enum Utf8Validation {
     /** Eagerly parses to String; silently accepts invalid UTF8 bytes. */
     LOOSE {
+      @Override
       Object readString(CodedInputStream input) throws IOException {
         return input.readString();
       }
     },
     /** Eagerly parses to String; throws an IOException on invalid bytes. */
     STRICT {
+      @Override
       Object readString(CodedInputStream input) throws IOException {
         return input.readStringRequireUtf8();
       }
     },
     /** Keep data as ByteString; validation/conversion to String is lazy. */
     LAZY {
+      @Override
       Object readString(CodedInputStream input) throws IOException {
         return input.readBytes();
       }

+ 33 - 8
java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java

@@ -64,35 +64,44 @@ public class AbstractMessageTest extends TestCase {
       this.wrappedMessage = wrappedMessage;
     }
 
+    @Override
     public Descriptors.Descriptor getDescriptorForType() {
       return wrappedMessage.getDescriptorForType();
     }
+    @Override
     public AbstractMessageWrapper getDefaultInstanceForType() {
       return new AbstractMessageWrapper(
         wrappedMessage.getDefaultInstanceForType());
     }
+    @Override
     public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
       return wrappedMessage.getAllFields();
     }
+    @Override
     public boolean hasField(Descriptors.FieldDescriptor field) {
       return wrappedMessage.hasField(field);
     }
+    @Override
     public Object getField(Descriptors.FieldDescriptor field) {
       return wrappedMessage.getField(field);
     }
+    @Override
     public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
       return wrappedMessage.getRepeatedFieldCount(field);
     }
-    public Object getRepeatedField(
-        Descriptors.FieldDescriptor field, int index) {
+    @Override
+    public Object getRepeatedField(Descriptors.FieldDescriptor field, int index) {
       return wrappedMessage.getRepeatedField(field, index);
     }
+    @Override
     public UnknownFieldSet getUnknownFields() {
       return wrappedMessage.getUnknownFields();
     }
+    @Override
     public Builder newBuilderForType() {
       return new Builder(wrappedMessage.newBuilderForType());
     }
+    @Override
     public Builder toBuilder() {
       return new Builder(wrappedMessage.toBuilder());
     }
@@ -104,65 +113,80 @@ public class AbstractMessageTest extends TestCase {
         this.wrappedBuilder = wrappedBuilder;
       }
 
+      @Override
       public AbstractMessageWrapper build() {
         return new AbstractMessageWrapper(wrappedBuilder.build());
       }
+      @Override
       public AbstractMessageWrapper buildPartial() {
         return new AbstractMessageWrapper(wrappedBuilder.buildPartial());
       }
+      @Override
       public Builder clone() {
         return new Builder(wrappedBuilder.clone());
       }
+      @Override
       public boolean isInitialized() {
         return clone().buildPartial().isInitialized();
       }
+      @Override
       public Descriptors.Descriptor getDescriptorForType() {
         return wrappedBuilder.getDescriptorForType();
       }
+      @Override
       public AbstractMessageWrapper getDefaultInstanceForType() {
         return new AbstractMessageWrapper(
           wrappedBuilder.getDefaultInstanceForType());
       }
+      @Override
       public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
         return wrappedBuilder.getAllFields();
       }
+      @Override
       public Builder newBuilderForField(Descriptors.FieldDescriptor field) {
         return new Builder(wrappedBuilder.newBuilderForField(field));
       }
+      @Override
       public boolean hasField(Descriptors.FieldDescriptor field) {
         return wrappedBuilder.hasField(field);
       }
+      @Override
       public Object getField(Descriptors.FieldDescriptor field) {
         return wrappedBuilder.getField(field);
       }
+      @Override
       public Builder setField(Descriptors.FieldDescriptor field, Object value) {
         wrappedBuilder.setField(field, value);
         return this;
       }
+      @Override
       public Builder clearField(Descriptors.FieldDescriptor field) {
         wrappedBuilder.clearField(field);
         return this;
       }
+      @Override
       public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
         return wrappedBuilder.getRepeatedFieldCount(field);
       }
-      public Object getRepeatedField(
-          Descriptors.FieldDescriptor field, int index) {
+      @Override
+      public Object getRepeatedField(Descriptors.FieldDescriptor field, int index) {
         return wrappedBuilder.getRepeatedField(field, index);
       }
-      public Builder setRepeatedField(Descriptors.FieldDescriptor field,
-                                      int index, Object value) {
+      @Override
+      public Builder setRepeatedField(Descriptors.FieldDescriptor field, int index, Object value) {
         wrappedBuilder.setRepeatedField(field, index, value);
         return this;
       }
-      public Builder addRepeatedField(
-          Descriptors.FieldDescriptor field, Object value) {
+      @Override
+      public Builder addRepeatedField(Descriptors.FieldDescriptor field, Object value) {
         wrappedBuilder.addRepeatedField(field, value);
         return this;
       }
+      @Override
       public UnknownFieldSet getUnknownFields() {
         return wrappedBuilder.getUnknownFields();
       }
+      @Override
       public Builder setUnknownFields(UnknownFieldSet unknownFields) {
         wrappedBuilder.setUnknownFields(unknownFields);
         return this;
@@ -172,6 +196,7 @@ public class AbstractMessageTest extends TestCase {
         return wrappedBuilder.getFieldBuilder(field);
       }
     }
+    @Override
     public Parser<? extends Message> getParserForType() {
       return wrappedMessage.getParserForType();
     }

+ 0 - 14
java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java

@@ -73,20 +73,6 @@ public class BooleanArrayListTest extends TestCase {
     assertImmutable(list);
   }
   
-  public void testCopyConstructor() {
-    BooleanArrayList copy = new BooleanArrayList(TERTIARY_LIST);
-    assertEquals(TERTIARY_LIST, copy);
-
-    copy = new BooleanArrayList(BooleanArrayList.emptyList());
-    assertEquals(BooleanArrayList.emptyList(), copy);
-    
-    copy = new BooleanArrayList(asList(false, false, true));
-    assertEquals(asList(false, false, true), copy);
-
-    copy = new BooleanArrayList(Collections.<Boolean>emptyList());
-    assertEquals(BooleanArrayList.emptyList(), copy);
-  }
-  
   public void testModificationWithIteration() {
     list.addAll(asList(true, false, false, true));
     Iterator<Boolean> iterator = list.iterator();

+ 2 - 0
java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java

@@ -81,10 +81,12 @@ public class CodedInputStreamTest extends TestCase {
       this.blockSize = blockSize;
     }
 
+    @Override
     public int read(byte[] b) throws IOException {
       return super.read(b, 0, Math.min(b.length, blockSize));
     }
 
+    @Override
     public int read(byte[] b, int off, int len) throws IOException {
       return super.read(b, off, Math.min(len, blockSize));
     }

+ 503 - 273
java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java

@@ -30,6 +30,7 @@
 
 package com.google.protobuf;
 
+import com.google.protobuf.CodedOutputStream.OutOfSpaceException;
 import protobuf_unittest.UnittestProto.SparseEnumMessage;
 import protobuf_unittest.UnittestProto.TestAllTypes;
 import protobuf_unittest.UnittestProto.TestPackedTypes;
@@ -50,118 +51,180 @@ import java.util.List;
  * @author kenton@google.com Kenton Varda
  */
 public class CodedOutputStreamTest extends TestCase {
-  /**
-   * Helper to construct a byte array from a bunch of bytes.  The inputs are
-   * actually ints so that I can use hex notation and not get stupid errors
-   * about precision.
-   */
-  private byte[] bytes(int... bytesAsInts) {
-    byte[] bytes = new byte[bytesAsInts.length];
-    for (int i = 0; i < bytesAsInts.length; i++) {
-      bytes[i] = (byte) bytesAsInts[i];
-    }
-    return bytes;
+  private interface Coder {
+    CodedOutputStream stream();
+
+    byte[] toByteArray();
+
+    OutputType getOutputType();
   }
 
-  /** Arrays.asList() does not work with arrays of primitives.  :( */
-  private List<Byte> toList(byte[] bytes) {
-    List<Byte> result = new ArrayList<Byte>();
-    for (byte b : bytes) {
-      result.add(b);
+  private static final class OutputStreamCoder implements Coder {
+    private final CodedOutputStream stream;
+    private final ByteArrayOutputStream output;
+
+    OutputStreamCoder(int size) {
+      output = new ByteArrayOutputStream();
+      stream = CodedOutputStream.newInstance(output, size);
+    }
+
+    @Override
+    public CodedOutputStream stream() {
+      return stream;
+    }
+
+    @Override
+    public byte[] toByteArray() {
+      return output.toByteArray();
+    }
+
+    @Override
+    public OutputType getOutputType() {
+      return OutputType.STREAM;
     }
-    return result;
   }
 
-  private void assertEqualBytes(byte[] a, byte[] b) {
-    assertEquals(toList(a), toList(b));
+  private static final class ArrayCoder implements Coder {
+    private final CodedOutputStream stream;
+    private final byte[] bytes;
+
+    ArrayCoder(int size) {
+      bytes = new byte[size];
+      stream = CodedOutputStream.newInstance(bytes);
+    }
+
+    @Override
+    public CodedOutputStream stream() {
+      return stream;
+    }
+
+    @Override
+    public byte[] toByteArray() {
+      return Arrays.copyOf(bytes, stream.getTotalBytesWritten());
+    }
+
+    @Override
+    public OutputType getOutputType() {
+      return OutputType.ARRAY;
+    }
   }
 
-  /**
-   * Writes the given value using writeRawVarint32() and writeRawVarint64() and
-   * checks that the result matches the given bytes.
-   */
-  private void assertWriteVarint(byte[] data, long value) throws Exception {
-    // Only test 32-bit write if the value fits into an int.
-    if (value == (int) value) {
-      ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-      CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
-      output.writeRawVarint32((int) value);
-      output.flush();
-      assertEqualBytes(data, rawOutput.toByteArray());
+  private static final class NioHeapCoder implements Coder {
+    private final CodedOutputStream stream;
+    private final ByteBuffer buffer;
+    private final int initialPosition;
 
-      // Also try computing size.
-      assertEquals(data.length,
-                   CodedOutputStream.computeRawVarint32Size((int) value));
+    NioHeapCoder(int size) {
+      this(size, 0);
     }
 
-    {
-      ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-      CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
-      output.writeRawVarint64(value);
-      output.flush();
-      assertEqualBytes(data, rawOutput.toByteArray());
+    NioHeapCoder(int size, int initialPosition) {
+      this.initialPosition = initialPosition;
+      buffer = ByteBuffer.allocate(size);
+      buffer.position(initialPosition);
+      stream = CodedOutputStream.newInstance(buffer);
+    }
 
-      // Also try computing size.
-      assertEquals(data.length,
-                   CodedOutputStream.computeRawVarint64Size(value));
+    @Override
+    public CodedOutputStream stream() {
+      return stream;
     }
 
-    // Try different block sizes.
-    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
-      // Only test 32-bit write if the value fits into an int.
-      if (value == (int) value) {
-        ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-        CodedOutputStream output =
-          CodedOutputStream.newInstance(rawOutput, blockSize);
-        output.writeRawVarint32((int) value);
-        output.flush();
-        assertEqualBytes(data, rawOutput.toByteArray());
-      }
+    @Override
+    public byte[] toByteArray() {
+      ByteBuffer dup = buffer.duplicate();
+      dup.position(initialPosition);
+      dup.limit(buffer.position());
 
-      {
-        ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-        CodedOutputStream output =
-          CodedOutputStream.newInstance(rawOutput, blockSize);
-        output.writeRawVarint64(value);
-        output.flush();
-        assertEqualBytes(data, rawOutput.toByteArray());
-      }
+      byte[] bytes = new byte[dup.remaining()];
+      dup.get(bytes);
+      return bytes;
+    }
+
+    @Override
+    public OutputType getOutputType() {
+      return OutputType.NIO_HEAP;
     }
   }
 
-  private void assertVarintRoundTrip(long value) throws Exception {
-    {
-      ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-      CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
-      output.writeRawVarint64(value);
-      output.flush();
-      byte[] bytes = rawOutput.toByteArray();
-      assertEquals(bytes.length, CodedOutputStream.computeRawVarint64Size(value));
-      CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes));
-      assertEquals(value, input.readRawVarint64());
+  private static final class NioDirectCoder implements Coder {
+    private final int initialPosition;
+    private final CodedOutputStream stream;
+    private final ByteBuffer buffer;
+
+    NioDirectCoder(int size) {
+      this(size, 0);
     }
 
-    if (value == (int) value) {
-      ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-      CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
-      output.writeRawVarint32((int) value);
-      output.flush();
-      byte[] bytes = rawOutput.toByteArray();
-      assertEquals(bytes.length, CodedOutputStream.computeRawVarint32Size((int) value));
-      CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes));
-      assertEquals(value, input.readRawVarint32());
+    NioDirectCoder(int size, int initialPosition) {
+      this.initialPosition = initialPosition;
+      buffer = ByteBuffer.allocateDirect(size);
+      buffer.position(initialPosition);
+      stream = CodedOutputStream.newInstance(buffer);
+    }
+
+    @Override
+    public CodedOutputStream stream() {
+      return stream;
+    }
+
+    @Override
+    public byte[] toByteArray() {
+      ByteBuffer dup = buffer.duplicate();
+      dup.position(initialPosition);
+      dup.limit(buffer.position());
+
+      byte[] bytes = new byte[dup.remaining()];
+      dup.get(bytes);
+      return bytes;
+    }
+
+    @Override
+    public OutputType getOutputType() {
+      return OutputType.NIO_DIRECT;
     }
   }
 
+  private enum OutputType {
+    ARRAY() {
+      @Override
+      Coder newCoder(int size) {
+        return new ArrayCoder(size);
+      }
+    },
+    NIO_HEAP() {
+      @Override
+      Coder newCoder(int size) {
+        return new NioHeapCoder(size);
+      }
+    },
+    NIO_DIRECT() {
+      @Override
+      Coder newCoder(int size) {
+        return new NioDirectCoder(size);
+      }
+    },
+    STREAM() {
+      @Override
+      Coder newCoder(int size) {
+        return new OutputStreamCoder(size);
+      }
+    };
+
+    abstract Coder newCoder(int size);
+  }
+
   /** Checks that invariants are maintained for varint round trip input and output. */
   public void testVarintRoundTrips() throws Exception {
-    assertVarintRoundTrip(0L);
-    for (int bits = 0; bits < 64; bits++) {
-      long value = 1L << bits;
-      assertVarintRoundTrip(value);
-      assertVarintRoundTrip(value + 1);
-      assertVarintRoundTrip(value - 1);
-      assertVarintRoundTrip(-value);
+    for (OutputType outputType : OutputType.values()) {
+      assertVarintRoundTrip(outputType, 0L);
+      for (int bits = 0; bits < 64; bits++) {
+        long value = 1L << bits;
+        assertVarintRoundTrip(outputType, value);
+        assertVarintRoundTrip(outputType, value + 1);
+        assertVarintRoundTrip(outputType, value - 1);
+        assertVarintRoundTrip(outputType, -value);
+      }
     }
   }
 
@@ -173,70 +236,25 @@ public class CodedOutputStreamTest extends TestCase {
     // 14882
     assertWriteVarint(bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
     // 2961488830
-    assertWriteVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
-      (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
-      (0x0bL << 28));
+    assertWriteVarint(
+        bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
+        (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x0bL << 28));
 
     // 64-bit
     // 7256456126
-    assertWriteVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
-      (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
-      (0x1bL << 28));
+    assertWriteVarint(
+        bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
+        (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x1bL << 28));
     // 41256202580718336
     assertWriteVarint(
-      bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
-      (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
-      (0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
+        bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
+        (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) | (0x43L << 28) | (0x49L << 35)
+        | (0x24L << 42) | (0x49L << 49));
     // 11964378330978735131
     assertWriteVarint(
-      bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
-      (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
-      (0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
-      (0x05L << 49) | (0x26L << 56) | (0x01L << 63));
-  }
-
-  /**
-   * Parses the given bytes using writeRawLittleEndian32() and checks
-   * that the result matches the given value.
-   */
-  private void assertWriteLittleEndian32(byte[] data, int value)
-                                         throws Exception {
-    ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
-    output.writeRawLittleEndian32(value);
-    output.flush();
-    assertEqualBytes(data, rawOutput.toByteArray());
-
-    // Try different block sizes.
-    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
-      rawOutput = new ByteArrayOutputStream();
-      output = CodedOutputStream.newInstance(rawOutput, blockSize);
-      output.writeRawLittleEndian32(value);
-      output.flush();
-      assertEqualBytes(data, rawOutput.toByteArray());
-    }
-  }
-
-  /**
-   * Parses the given bytes using writeRawLittleEndian64() and checks
-   * that the result matches the given value.
-   */
-  private void assertWriteLittleEndian64(byte[] data, long value)
-                                         throws Exception {
-    ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
-    output.writeRawLittleEndian64(value);
-    output.flush();
-    assertEqualBytes(data, rawOutput.toByteArray());
-
-    // Try different block sizes.
-    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
-      rawOutput = new ByteArrayOutputStream();
-      output = CodedOutputStream.newInstance(rawOutput, blockSize);
-      output.writeRawLittleEndian64(value);
-      output.flush();
-      assertEqualBytes(data, rawOutput.toByteArray());
-    }
+        bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
+        (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) | (0x3bL << 28) | (0x56L << 35)
+        | (0x00L << 42) | (0x05L << 49) | (0x26L << 56) | (0x01L << 63));
   }
 
   /** Tests writeRawLittleEndian32() and writeRawLittleEndian64(). */
@@ -245,141 +263,138 @@ public class CodedOutputStreamTest extends TestCase {
     assertWriteLittleEndian32(bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
 
     assertWriteLittleEndian64(
-      bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
-      0x123456789abcdef0L);
+        bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12), 0x123456789abcdef0L);
     assertWriteLittleEndian64(
-      bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a),
-      0x9abcdef012345678L);
+        bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef012345678L);
   }
 
   /** Test encodeZigZag32() and encodeZigZag64(). */
   public void testEncodeZigZag() throws Exception {
-    assertEquals(0, CodedOutputStream.encodeZigZag32( 0));
+    assertEquals(0, CodedOutputStream.encodeZigZag32(0));
     assertEquals(1, CodedOutputStream.encodeZigZag32(-1));
-    assertEquals(2, CodedOutputStream.encodeZigZag32( 1));
+    assertEquals(2, CodedOutputStream.encodeZigZag32(1));
     assertEquals(3, CodedOutputStream.encodeZigZag32(-2));
     assertEquals(0x7FFFFFFE, CodedOutputStream.encodeZigZag32(0x3FFFFFFF));
     assertEquals(0x7FFFFFFF, CodedOutputStream.encodeZigZag32(0xC0000000));
     assertEquals(0xFFFFFFFE, CodedOutputStream.encodeZigZag32(0x7FFFFFFF));
     assertEquals(0xFFFFFFFF, CodedOutputStream.encodeZigZag32(0x80000000));
 
-    assertEquals(0, CodedOutputStream.encodeZigZag64( 0));
+    assertEquals(0, CodedOutputStream.encodeZigZag64(0));
     assertEquals(1, CodedOutputStream.encodeZigZag64(-1));
-    assertEquals(2, CodedOutputStream.encodeZigZag64( 1));
+    assertEquals(2, CodedOutputStream.encodeZigZag64(1));
     assertEquals(3, CodedOutputStream.encodeZigZag64(-2));
-    assertEquals(0x000000007FFFFFFEL,
-                 CodedOutputStream.encodeZigZag64(0x000000003FFFFFFFL));
-    assertEquals(0x000000007FFFFFFFL,
-                 CodedOutputStream.encodeZigZag64(0xFFFFFFFFC0000000L));
-    assertEquals(0x00000000FFFFFFFEL,
-                 CodedOutputStream.encodeZigZag64(0x000000007FFFFFFFL));
-    assertEquals(0x00000000FFFFFFFFL,
-                 CodedOutputStream.encodeZigZag64(0xFFFFFFFF80000000L));
-    assertEquals(0xFFFFFFFFFFFFFFFEL,
-                 CodedOutputStream.encodeZigZag64(0x7FFFFFFFFFFFFFFFL));
-    assertEquals(0xFFFFFFFFFFFFFFFFL,
-                 CodedOutputStream.encodeZigZag64(0x8000000000000000L));
+    assertEquals(0x000000007FFFFFFEL, CodedOutputStream.encodeZigZag64(0x000000003FFFFFFFL));
+    assertEquals(0x000000007FFFFFFFL, CodedOutputStream.encodeZigZag64(0xFFFFFFFFC0000000L));
+    assertEquals(0x00000000FFFFFFFEL, CodedOutputStream.encodeZigZag64(0x000000007FFFFFFFL));
+    assertEquals(0x00000000FFFFFFFFL, CodedOutputStream.encodeZigZag64(0xFFFFFFFF80000000L));
+    assertEquals(0xFFFFFFFFFFFFFFFEL, CodedOutputStream.encodeZigZag64(0x7FFFFFFFFFFFFFFFL));
+    assertEquals(0xFFFFFFFFFFFFFFFFL, CodedOutputStream.encodeZigZag64(0x8000000000000000L));
 
     // Some easier-to-verify round-trip tests.  The inputs (other than 0, 1, -1)
     // were chosen semi-randomly via keyboard bashing.
-    assertEquals(0,
-      CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(0)));
-    assertEquals(1,
-      CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(1)));
-    assertEquals(-1,
-      CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-1)));
-    assertEquals(14927,
-      CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(14927)));
-    assertEquals(-3612,
-      CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-3612)));
-
-    assertEquals(0,
-      CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(0)));
-    assertEquals(1,
-      CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(1)));
-    assertEquals(-1,
-      CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-1)));
-    assertEquals(14927,
-      CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(14927)));
-    assertEquals(-3612,
-      CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-3612)));
-
-    assertEquals(856912304801416L,
-      CodedOutputStream.encodeZigZag64(
-        CodedInputStream.decodeZigZag64(
-          856912304801416L)));
-    assertEquals(-75123905439571256L,
-      CodedOutputStream.encodeZigZag64(
-        CodedInputStream.decodeZigZag64(
-          -75123905439571256L)));
+    assertEquals(0, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(0)));
+    assertEquals(1, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(1)));
+    assertEquals(-1, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-1)));
+    assertEquals(14927, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(14927)));
+    assertEquals(-3612, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-3612)));
+
+    assertEquals(0, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(0)));
+    assertEquals(1, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(1)));
+    assertEquals(-1, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-1)));
+    assertEquals(14927, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(14927)));
+    assertEquals(-3612, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-3612)));
+
+    assertEquals(
+        856912304801416L,
+        CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(856912304801416L)));
+    assertEquals(
+        -75123905439571256L,
+        CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-75123905439571256L)));
   }
 
   /** Tests writing a whole message with every field type. */
   public void testWriteWholeMessage() throws Exception {
+    final byte[] expectedBytes = TestUtil.getGoldenMessage().toByteArray();
     TestAllTypes message = TestUtil.getAllSet();
 
-    byte[] rawBytes = message.toByteArray();
-    assertEqualBytes(TestUtil.getGoldenMessage().toByteArray(), rawBytes);
+    for (OutputType outputType : OutputType.values()) {
+      Coder coder = outputType.newCoder(message.getSerializedSize());
+      message.writeTo(coder.stream());
+      coder.stream().flush();
+      byte[] rawBytes = coder.toByteArray();
+      assertEqualBytes(outputType, expectedBytes, rawBytes);
+    }
 
     // Try different block sizes.
     for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
-      ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
-      CodedOutputStream output =
-        CodedOutputStream.newInstance(rawOutput, blockSize);
-      message.writeTo(output);
-      output.flush();
-      assertEqualBytes(rawBytes, rawOutput.toByteArray());
+      Coder coder = OutputType.STREAM.newCoder(blockSize);
+      message.writeTo(coder.stream());
+      coder.stream().flush();
+      assertEqualBytes(OutputType.STREAM, expectedBytes, coder.toByteArray());
     }
   }
 
-  /** Tests writing a whole message with every packed field type. Ensures the
-   * wire format of packed fields is compatible with C++. */
+  /**
+   * Tests writing a whole message with every packed field type. Ensures the
+   * wire format of packed fields is compatible with C++.
+   */
   public void testWriteWholePackedFieldsMessage() throws Exception {
+    byte[] expectedBytes = TestUtil.getGoldenPackedFieldsMessage().toByteArray();
     TestPackedTypes message = TestUtil.getPackedSet();
 
-    byte[] rawBytes = message.toByteArray();
-    assertEqualBytes(TestUtil.getGoldenPackedFieldsMessage().toByteArray(),
-                     rawBytes);
+    for (OutputType outputType : OutputType.values()) {
+      Coder coder = outputType.newCoder(message.getSerializedSize());
+      message.writeTo(coder.stream());
+      coder.stream().flush();
+      byte[] rawBytes = coder.toByteArray();
+      assertEqualBytes(outputType, expectedBytes, rawBytes);
+    }
   }
 
-  /** Test writing a message containing a negative enum value. This used to
+  /**
+   * Test writing a message containing a negative enum value. This used to
    * fail because the size was not properly computed as a sign-extended varint.
    */
   public void testWriteMessageWithNegativeEnumValue() throws Exception {
-    SparseEnumMessage message = SparseEnumMessage.newBuilder()
-        .setSparseEnum(TestSparseEnum.SPARSE_E) .build();
+    SparseEnumMessage message =
+        SparseEnumMessage.newBuilder().setSparseEnum(TestSparseEnum.SPARSE_E).build();
     assertTrue(message.getSparseEnum().getNumber() < 0);
-    byte[] rawBytes = message.toByteArray();
-    SparseEnumMessage message2 = SparseEnumMessage.parseFrom(rawBytes);
-    assertEquals(TestSparseEnum.SPARSE_E, message2.getSparseEnum());
+    for (OutputType outputType : OutputType.values()) {
+      Coder coder = outputType.newCoder(message.getSerializedSize());
+      message.writeTo(coder.stream());
+      coder.stream().flush();
+      byte[] rawBytes = coder.toByteArray();
+      SparseEnumMessage message2 = SparseEnumMessage.parseFrom(rawBytes);
+      assertEquals(TestSparseEnum.SPARSE_E, message2.getSparseEnum());
+    }
   }
 
   /** Test getTotalBytesWritten() */
   public void testGetTotalBytesWritten() throws Exception {
-    final int BUFFER_SIZE = 4 * 1024;
-    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(BUFFER_SIZE);
-    CodedOutputStream codedStream = CodedOutputStream.newInstance(outputStream);
+    Coder coder = OutputType.STREAM.newCoder(4 * 1024);
+
+    // Write some some bytes (more than the buffer can hold) and verify that totalWritten
+    // is correct.
     byte[] value = "abcde".getBytes(Internal.UTF_8);
     for (int i = 0; i < 1024; ++i) {
-      codedStream.writeRawBytes(value, 0, value.length);
+      coder.stream().writeRawBytes(value, 0, value.length);
     }
+    assertEquals(value.length * 1024, coder.stream().getTotalBytesWritten());
+
+    // Now write an encoded string.
     String string =
         "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
     // Ensure we take the slower fast path.
-    assertTrue(CodedOutputStream.computeRawVarint32Size(string.length())
-        != CodedOutputStream.computeRawVarint32Size(string.length() * Utf8.MAX_BYTES_PER_CHAR));
-    
-    codedStream.writeStringNoTag(string);
+    assertTrue(CodedOutputStream.computeUInt32SizeNoTag(string.length())
+        != CodedOutputStream.computeUInt32SizeNoTag(string.length() * Utf8.MAX_BYTES_PER_CHAR));
+
+    coder.stream().writeStringNoTag(string);
     int stringSize = CodedOutputStream.computeStringSizeNoTag(string);
-    
-    // Make sure we have written more bytes than the buffer could hold. This is
-    // to make the test complete.
-    assertTrue(codedStream.getTotalBytesWritten() > BUFFER_SIZE);
-    
+
     // Verify that the total bytes written is correct
-    assertEquals((value.length * 1024) + stringSize, codedStream.getTotalBytesWritten());
+    assertEquals((value.length * 1024) + stringSize, coder.stream().getTotalBytesWritten());
   }
-  
+
   // TODO(dweis): Write a comprehensive test suite for CodedOutputStream that covers more than just
   //    this case.
   public void testWriteStringNoTag_fastpath() throws Exception {
@@ -390,14 +405,16 @@ public class CodedOutputStreamTest extends TestCase {
       string += threeBytesPer;
     }
     // These checks ensure we will tickle the slower fast path.
-    assertEquals(1, CodedOutputStream.computeRawVarint32Size(string.length()));
+    assertEquals(1, CodedOutputStream.computeUInt32SizeNoTag(string.length()));
     assertEquals(
-        2, CodedOutputStream.computeRawVarint32Size(string.length() * Utf8.MAX_BYTES_PER_CHAR));
+        2, CodedOutputStream.computeUInt32SizeNoTag(string.length() * Utf8.MAX_BYTES_PER_CHAR));
     assertEquals(bufferSize, string.length() * Utf8.MAX_BYTES_PER_CHAR);
-    
-    CodedOutputStream output =
-        CodedOutputStream.newInstance(ByteBuffer.allocate(bufferSize), bufferSize);
-    output.writeStringNoTag(string);
+
+    for (OutputType outputType : OutputType.values()) {
+      Coder coder = outputType.newCoder(bufferSize + 2);
+      coder.stream().writeStringNoTag(string);
+      coder.stream().flush();
+    }
   }
 
   public void testWriteToByteBuffer() throws Exception {
@@ -464,83 +481,296 @@ public class CodedOutputStreamTest extends TestCase {
     byte[] destination = new byte[4];
     CodedOutputStream codedStream = CodedOutputStream.newInstance(destination);
     codedStream.writeByteArrayNoTag(fullArray, 2, 2);
-    assertEqualBytes(bytes(0x02, 0x33, 0x44, 0x00), destination);
+    assertEqualBytes(OutputType.ARRAY, bytes(0x02, 0x33, 0x44, 0x00), destination);
     assertEquals(3, codedStream.getTotalBytesWritten());
   }
-  
+
+  public void testSerializeUtf8_MultipleSmallWrites() throws Exception {
+    final String source = "abcdefghijklmnopqrstuvwxyz";
+
+    // Generate the expected output if the source string is written 2 bytes at a time.
+    ByteArrayOutputStream expectedBytesStream = new ByteArrayOutputStream();
+    for (int pos = 0; pos < source.length(); pos += 2) {
+      String substr = source.substring(pos, pos + 2);
+      expectedBytesStream.write(2);
+      expectedBytesStream.write(substr.getBytes(Internal.UTF_8));
+    }
+    final byte[] expectedBytes = expectedBytesStream.toByteArray();
+
+    // For each output type, write the source string 2 bytes at a time and verify the output.
+    for (OutputType outputType : OutputType.values()) {
+      Coder coder = outputType.newCoder(expectedBytes.length);
+      for (int pos = 0; pos < source.length(); pos += 2) {
+        String substr = source.substring(pos, pos + 2);
+        coder.stream().writeStringNoTag(substr);
+      }
+      coder.stream().flush();
+      assertEqualBytes(outputType, expectedBytes, coder.toByteArray());
+    }
+  }
+
   public void testSerializeInvalidUtf8() throws Exception {
-    String[] invalidStrings = new String[] {
-        newString(Character.MIN_HIGH_SURROGATE),
-        "foobar" + newString(Character.MIN_HIGH_SURROGATE),
-        newString(Character.MIN_LOW_SURROGATE),
+    String[] invalidStrings = new String[] {newString(Character.MIN_HIGH_SURROGATE),
+        "foobar" + newString(Character.MIN_HIGH_SURROGATE), newString(Character.MIN_LOW_SURROGATE),
         "foobar" + newString(Character.MIN_LOW_SURROGATE),
-        newString(Character.MIN_HIGH_SURROGATE, Character.MIN_HIGH_SURROGATE)
-    };
-    
+        newString(Character.MIN_HIGH_SURROGATE, Character.MIN_HIGH_SURROGATE)};
+
     CodedOutputStream outputWithStream = CodedOutputStream.newInstance(new ByteArrayOutputStream());
     CodedOutputStream outputWithArray = CodedOutputStream.newInstance(new byte[10000]);
+    CodedOutputStream outputWithByteBuffer =
+        CodedOutputStream.newInstance(ByteBuffer.allocate(10000));
     for (String s : invalidStrings) {
       // TODO(dweis): These should all fail; instead they are corrupting data.
       CodedOutputStream.computeStringSizeNoTag(s);
       outputWithStream.writeStringNoTag(s);
       outputWithArray.writeStringNoTag(s);
+      outputWithByteBuffer.writeStringNoTag(s);
     }
   }
-  
-  private static String newString(char... chars) {
-    return new String(chars);
+
+  // TODO(nathanmittler): This test can be deleted once we properly throw IOException while
+  // encoding invalid UTF-8 strings.
+  public void testSerializeInvalidUtf8FollowedByOutOfSpace() throws Exception {
+    final int notEnoughBytes = 4;
+    CodedOutputStream outputWithArray = CodedOutputStream.newInstance(new byte[notEnoughBytes]);
+    CodedOutputStream outputWithByteBuffer =
+        CodedOutputStream.newInstance(ByteBuffer.allocate(notEnoughBytes));
+
+    String invalidString = newString(Character.MIN_HIGH_SURROGATE, 'f', 'o', 'o', 'b', 'a', 'r');
+    try {
+      outputWithArray.writeStringNoTag(invalidString);
+      fail("Expected OutOfSpaceException");
+    } catch (OutOfSpaceException e) {
+      assertTrue(e.getCause() instanceof IndexOutOfBoundsException);
+    }
+    try {
+      outputWithByteBuffer.writeStringNoTag(invalidString);
+      fail("Expected OutOfSpaceException");
+    } catch (OutOfSpaceException e) {
+      assertTrue(e.getCause() instanceof IndexOutOfBoundsException);
+    }
   }
 
   /** Regression test for https://github.com/google/protobuf/issues/292 */
   public void testCorrectExceptionThrowWhenEncodingStringsWithoutEnoughSpace() throws Exception {
     String testCase = "Foooooooo";
-    assertEquals(CodedOutputStream.computeRawVarint32Size(testCase.length()),
-        CodedOutputStream.computeRawVarint32Size(testCase.length() * 3));
+    assertEquals(
+        CodedOutputStream.computeUInt32SizeNoTag(testCase.length()),
+        CodedOutputStream.computeUInt32SizeNoTag(testCase.length() * 3));
     assertEquals(11, CodedOutputStream.computeStringSize(1, testCase));
     // Tag is one byte, varint describing string length is 1 byte, string length is 9 bytes.
     // An array of size 1 will cause a failure when trying to write the varint.
-    for (int i = 0; i < 11; i++) {
-      CodedOutputStream output = CodedOutputStream.newInstance(new byte[i]);
-      try {
-        output.writeString(1, testCase);
-        fail("Should have thrown an out of space exception");
-      } catch (CodedOutputStream.OutOfSpaceException expected) {}
+    for (OutputType outputType :
+        new OutputType[] {OutputType.ARRAY, OutputType.NIO_HEAP, OutputType.NIO_DIRECT}) {
+      for (int i = 0; i < 11; i++) {
+        Coder coder = outputType.newCoder(i);
+        try {
+          coder.stream().writeString(1, testCase);
+          fail("Should have thrown an out of space exception");
+        } catch (CodedOutputStream.OutOfSpaceException expected) {
+        }
+      }
     }
   }
-  
+
   public void testDifferentStringLengths() throws Exception {
     // Test string serialization roundtrip using strings of the following lengths,
     // with ASCII and Unicode characters requiring different UTF-8 byte counts per
     // char, hence causing the length delimiter varint to sometimes require more
     // bytes for the Unicode strings than the ASCII string of the same length.
     int[] lengths = new int[] {
-            0,
-            1,
-            (1 << 4) - 1,  // 1 byte for ASCII and Unicode
-            (1 << 7) - 1,  // 1 byte for ASCII, 2 bytes for Unicode
-            (1 << 11) - 1, // 2 bytes for ASCII and Unicode
-            (1 << 14) - 1, // 2 bytes for ASCII, 3 bytes for Unicode
-            (1 << 17) - 1, // 3 bytes for ASCII and Unicode
+        0,
+        1,
+        (1 << 4) - 1, // 1 byte for ASCII and Unicode
+        (1 << 7) - 1, // 1 byte for ASCII, 2 bytes for Unicode
+        (1 << 11) - 1, // 2 bytes for ASCII and Unicode
+        (1 << 14) - 1, // 2 bytes for ASCII, 3 bytes for Unicode
+        (1 << 17) - 1,
+        // 3 bytes for ASCII and Unicode
     };
-    for (int i : lengths) {
-      testEncodingOfString('q', i);      // 1 byte per char
-      testEncodingOfString('\u07FF', i); // 2 bytes per char
-      testEncodingOfString('\u0981', i); // 3 bytes per char
+    for (OutputType outputType : OutputType.values()) {
+      for (int i : lengths) {
+        testEncodingOfString(outputType, 'q', i); // 1 byte per char
+        testEncodingOfString(outputType, '\u07FF', i); // 2 bytes per char
+        testEncodingOfString(outputType, '\u0981', i); // 3 bytes per char
+      }
     }
   }
 
-  private void testEncodingOfString(char c, int length) throws Exception {
+  public void testNioEncodersWithInitialOffsets() throws Exception {
+    String value = "abc";
+    for (Coder coder : new Coder[] {new NioHeapCoder(10, 2), new NioDirectCoder(10, 2)}) {
+      coder.stream().writeStringNoTag(value);
+      coder.stream().flush();
+      assertEqualBytes(coder.getOutputType(), new byte[]{3, 'a', 'b', 'c'}, coder.toByteArray());
+    }
+  }
+
+  /**
+   * Parses the given bytes using writeRawLittleEndian32() and checks
+   * that the result matches the given value.
+   */
+  private static void assertWriteLittleEndian32(byte[] data, int value) throws Exception {
+    for (OutputType outputType : OutputType.values()) {
+      Coder coder = outputType.newCoder(data.length);
+      coder.stream().writeFixed32NoTag(value);
+      coder.stream().flush();
+      assertEqualBytes(outputType, data, coder.toByteArray());
+    }
+
+    // Try different block sizes.
+    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+      Coder coder = OutputType.STREAM.newCoder(blockSize);
+      coder.stream().writeFixed32NoTag(value);
+      coder.stream().flush();
+      assertEqualBytes(OutputType.STREAM, data, coder.toByteArray());
+    }
+  }
+
+  /**
+   * Parses the given bytes using writeRawLittleEndian64() and checks
+   * that the result matches the given value.
+   */
+  private static void assertWriteLittleEndian64(byte[] data, long value) throws Exception {
+    for (OutputType outputType : OutputType.values()) {
+      Coder coder = outputType.newCoder(data.length);
+      coder.stream().writeFixed64NoTag(value);
+      coder.stream().flush();
+      assertEqualBytes(outputType, data, coder.toByteArray());
+    }
+
+    // Try different block sizes.
+    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+      Coder coder = OutputType.STREAM.newCoder(blockSize);
+      coder.stream().writeFixed64NoTag(value);
+      coder.stream().flush();
+      assertEqualBytes(OutputType.STREAM, data, coder.toByteArray());
+    }
+  }
+
+  private static String newString(char... chars) {
+    return new String(chars);
+  }
+
+  private static void testEncodingOfString(OutputType outputType, char c, int length)
+      throws Exception {
     String fullString = fullString(c, length);
-    TestAllTypes testAllTypes = TestAllTypes.newBuilder()
-        .setOptionalString(fullString)
-        .build();
+    TestAllTypes testAllTypes = TestAllTypes.newBuilder().setOptionalString(fullString).build();
+    Coder coder = outputType.newCoder(testAllTypes.getSerializedSize());
+    testAllTypes.writeTo(coder.stream());
+    coder.stream().flush();
     assertEquals(
-        fullString, TestAllTypes.parseFrom(testAllTypes.toByteArray()).getOptionalString());
+        "OuputType: " + outputType,
+        fullString,
+        TestAllTypes.parseFrom(coder.toByteArray()).getOptionalString());
   }
 
-  private String fullString(char c, int length) {
+  private static String fullString(char c, int length) {
     char[] result = new char[length];
     Arrays.fill(result, c);
     return new String(result);
   }
+
+  /**
+   * Helper to construct a byte array from a bunch of bytes.  The inputs are
+   * actually ints so that I can use hex notation and not get stupid errors
+   * about precision.
+   */
+  private static byte[] bytes(int... bytesAsInts) {
+    byte[] bytes = new byte[bytesAsInts.length];
+    for (int i = 0; i < bytesAsInts.length; i++) {
+      bytes[i] = (byte) bytesAsInts[i];
+    }
+    return bytes;
+  }
+
+  /** Arrays.asList() does not work with arrays of primitives.  :( */
+  private static List<Byte> toList(byte[] bytes) {
+    List<Byte> result = new ArrayList<Byte>();
+    for (byte b : bytes) {
+      result.add(b);
+    }
+    return result;
+  }
+
+  private static void assertEqualBytes(OutputType outputType, byte[] a, byte[] b) {
+    assertEquals(outputType.name(), toList(a), toList(b));
+  }
+
+  /**
+   * Writes the given value using writeRawVarint32() and writeRawVarint64() and
+   * checks that the result matches the given bytes.
+   */
+  private static void assertWriteVarint(byte[] data, long value) throws Exception {
+    for (OutputType outputType : OutputType.values()) {
+      // Only test 32-bit write if the value fits into an int.
+      if (value == (int) value) {
+        Coder coder = outputType.newCoder(10);
+        coder.stream().writeUInt32NoTag((int) value);
+        coder.stream().flush();
+        assertEqualBytes(outputType, data, coder.toByteArray());
+
+        // Also try computing size.
+        assertEquals(data.length, CodedOutputStream.computeUInt32SizeNoTag((int) value));
+      }
+
+      {
+        Coder coder = outputType.newCoder(10);
+        coder.stream().writeUInt64NoTag(value);
+        coder.stream().flush();
+        assertEqualBytes(outputType, data, coder.toByteArray());
+
+        // Also try computing size.
+        assertEquals(data.length, CodedOutputStream.computeUInt64SizeNoTag(value));
+      }
+    }
+
+    // Try different block sizes.
+    for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+      // Only test 32-bit write if the value fits into an int.
+      if (value == (int) value) {
+        Coder coder = OutputType.STREAM.newCoder(blockSize);
+        coder.stream().writeUInt64NoTag((int) value);
+        coder.stream().flush();
+        assertEqualBytes(OutputType.STREAM, data, coder.toByteArray());
+
+        ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+        CodedOutputStream output = CodedOutputStream.newInstance(rawOutput, blockSize);
+        output.writeUInt32NoTag((int) value);
+        output.flush();
+        assertEqualBytes(OutputType.STREAM, data, rawOutput.toByteArray());
+      }
+
+      {
+        Coder coder = OutputType.STREAM.newCoder(blockSize);
+        coder.stream().writeUInt64NoTag(value);
+        coder.stream().flush();
+        assertEqualBytes(OutputType.STREAM, data, coder.toByteArray());
+      }
+    }
+  }
+
+  private static void assertVarintRoundTrip(OutputType outputType, long value) throws Exception {
+    {
+      Coder coder = outputType.newCoder(10);
+      coder.stream().writeUInt64NoTag(value);
+      coder.stream().flush();
+      byte[] bytes = coder.toByteArray();
+      assertEquals(
+          outputType.name(), bytes.length, CodedOutputStream.computeUInt64SizeNoTag(value));
+      CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes));
+      assertEquals(outputType.name(), value, input.readRawVarint64());
+    }
+
+    if (value == (int) value) {
+      Coder coder = outputType.newCoder(10);
+      coder.stream().writeUInt32NoTag((int) value);
+      coder.stream().flush();
+      byte[] bytes = coder.toByteArray();
+      assertEquals(
+          outputType.name(), bytes.length, CodedOutputStream.computeUInt32SizeNoTag((int) value));
+      CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes));
+      assertEquals(outputType.name(), value, input.readRawVarint32());
+    }
+  }
 }

+ 0 - 14
java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java

@@ -73,20 +73,6 @@ public class DoubleArrayListTest extends TestCase {
     assertImmutable(list);
   }
   
-  public void testCopyConstructor() {
-    DoubleArrayList copy = new DoubleArrayList(TERTIARY_LIST);
-    assertEquals(TERTIARY_LIST, copy);
-
-    copy = new DoubleArrayList(DoubleArrayList.emptyList());
-    assertEquals(DoubleArrayList.emptyList(), copy);
-    
-    copy = new DoubleArrayList(asList(1D, 2D, 3D));
-    assertEquals(asList(1D, 2D, 3D), copy);
-
-    copy = new DoubleArrayList(Collections.<Double>emptyList());
-    assertEquals(DoubleArrayList.emptyList(), copy);
-  }
-  
   public void testModificationWithIteration() {
     list.addAll(asList(1D, 2D, 3D, 4D));
     Iterator<Double> iterator = list.iterator();

+ 0 - 14
java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java

@@ -73,20 +73,6 @@ public class FloatArrayListTest extends TestCase {
     assertImmutable(list);
   }
   
-  public void testCopyConstructor() {
-    FloatArrayList copy = new FloatArrayList(TERTIARY_LIST);
-    assertEquals(TERTIARY_LIST, copy);
-
-    copy = new FloatArrayList(FloatArrayList.emptyList());
-    assertEquals(FloatArrayList.emptyList(), copy);
-    
-    copy = new FloatArrayList(asList(1F, 2F, 3F));
-    assertEquals(asList(1F, 2F, 3F), copy);
-
-    copy = new FloatArrayList(Collections.<Float>emptyList());
-    assertEquals(FloatArrayList.emptyList(), copy);
-  }
-  
   public void testModificationWithIteration() {
     list.addAll(asList(1F, 2F, 3F, 4F));
     Iterator<Float> iterator = list.iterator();

+ 1 - 1
java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java

@@ -41,7 +41,7 @@ package com.google.protobuf;
  */
 public class ForceFieldBuildersPreRun implements Runnable {
 
-  //@Override (Java 1.6 override semantics, but we must support 1.5)
+  @Override
   public void run() {
     GeneratedMessage.enableAlwaysUseFieldBuildersForTesting();
   }

+ 4 - 4
java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java

@@ -723,7 +723,7 @@ public class GeneratedMessageTest extends TestCase {
 
   public void testLiteExtensionMessageOrBuilder() throws Exception {
     TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
-    TestUtil.setAllExtensions(builder);
+    TestUtilLite.setAllExtensions(builder);
     TestUtil.assertAllExtensionsSet(builder);
 
     TestAllExtensionsLite message = builder.build();
@@ -732,8 +732,8 @@ public class GeneratedMessageTest extends TestCase {
 
   public void testLiteExtensionRepeatedSetters() throws Exception {
     TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
-    TestUtil.setAllExtensions(builder);
-    TestUtil.modifyRepeatedExtensions(builder);
+    TestUtilLite.setAllExtensions(builder);
+    TestUtilLite.modifyRepeatedExtensions(builder);
     TestUtil.assertRepeatedExtensionsModified(builder);
 
     TestAllExtensionsLite message = builder.build();
@@ -760,7 +760,7 @@ public class GeneratedMessageTest extends TestCase {
   }
 
   public void testLiteExtensionCopy() throws Exception {
-    TestAllExtensionsLite original = TestUtil.getAllLiteExtensionsSet();
+    TestAllExtensionsLite original = TestUtilLite.getAllLiteExtensionsSet();
     TestAllExtensionsLite copy =
         TestAllExtensionsLite.newBuilder(original).build();
     TestUtil.assertAllExtensionsSet(copy);

+ 0 - 14
java/core/src/test/java/com/google/protobuf/IntArrayListTest.java

@@ -72,20 +72,6 @@ public class IntArrayListTest extends TestCase {
     list.makeImmutable();
     assertImmutable(list);
   }
-  
-  public void testCopyConstructor() {
-    IntArrayList copy = new IntArrayList(TERTIARY_LIST);
-    assertEquals(TERTIARY_LIST, copy);
-
-    copy = new IntArrayList(IntArrayList.emptyList());
-    assertEquals(IntArrayList.emptyList(), copy);
-    
-    copy = new IntArrayList(asList(1, 2, 3));
-    assertEquals(asList(1, 2, 3), copy);
-
-    copy = new IntArrayList(Collections.<Integer>emptyList());
-    assertEquals(IntArrayList.emptyList(), copy);
-  }
 
   public void testModificationWithIteration() {
     list.addAll(asList(1, 2, 3, 4));

+ 660 - 32
java/core/src/test/java/com/google/protobuf/LiteTest.java

@@ -33,17 +33,25 @@ package com.google.protobuf;
 import static java.util.Collections.emptyList;
 import static java.util.Collections.singletonList;
 
+import com.google.protobuf.UnittestImportLite.ImportEnumLite;
+import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
 import com.google.protobuf.UnittestLite;
 import com.google.protobuf.UnittestLite.ForeignEnumLite;
 import com.google.protobuf.UnittestLite.ForeignMessageLite;
 import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
 import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedEnum;
 import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedMessage;
 import com.google.protobuf.UnittestLite.TestAllTypesLite.OneofFieldCase;
 import com.google.protobuf.UnittestLite.TestAllTypesLite.OptionalGroup;
 import com.google.protobuf.UnittestLite.TestAllTypesLite.RepeatedGroup;
 import com.google.protobuf.UnittestLite.TestAllTypesLiteOrBuilder;
 import com.google.protobuf.UnittestLite.TestNestedExtensionLite;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.BarPrime;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestOneofEquals;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestRecursiveOneof;
 
 import junit.framework.TestCase;
 
@@ -59,6 +67,7 @@ import java.io.ObjectOutputStream;
  * @author kenton@google.com Kenton Varda
  */
 public class LiteTest extends TestCase {
+  @Override
   public void setUp() throws Exception {
     // Test that nested extensions are initialized correctly even if the outer
     // class has not been accessed directly.  This was once a bug with lite
@@ -302,11 +311,9 @@ public class LiteTest extends TestCase {
     assertEquals(
         ForeignMessageLite.getDefaultInstance(),
         message.getOptionalForeignMessage());
-    // LITE_RUNTIME doesn't implement equals so we compare on a property and
-    // ensure the property isn't set on foreignMessage.
-    assertEquals(3, builder.getOptionalForeignMessage().getC());
+    assertEquals(foreignMessageBuilder.build(), builder.getOptionalForeignMessage());
     messageAfterBuild = builder.build();
-    assertEquals(3, messageAfterBuild.getOptionalForeignMessage().getC());
+    assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getOptionalForeignMessage());
     assertEquals(
         ForeignMessageLite.getDefaultInstance(),
         message.getOptionalForeignMessage());
@@ -314,7 +321,7 @@ public class LiteTest extends TestCase {
     assertEquals(
         ForeignMessageLite.getDefaultInstance(),
         builder.getOptionalForeignMessage());
-    assertEquals(3, messageAfterBuild.getOptionalForeignMessage().getC());
+    assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getOptionalForeignMessage());
 
     message = builder.build();
     OptionalGroup optionalGroup = OptionalGroup.newBuilder()
@@ -339,17 +346,15 @@ public class LiteTest extends TestCase {
     builder.setOptionalGroup(optionalGroupBuilder);
     assertEquals(
         OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
-    // LITE_RUNTIME doesn't implement equals so we compare on a property and
-    // ensure the property isn't set on optionalGroup.
-    assertEquals(3, builder.getOptionalGroup().getA());
+    assertEquals(optionalGroupBuilder.build(), builder.getOptionalGroup());
     messageAfterBuild = builder.build();
-    assertEquals(3, messageAfterBuild.getOptionalGroup().getA());
+    assertEquals(optionalGroupBuilder.build(), messageAfterBuild.getOptionalGroup());
     assertEquals(
         OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
     builder.clearOptionalGroup();
     assertEquals(
         OptionalGroup.getDefaultInstance(), builder.getOptionalGroup());
-    assertEquals(3, messageAfterBuild.getOptionalGroup().getA());
+    assertEquals(optionalGroupBuilder.build(), messageAfterBuild.getOptionalGroup());
 
     message = builder.build();
     builder.setOptionalInt32(1);
@@ -400,17 +405,16 @@ public class LiteTest extends TestCase {
     assertEquals(
         NestedMessage.getDefaultInstance(),
         message.getOptionalLazyMessage());
-    // LITE_RUNTIME doesn't implement equals so we compare on a property.
-    assertEquals(3, builder.getOptionalLazyMessage().getBb());
+    assertEquals(nestedMessageBuilder.build(), builder.getOptionalLazyMessage());
     messageAfterBuild = builder.build();
-    assertEquals(3, messageAfterBuild.getOptionalLazyMessage().getBb());
+    assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getOptionalLazyMessage());
     assertEquals(
         NestedMessage.getDefaultInstance(),
         message.getOptionalLazyMessage());
     builder.clearOptionalLazyMessage();
     assertEquals(
         NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage());
-    assertEquals(3, messageAfterBuild.getOptionalLazyMessage().getBb());
+    assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getOptionalLazyMessage());
 
     message = builder.build();
     builder.setOptionalSfixed32(1);
@@ -1100,8 +1104,7 @@ public class LiteTest extends TestCase {
     assertEquals(0, message.getRepeatedForeignMessageCount());
     builder.setRepeatedForeignMessage(
         0, ForeignMessageLite.getDefaultInstance());
-    // LITE_RUNTIME doesn't implement equals so we compare on a property.
-    assertEquals(3, messageAfterBuild.getRepeatedForeignMessage(0).getC());
+    assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getRepeatedForeignMessage(0));
     assertEquals(
         ForeignMessageLite.getDefaultInstance(),
         builder.getRepeatedForeignMessage(0));
@@ -1114,8 +1117,7 @@ public class LiteTest extends TestCase {
     builder.setRepeatedForeignMessage(0, foreignMessageBuilder);
     assertEquals(
         foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0));
-    // LITE_RUNTIME doesn't implement equals so we compare on a property.
-    assertEquals(3, builder.getRepeatedForeignMessage(0).getC());
+    assertEquals(foreignMessageBuilder.build(), builder.getRepeatedForeignMessage(0));
     builder.clearRepeatedForeignMessage();
 
     message = builder.build();
@@ -1148,9 +1150,7 @@ public class LiteTest extends TestCase {
     messageAfterBuild = builder.build();
     assertEquals(0, message.getRepeatedGroupCount());
     builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
-    // LITE_RUNTIME doesn't implement equals so we compare on a property and
-    // ensure the property isn't set on repeatedGroup.
-    assertEquals(3, messageAfterBuild.getRepeatedGroup(0).getA());
+    assertEquals(repeatedGroupBuilder.build(), messageAfterBuild.getRepeatedGroup(0));
     assertEquals(
         RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
     builder.clearRepeatedGroup();
@@ -1160,9 +1160,7 @@ public class LiteTest extends TestCase {
     messageAfterBuild = builder.build();
     assertEquals(0, message.getRepeatedGroupCount());
     builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
-    // LITE_RUNTIME doesn't implement equals so we compare on a property and
-    // ensure the property isn't set on repeatedGroup.
-    assertEquals(3, messageAfterBuild.getRepeatedGroup(0).getA());
+    assertEquals(repeatedGroupBuilder.build(), messageAfterBuild.getRepeatedGroup(0));
     assertEquals(
         RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
     builder.clearRepeatedGroup();
@@ -1210,9 +1208,7 @@ public class LiteTest extends TestCase {
     messageAfterBuild = builder.build();
     assertEquals(0, message.getRepeatedLazyMessageCount());
     builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
-    // LITE_RUNTIME doesn't implement equals so we compare on a property and
-    // ensure the property isn't set on repeatedGroup.
-    assertEquals(3, messageAfterBuild.getRepeatedLazyMessage(0).getBb());
+    assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getRepeatedLazyMessage(0));
     assertEquals(
         NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
     builder.clearRepeatedLazyMessage();
@@ -1222,9 +1218,7 @@ public class LiteTest extends TestCase {
     messageAfterBuild = builder.build();
     assertEquals(0, message.getRepeatedLazyMessageCount());
     builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
-    // LITE_RUNTIME doesn't implement equals so we compare on a property and
-    // ensure the property isn't set on repeatedGroup.
-    assertEquals(3, messageAfterBuild.getRepeatedLazyMessage(0).getBb());
+    assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getRepeatedLazyMessage(0));
     assertEquals(
         NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
     builder.clearRepeatedLazyMessage();
@@ -1456,7 +1450,7 @@ public class LiteTest extends TestCase {
         .setOptionalFloat(2.72f)
         .setOptionalDouble(3.14)
         .build();
-    assertToStringEquals("optional_float: 2.72\noptional_double: 3.14", proto);
+    assertToStringEquals("optional_double: 3.14\noptional_float: 2.72", proto);
   }
 
   public void testToStringStringFields() throws Exception {
@@ -1511,7 +1505,7 @@ public class LiteTest extends TestCase {
             .setC(3))
         .build();
     assertToStringEquals(
-        "optional_foreign_message {\n  c: 3\n}\noptional_foreign_enum: FOREIGN_LITE_BAR",
+        "optional_foreign_enum: FOREIGN_LITE_BAR\noptional_foreign_message {\n  c: 3\n}",
         proto);
   }
 
@@ -1546,6 +1540,27 @@ public class LiteTest extends TestCase {
         "1: 123\n18: \"\\b\\a\"\n21: 3\n44: \"spam\"\n44: \"eggs\"",
         messageWithUnknownFields);
   }
+  
+  public void testToStringLazyMessage() throws Exception {
+    TestAllTypesLite message = TestAllTypesLite.newBuilder()
+        .setOptionalLazyMessage(NestedMessage.newBuilder().setBb(1).build())
+        .build();
+    assertToStringEquals("optional_lazy_message {\n  bb: 1\n}", message);
+  }
+  
+  public void testToStringGroup() throws Exception {
+    TestAllTypesLite message = TestAllTypesLite.newBuilder()
+        .setOptionalGroup(OptionalGroup.newBuilder().setA(1).build())
+        .build();
+    assertToStringEquals("optional_group {\n  a: 1\n}", message);
+  }
+  
+  public void testToStringOneof() throws Exception {
+    TestAllTypesLite message = TestAllTypesLite.newBuilder()
+        .setOneofString("hello")
+        .build();
+    assertToStringEquals("oneof_string: \"hello\"", message);
+  }
 
   // Asserts that the toString() representation of the message matches the expected. This verifies
   // the first line starts with a comment; but, does not factor in said comment as part of the
@@ -1598,4 +1613,617 @@ public class LiteTest extends TestCase {
     assertEquals(11, message.getOneofLazyNestedMessage().getBb());
     assertEquals(22L, message.getOneofLazyNestedMessage().getCc());
   }
+
+  public void testMergeFromStream_repeatedField() throws Exception {
+    TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder()
+        .addRepeatedString("hello");
+    builder.mergeFrom(CodedInputStream.newInstance(builder.build().toByteArray()));
+
+    assertEquals(2, builder.getRepeatedStringCount());
+  }
+
+  public void testMergeFromStream_invalidBytes() throws Exception {
+    TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder()
+        .setDefaultBool(true);
+    try {
+      builder.mergeFrom(CodedInputStream.newInstance("Invalid bytes".getBytes(Internal.UTF_8)));
+      fail();
+    } catch (InvalidProtocolBufferException expected) {}
+  }
+  
+  public void testMergeFrom_sanity() throws Exception {
+    TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build();
+    byte[] bytes = one.toByteArray();
+    TestAllTypesLite two = TestAllTypesLite.parseFrom(bytes);
+    
+    one = one.toBuilder().mergeFrom(one).build();
+    two = two.toBuilder().mergeFrom(bytes).build();
+    assertEquals(one, two);
+    assertEquals(two, one);
+    assertEquals(one.hashCode(), two.hashCode());
+  }
+  
+  public void testEquals_notEqual() throws Exception {
+    TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build();
+    byte[] bytes = one.toByteArray();
+    TestAllTypesLite two = one.toBuilder().mergeFrom(one).mergeFrom(bytes).build();
+    
+    assertFalse(one.equals(two));
+    assertFalse(two.equals(one));
+    
+    assertFalse(one.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(one));
+    
+    TestAllTypesLite oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultBool(true)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultCord("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultCordBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultDouble(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultFixed32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultFixed64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultFloat(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultImportEnum(ImportEnumLite.IMPORT_LITE_BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultInt32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultInt64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultNestedEnum(NestedEnum.BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultSfixed32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultSfixed64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultSint32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultSint64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultString("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultStringBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultStringPiece("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultStringPieceBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultUint32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setDefaultUint64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedBool(true)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedCord("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedCordBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedDouble(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedFixed32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedFixed64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedFloat(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedImportEnum(ImportEnumLite.IMPORT_LITE_BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedInt32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedInt64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedNestedEnum(NestedEnum.BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedSfixed32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedSfixed64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedSint32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedSint64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedString("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedStringBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedStringPiece("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedStringPieceBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedUint32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedUint64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalBool(true)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalCord("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalCordBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalDouble(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalFixed32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalFixed64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalFloat(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalImportEnum(ImportEnumLite.IMPORT_LITE_BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalInt32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalInt64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalNestedEnum(NestedEnum.BAR)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalSfixed32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalSfixed64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalSint32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalSint64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalString("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalStringBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalStringPiece("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalStringPieceBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalUint32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalUint64(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOneofBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOneofLazyNestedMessage(NestedMessage.getDefaultInstance())
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOneofNestedMessage(NestedMessage.getDefaultInstance())
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOneofString("")
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOneofStringBytes(ByteString.EMPTY)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOneofUint32(0)
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalForeignMessage(ForeignMessageLite.getDefaultInstance())
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalGroup(OptionalGroup.getDefaultInstance())
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalPublicImportMessage(PublicImportMessageLite.getDefaultInstance())
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .setOptionalLazyMessage(NestedMessage.getDefaultInstance())
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+    oneFieldSet = TestAllTypesLite.newBuilder()
+        .addRepeatedLazyMessage(NestedMessage.getDefaultInstance())
+        .build();
+    assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+    assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+  }
+
+  public void testEquals() throws Exception {
+    // Check that two identical objs are equal.
+    Foo foo1a = Foo.newBuilder()
+        .setValue(1)
+        .addBar(Bar.newBuilder().setName("foo1"))
+        .build();
+    Foo foo1b = Foo.newBuilder()
+        .setValue(1)
+        .addBar(Bar.newBuilder().setName("foo1"))
+        .build();
+    Foo foo2 = Foo.newBuilder()
+        .setValue(1)
+        .addBar(Bar.newBuilder().setName("foo2"))
+        .build();
+
+    // Check that equals is doing value rather than object equality.
+    assertEquals(foo1a, foo1b);
+    assertEquals(foo1a.hashCode(), foo1b.hashCode());
+
+    // Check that a diffeent object is not equal.
+    assertFalse(foo1a.equals(foo2));
+
+    // Check that two objects which have different types but the same field values are not
+    // considered to be equal.
+    Bar bar = Bar.newBuilder().setName("bar").build();
+    BarPrime barPrime = BarPrime.newBuilder().setName("bar").build();
+    assertFalse(bar.equals(barPrime));
+  }
+
+  public void testOneofEquals() throws Exception {
+    TestOneofEquals.Builder builder = TestOneofEquals.newBuilder();
+    TestOneofEquals message1 = builder.build();
+    // Set message2's name field to default value. The two messages should be different when we
+    // check with the oneof case.
+    builder.setName("");
+    TestOneofEquals message2 = builder.build();
+    assertFalse(message1.equals(message2));
+  }
+  
+  public void testEquals_sanity() throws Exception {
+    TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build();
+    TestAllTypesLite two = TestAllTypesLite.parseFrom(one.toByteArray());
+    assertEquals(one, two);
+    assertEquals(one.hashCode(), two.hashCode());
+    
+    assertEquals(
+        one.toBuilder().mergeFrom(two).build(),
+        two.toBuilder().mergeFrom(two.toByteArray()).build());
+  }
+
+  public void testEqualsAndHashCodeWithUnknownFields() throws InvalidProtocolBufferException {
+    Foo fooWithOnlyValue = Foo.newBuilder()
+        .setValue(1)
+        .build();
+
+    Foo fooWithValueAndExtension = fooWithOnlyValue.toBuilder()
+        .setValue(1)
+        .setExtension(Bar.fooExt, Bar.newBuilder()
+            .setName("name")
+            .build())
+        .build();
+
+    Foo fooWithValueAndUnknownFields = Foo.parseFrom(fooWithValueAndExtension.toByteArray());
+
+    assertEqualsAndHashCodeAreFalse(fooWithOnlyValue, fooWithValueAndUnknownFields);
+    assertEqualsAndHashCodeAreFalse(fooWithValueAndExtension, fooWithValueAndUnknownFields);
+  }
+  
+  // Test to ensure we avoid a class cast exception with oneofs.
+  public void testEquals_oneOfMessages() {
+    TestAllTypesLite mine = TestAllTypesLite.newBuilder()
+        .setOneofString("Hello")
+        .build();
+    
+    TestAllTypesLite other = TestAllTypesLite.newBuilder()
+        .setOneofNestedMessage(NestedMessage.getDefaultInstance())
+        .build();
+    
+    assertFalse(mine.equals(other));
+    assertFalse(other.equals(mine));
+  }
+
+  private void assertEqualsAndHashCodeAreFalse(Object o1, Object o2) {
+    assertFalse(o1.equals(o2));
+    assertFalse(o1.hashCode() == o2.hashCode());
+  }
+
+  public void testRecursiveHashcode() {
+    // This tests that we don't infinite loop.
+    TestRecursiveOneof.getDefaultInstance().hashCode();
+  }
 }

+ 0 - 14
java/core/src/test/java/com/google/protobuf/LongArrayListTest.java

@@ -73,20 +73,6 @@ public class LongArrayListTest extends TestCase {
     assertImmutable(list);
   }
   
-  public void testCopyConstructor() {
-    LongArrayList copy = new LongArrayList(TERTIARY_LIST);
-    assertEquals(TERTIARY_LIST, copy);
-
-    copy = new LongArrayList(LongArrayList.emptyList());
-    assertEquals(LongArrayList.emptyList(), copy);
-    
-    copy = new LongArrayList(asList(1L, 2L, 3L));
-    assertEquals(asList(1L, 2L, 3L), copy);
-
-    copy = new LongArrayList(Collections.<Long>emptyList());
-    assertEquals(LongArrayList.emptyList(), copy);
-  }
-  
   public void testModificationWithIteration() {
     list.addAll(asList(1L, 2L, 3L, 4L));
     Iterator<Long> iterator = list.iterator();

+ 8 - 8
java/core/src/test/java/com/google/protobuf/ParserTest.java

@@ -179,16 +179,16 @@ public class ParserTest extends TestCase {
   public void testParseExtensions() throws Exception {
     assertRoundTripEquals(TestUtil.getAllExtensionsSet(),
                           TestUtil.getExtensionRegistry());
-    assertRoundTripEquals(TestUtil.getAllLiteExtensionsSet(),
-                          TestUtil.getExtensionRegistryLite());
+    assertRoundTripEquals(
+        TestUtilLite.getAllLiteExtensionsSet(), TestUtilLite.getExtensionRegistryLite());
   }
 
   public void testParsePacked() throws Exception {
     assertRoundTripEquals(TestUtil.getPackedSet());
     assertRoundTripEquals(TestUtil.getPackedExtensionsSet(),
                           TestUtil.getExtensionRegistry());
-    assertRoundTripEquals(TestUtil.getLitePackedExtensionsSet(),
-                          TestUtil.getExtensionRegistryLite());
+    assertRoundTripEquals(
+        TestUtilLite.getLitePackedExtensionsSet(), TestUtilLite.getExtensionRegistryLite());
   }
 
   public void testParseDelimitedTo() throws Exception {
@@ -198,8 +198,7 @@ public class ParserTest extends TestCase {
     normalMessage.writeDelimitedTo(output);
 
     // Write MessageLite with packed extension fields.
-    TestPackedExtensionsLite packedMessage =
-        TestUtil.getLitePackedExtensionsSet();
+    TestPackedExtensionsLite packedMessage = TestUtilLite.getLitePackedExtensionsSet();
     packedMessage.writeDelimitedTo(output);
 
     InputStream input = new ByteArrayInputStream(output.toByteArray());
@@ -208,8 +207,9 @@ public class ParserTest extends TestCase {
         normalMessage.getParserForType().parseDelimitedFrom(input));
     assertMessageEquals(
         packedMessage,
-        packedMessage.getParserForType().parseDelimitedFrom(
-            input, TestUtil.getExtensionRegistryLite()));
+        packedMessage
+            .getParserForType()
+            .parseDelimitedFrom(input, TestUtilLite.getExtensionRegistryLite()));
   }
 
   public void testParseUnknownFields() throws Exception {

+ 0 - 14
java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java

@@ -63,20 +63,6 @@ public class ProtobufArrayListTest extends TestCase {
     assertImmutable(ProtobufArrayList.<Integer>emptyList());
   }
   
-  public void testCopyConstructor() {
-    ProtobufArrayList<Integer> copy = new ProtobufArrayList<Integer>(TERTIARY_LIST);
-    assertEquals(TERTIARY_LIST, copy);
-
-    copy = new ProtobufArrayList<Integer>(IntArrayList.emptyList());
-    assertEquals(ProtobufArrayList.emptyList(), copy);
-    
-    copy = new ProtobufArrayList<Integer>(asList(1, 2, 3));
-    assertEquals(asList(1, 2, 3), copy);
-
-    copy = new ProtobufArrayList<Integer>(Collections.<Integer>emptyList());
-    assertEquals(ProtobufArrayList.emptyList(), copy);
-  }
-  
   public void testModificationWithIteration() {
     list.addAll(asList(1, 2, 3, 4));
     Iterator<Integer> iterator = list.iterator();

+ 13 - 7
java/core/src/test/java/com/google/protobuf/ServiceTest.java

@@ -175,12 +175,14 @@ public class ServiceTest extends TestCase {
     MethodDescriptor fooMethod =
         ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
     MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
-    RpcCallback<Message> callback = new RpcCallback<Message>() {
-      public void run(Message parameter) {
-        // No reason this should be run.
-        fail();
-      }
-    };
+    RpcCallback<Message> callback =
+        new RpcCallback<Message>() {
+          @Override
+          public void run(Message parameter) {
+            // No reason this should be run.
+            fail();
+          }
+        };
     RpcCallback<TestAllTypes> specializedCallback =
         RpcUtil.specializeCallback(callback);
 
@@ -290,7 +292,9 @@ public class ServiceTest extends TestCase {
     public boolean isCalled() { return called; }
 
     public void reset() { called = false; }
-    public void run(Type message) { called = true; }
+    @Override
+    public void run(Type message) {
+      called = true; }
   }
 
   /** Implementation of the wrapsCallback() argument matcher. */
@@ -301,6 +305,7 @@ public class ServiceTest extends TestCase {
       this.callback = callback;
     }
 
+    @Override
     @SuppressWarnings("unchecked")
     public boolean matches(Object actual) {
       if (!(actual instanceof RpcCallback)) {
@@ -313,6 +318,7 @@ public class ServiceTest extends TestCase {
       return callback.isCalled();
     }
 
+    @Override
     public void appendTo(StringBuffer buffer) {
       buffer.append("wrapsCallback(mockCallback)");
     }

+ 3 - 0
java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java

@@ -56,14 +56,17 @@ public class SmallSortedMapTest extends TestCase {
       this.value = value;
     }
 
+    @Override
     public K getKey() {
       return key;
     }
 
+    @Override
     public V getValue() {
       return value;
     }
 
+    @Override
     public V setValue(V value) {
       V oldValue = this.value;
       this.value = value;

+ 2 - 407
java/core/src/test/java/com/google/protobuf/TestUtil.java

@@ -30,8 +30,6 @@
 
 package com.google.protobuf;
 
-import static com.google.protobuf.UnittestLite.OptionalGroup_extension_lite;
-import static com.google.protobuf.UnittestLite.RepeatedGroup_extension_lite;
 import static com.google.protobuf.UnittestLite.defaultBoolExtensionLite;
 import static com.google.protobuf.UnittestLite.defaultBytesExtensionLite;
 import static com.google.protobuf.UnittestLite.defaultCordExtensionLite;
@@ -216,12 +214,7 @@ import static protobuf_unittest.UnittestProto.repeatedUint32Extension;
 import static protobuf_unittest.UnittestProto.repeatedUint64Extension;
 
 import com.google.protobuf.UnittestImportLite.ImportEnumLite;
-import com.google.protobuf.UnittestImportLite.ImportMessageLite;
-import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
-import com.google.protobuf.UnittestLite;
 import com.google.protobuf.UnittestLite.ForeignEnumLite;
-import com.google.protobuf.UnittestLite.ForeignMessageLite;
-import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
 import com.google.protobuf.UnittestLite.TestAllExtensionsLiteOrBuilder;
 import com.google.protobuf.UnittestLite.TestAllTypesLite;
 import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
@@ -286,16 +279,6 @@ public final class TestUtil {
     return builder;
   }
 
-  /**
-   * Get a {@code TestAllTypesLite.Builder} with all fields set as they would be by
-   * {@link #setAllFields(TestAllTypesLite.Builder)}.
-   */
-  public static TestAllTypesLite.Builder getAllLiteSetBuilder() {
-    TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder();
-    setAllFields(builder);
-    return builder;
-  }
-
   /**
    * Get a {@code TestAllExtensions} with all fields set as they would be by
    * {@link #setAllExtensions(TestAllExtensions.Builder)}.
@@ -306,12 +289,6 @@ public final class TestUtil {
     return builder.build();
   }
 
-  public static TestAllExtensionsLite getAllLiteExtensionsSet() {
-    TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
-    setAllExtensions(builder);
-    return builder.build();
-  }
-
   public static TestPackedTypes getPackedSet() {
     TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
     setPackedFields(builder);
@@ -330,157 +307,6 @@ public final class TestUtil {
     return builder.build();
   }
 
-  public static TestPackedExtensionsLite getLitePackedExtensionsSet() {
-    TestPackedExtensionsLite.Builder builder =
-        TestPackedExtensionsLite.newBuilder();
-    setPackedExtensions(builder);
-    return builder.build();
-  }
-  
-  /**
-   * Set every field of {@code builder} to the values expected by
-   * {@code assertAllFieldsSet()}.
-   */
-  public static void setAllFields(TestAllTypesLite.Builder builder) {
-    builder.setOptionalInt32   (101);
-    builder.setOptionalInt64   (102);
-    builder.setOptionalUint32  (103);
-    builder.setOptionalUint64  (104);
-    builder.setOptionalSint32  (105);
-    builder.setOptionalSint64  (106);
-    builder.setOptionalFixed32 (107);
-    builder.setOptionalFixed64 (108);
-    builder.setOptionalSfixed32(109);
-    builder.setOptionalSfixed64(110);
-    builder.setOptionalFloat   (111);
-    builder.setOptionalDouble  (112);
-    builder.setOptionalBool    (true);
-    builder.setOptionalString  ("115");
-    builder.setOptionalBytes   (toBytes("116"));
-
-    builder.setOptionalGroup(
-        TestAllTypesLite.OptionalGroup.newBuilder().setA(117).build());
-    builder.setOptionalNestedMessage(
-        TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build());
-    builder.setOptionalForeignMessage(
-        ForeignMessageLite.newBuilder().setC(119).build());
-    builder.setOptionalImportMessage(
-        ImportMessageLite.newBuilder().setD(120).build());
-    builder.setOptionalPublicImportMessage(
-        PublicImportMessageLite.newBuilder().setE(126).build());
-    builder.setOptionalLazyMessage(
-        TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build());
-
-    builder.setOptionalNestedEnum (TestAllTypesLite.NestedEnum.BAZ);
-    builder.setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAZ);
-    builder.setOptionalImportEnum (ImportEnumLite.IMPORT_LITE_BAZ);
-
-    builder.setOptionalStringPiece("124");
-    builder.setOptionalCord("125");
-
-    // -----------------------------------------------------------------
-
-    builder.addRepeatedInt32   (201);
-    builder.addRepeatedInt64   (202);
-    builder.addRepeatedUint32  (203);
-    builder.addRepeatedUint64  (204);
-    builder.addRepeatedSint32  (205);
-    builder.addRepeatedSint64  (206);
-    builder.addRepeatedFixed32 (207);
-    builder.addRepeatedFixed64 (208);
-    builder.addRepeatedSfixed32(209);
-    builder.addRepeatedSfixed64(210);
-    builder.addRepeatedFloat   (211);
-    builder.addRepeatedDouble  (212);
-    builder.addRepeatedBool    (true);
-    builder.addRepeatedString  ("215");
-    builder.addRepeatedBytes   (toBytes("216"));
-
-    builder.addRepeatedGroup(
-        TestAllTypesLite.RepeatedGroup.newBuilder().setA(217).build());
-    builder.addRepeatedNestedMessage(
-        TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build());
-    builder.addRepeatedForeignMessage(
-        ForeignMessageLite.newBuilder().setC(219).build());
-    builder.addRepeatedImportMessage(
-        ImportMessageLite.newBuilder().setD(220).build());
-    builder.addRepeatedLazyMessage(
-        TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build());
-
-    builder.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAR);
-    builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
-    builder.addRepeatedImportEnum (ImportEnumLite.IMPORT_LITE_BAR);
-
-    builder.addRepeatedStringPiece("224");
-    builder.addRepeatedCord("225");
-
-    // Add a second one of each field.
-    builder.addRepeatedInt32   (301);
-    builder.addRepeatedInt64   (302);
-    builder.addRepeatedUint32  (303);
-    builder.addRepeatedUint64  (304);
-    builder.addRepeatedSint32  (305);
-    builder.addRepeatedSint64  (306);
-    builder.addRepeatedFixed32 (307);
-    builder.addRepeatedFixed64 (308);
-    builder.addRepeatedSfixed32(309);
-    builder.addRepeatedSfixed64(310);
-    builder.addRepeatedFloat   (311);
-    builder.addRepeatedDouble  (312);
-    builder.addRepeatedBool    (false);
-    builder.addRepeatedString  ("315");
-    builder.addRepeatedBytes   (toBytes("316"));
-
-    builder.addRepeatedGroup(
-        TestAllTypesLite.RepeatedGroup.newBuilder().setA(317).build());
-    builder.addRepeatedNestedMessage(
-        TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build());
-    builder.addRepeatedForeignMessage(
-        ForeignMessageLite.newBuilder().setC(319).build());
-    builder.addRepeatedImportMessage(
-        ImportMessageLite.newBuilder().setD(320).build());
-    builder.addRepeatedLazyMessage(
-        TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build());
-
-    builder.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAZ);
-    builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAZ);
-    builder.addRepeatedImportEnum (ImportEnumLite.IMPORT_LITE_BAZ);
-
-    builder.addRepeatedStringPiece("324");
-    builder.addRepeatedCord("325");
-
-    // -----------------------------------------------------------------
-
-    builder.setDefaultInt32   (401);
-    builder.setDefaultInt64   (402);
-    builder.setDefaultUint32  (403);
-    builder.setDefaultUint64  (404);
-    builder.setDefaultSint32  (405);
-    builder.setDefaultSint64  (406);
-    builder.setDefaultFixed32 (407);
-    builder.setDefaultFixed64 (408);
-    builder.setDefaultSfixed32(409);
-    builder.setDefaultSfixed64(410);
-    builder.setDefaultFloat   (411);
-    builder.setDefaultDouble  (412);
-    builder.setDefaultBool    (false);
-    builder.setDefaultString  ("415");
-    builder.setDefaultBytes   (toBytes("416"));
-
-    builder.setDefaultNestedEnum (TestAllTypesLite.NestedEnum.FOO);
-    builder.setDefaultForeignEnum(ForeignEnumLite.FOREIGN_LITE_FOO);
-    builder.setDefaultImportEnum (ImportEnumLite.IMPORT_LITE_FOO);
-
-    builder.setDefaultStringPiece("424");
-    builder.setDefaultCord("425");
-
-    builder.setOneofUint32(601);
-    builder.setOneofNestedMessage(
-        TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build());
-    builder.setOneofString("603");
-    builder.setOneofBytes(toBytes("604"));
-  }
-
   /**
    * Set every field of {@code message} to the values expected by
    * {@code assertAllFieldsSet()}.
@@ -1370,23 +1196,13 @@ public final class TestUtil {
     return registry.getUnmodifiable();
   }
 
-  public static ExtensionRegistryLite getExtensionRegistryLite() {
-    ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance();
-    registerAllExtensionsLite(registry);
-    return registry.getUnmodifiable();
-  }
-
   /**
    * Register all of {@code TestAllExtensions}'s extensions with the
    * given {@link ExtensionRegistry}.
    */
   public static void registerAllExtensions(ExtensionRegistry registry) {
     UnittestProto.registerAllExtensions(registry);
-    registerAllExtensionsLite(registry);
-  }
-
-  public static void registerAllExtensionsLite(ExtensionRegistryLite registry) {
-    UnittestLite.registerAllExtensions(registry);
+    TestUtilLite.registerAllExtensionsLite(registry);
   }
 
   /**
@@ -2179,195 +1995,6 @@ public final class TestUtil {
   // ===================================================================
   // Lite extensions
 
-  /**
-   * Set every field of {@code message} to the values expected by
-   * {@code assertAllExtensionsSet()}.
-   */
-  public static void setAllExtensions(TestAllExtensionsLite.Builder message) {
-    message.setExtension(optionalInt32ExtensionLite   , 101);
-    message.setExtension(optionalInt64ExtensionLite   , 102L);
-    message.setExtension(optionalUint32ExtensionLite  , 103);
-    message.setExtension(optionalUint64ExtensionLite  , 104L);
-    message.setExtension(optionalSint32ExtensionLite  , 105);
-    message.setExtension(optionalSint64ExtensionLite  , 106L);
-    message.setExtension(optionalFixed32ExtensionLite , 107);
-    message.setExtension(optionalFixed64ExtensionLite , 108L);
-    message.setExtension(optionalSfixed32ExtensionLite, 109);
-    message.setExtension(optionalSfixed64ExtensionLite, 110L);
-    message.setExtension(optionalFloatExtensionLite   , 111F);
-    message.setExtension(optionalDoubleExtensionLite  , 112D);
-    message.setExtension(optionalBoolExtensionLite    , true);
-    message.setExtension(optionalStringExtensionLite  , "115");
-    message.setExtension(optionalBytesExtensionLite   , toBytes("116"));
-
-    message.setExtension(optionalGroupExtensionLite,
-      OptionalGroup_extension_lite.newBuilder().setA(117).build());
-    message.setExtension(optionalNestedMessageExtensionLite,
-      TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build());
-    message.setExtension(optionalForeignMessageExtensionLite,
-      ForeignMessageLite.newBuilder().setC(119).build());
-    message.setExtension(optionalImportMessageExtensionLite,
-      ImportMessageLite.newBuilder().setD(120).build());
-    message.setExtension(optionalPublicImportMessageExtensionLite,
-      PublicImportMessageLite.newBuilder().setE(126).build());
-    message.setExtension(optionalLazyMessageExtensionLite,
-      TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build());
-
-    message.setExtension(optionalNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
-    message.setExtension(optionalForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
-    message.setExtension(optionalImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ);
-
-    message.setExtension(optionalStringPieceExtensionLite, "124");
-    message.setExtension(optionalCordExtensionLite, "125");
-
-    // -----------------------------------------------------------------
-
-    message.addExtension(repeatedInt32ExtensionLite   , 201);
-    message.addExtension(repeatedInt64ExtensionLite   , 202L);
-    message.addExtension(repeatedUint32ExtensionLite  , 203);
-    message.addExtension(repeatedUint64ExtensionLite  , 204L);
-    message.addExtension(repeatedSint32ExtensionLite  , 205);
-    message.addExtension(repeatedSint64ExtensionLite  , 206L);
-    message.addExtension(repeatedFixed32ExtensionLite , 207);
-    message.addExtension(repeatedFixed64ExtensionLite , 208L);
-    message.addExtension(repeatedSfixed32ExtensionLite, 209);
-    message.addExtension(repeatedSfixed64ExtensionLite, 210L);
-    message.addExtension(repeatedFloatExtensionLite   , 211F);
-    message.addExtension(repeatedDoubleExtensionLite  , 212D);
-    message.addExtension(repeatedBoolExtensionLite    , true);
-    message.addExtension(repeatedStringExtensionLite  , "215");
-    message.addExtension(repeatedBytesExtensionLite   , toBytes("216"));
-
-    message.addExtension(repeatedGroupExtensionLite,
-      RepeatedGroup_extension_lite.newBuilder().setA(217).build());
-    message.addExtension(repeatedNestedMessageExtensionLite,
-      TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build());
-    message.addExtension(repeatedForeignMessageExtensionLite,
-      ForeignMessageLite.newBuilder().setC(219).build());
-    message.addExtension(repeatedImportMessageExtensionLite,
-      ImportMessageLite.newBuilder().setD(220).build());
-    message.addExtension(repeatedLazyMessageExtensionLite,
-      TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build());
-
-    message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAR);
-    message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
-    message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAR);
-
-    message.addExtension(repeatedStringPieceExtensionLite, "224");
-    message.addExtension(repeatedCordExtensionLite, "225");
-
-    // Add a second one of each field.
-    message.addExtension(repeatedInt32ExtensionLite   , 301);
-    message.addExtension(repeatedInt64ExtensionLite   , 302L);
-    message.addExtension(repeatedUint32ExtensionLite  , 303);
-    message.addExtension(repeatedUint64ExtensionLite  , 304L);
-    message.addExtension(repeatedSint32ExtensionLite  , 305);
-    message.addExtension(repeatedSint64ExtensionLite  , 306L);
-    message.addExtension(repeatedFixed32ExtensionLite , 307);
-    message.addExtension(repeatedFixed64ExtensionLite , 308L);
-    message.addExtension(repeatedSfixed32ExtensionLite, 309);
-    message.addExtension(repeatedSfixed64ExtensionLite, 310L);
-    message.addExtension(repeatedFloatExtensionLite   , 311F);
-    message.addExtension(repeatedDoubleExtensionLite  , 312D);
-    message.addExtension(repeatedBoolExtensionLite    , false);
-    message.addExtension(repeatedStringExtensionLite  , "315");
-    message.addExtension(repeatedBytesExtensionLite   , toBytes("316"));
-
-    message.addExtension(repeatedGroupExtensionLite,
-      RepeatedGroup_extension_lite.newBuilder().setA(317).build());
-    message.addExtension(repeatedNestedMessageExtensionLite,
-      TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build());
-    message.addExtension(repeatedForeignMessageExtensionLite,
-      ForeignMessageLite.newBuilder().setC(319).build());
-    message.addExtension(repeatedImportMessageExtensionLite,
-      ImportMessageLite.newBuilder().setD(320).build());
-    message.addExtension(repeatedLazyMessageExtensionLite,
-      TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build());
-
-    message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
-    message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
-    message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ);
-
-    message.addExtension(repeatedStringPieceExtensionLite, "324");
-    message.addExtension(repeatedCordExtensionLite, "325");
-
-    // -----------------------------------------------------------------
-
-    message.setExtension(defaultInt32ExtensionLite   , 401);
-    message.setExtension(defaultInt64ExtensionLite   , 402L);
-    message.setExtension(defaultUint32ExtensionLite  , 403);
-    message.setExtension(defaultUint64ExtensionLite  , 404L);
-    message.setExtension(defaultSint32ExtensionLite  , 405);
-    message.setExtension(defaultSint64ExtensionLite  , 406L);
-    message.setExtension(defaultFixed32ExtensionLite , 407);
-    message.setExtension(defaultFixed64ExtensionLite , 408L);
-    message.setExtension(defaultSfixed32ExtensionLite, 409);
-    message.setExtension(defaultSfixed64ExtensionLite, 410L);
-    message.setExtension(defaultFloatExtensionLite   , 411F);
-    message.setExtension(defaultDoubleExtensionLite  , 412D);
-    message.setExtension(defaultBoolExtensionLite    , false);
-    message.setExtension(defaultStringExtensionLite  , "415");
-    message.setExtension(defaultBytesExtensionLite   , toBytes("416"));
-
-    message.setExtension(defaultNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.FOO);
-    message.setExtension(defaultForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_FOO);
-    message.setExtension(defaultImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_FOO);
-
-    message.setExtension(defaultStringPieceExtensionLite, "424");
-    message.setExtension(defaultCordExtensionLite, "425");
-
-    message.setExtension(oneofUint32ExtensionLite, 601);
-    message.setExtension(oneofNestedMessageExtensionLite,
-      TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build());
-    message.setExtension(oneofStringExtensionLite, "603");
-    message.setExtension(oneofBytesExtensionLite, toBytes("604"));
-  }
-
-  // -------------------------------------------------------------------
-
-  /**
-   * Modify the repeated extensions of {@code message} to contain the values
-   * expected by {@code assertRepeatedExtensionsModified()}.
-   */
-  public static void modifyRepeatedExtensions(
-      TestAllExtensionsLite.Builder message) {
-    message.setExtension(repeatedInt32ExtensionLite   , 1, 501);
-    message.setExtension(repeatedInt64ExtensionLite   , 1, 502L);
-    message.setExtension(repeatedUint32ExtensionLite  , 1, 503);
-    message.setExtension(repeatedUint64ExtensionLite  , 1, 504L);
-    message.setExtension(repeatedSint32ExtensionLite  , 1, 505);
-    message.setExtension(repeatedSint64ExtensionLite  , 1, 506L);
-    message.setExtension(repeatedFixed32ExtensionLite , 1, 507);
-    message.setExtension(repeatedFixed64ExtensionLite , 1, 508L);
-    message.setExtension(repeatedSfixed32ExtensionLite, 1, 509);
-    message.setExtension(repeatedSfixed64ExtensionLite, 1, 510L);
-    message.setExtension(repeatedFloatExtensionLite   , 1, 511F);
-    message.setExtension(repeatedDoubleExtensionLite  , 1, 512D);
-    message.setExtension(repeatedBoolExtensionLite    , 1, true);
-    message.setExtension(repeatedStringExtensionLite  , 1, "515");
-    message.setExtension(repeatedBytesExtensionLite   , 1, toBytes("516"));
-
-    message.setExtension(repeatedGroupExtensionLite, 1,
-      RepeatedGroup_extension_lite.newBuilder().setA(517).build());
-    message.setExtension(repeatedNestedMessageExtensionLite, 1,
-      TestAllTypesLite.NestedMessage.newBuilder().setBb(518).build());
-    message.setExtension(repeatedForeignMessageExtensionLite, 1,
-      ForeignMessageLite.newBuilder().setC(519).build());
-    message.setExtension(repeatedImportMessageExtensionLite, 1,
-      ImportMessageLite.newBuilder().setD(520).build());
-    message.setExtension(repeatedLazyMessageExtensionLite, 1,
-      TestAllTypesLite.NestedMessage.newBuilder().setBb(527).build());
-
-    message.setExtension(repeatedNestedEnumExtensionLite , 1, TestAllTypesLite.NestedEnum.FOO);
-    message.setExtension(repeatedForeignEnumExtensionLite, 1, ForeignEnumLite.FOREIGN_LITE_FOO);
-    message.setExtension(repeatedImportEnumExtensionLite , 1, ImportEnumLite.IMPORT_LITE_FOO);
-
-    message.setExtension(repeatedStringPieceExtensionLite, 1, "524");
-    message.setExtension(repeatedCordExtensionLite, 1, "525");
-  }
-
-  // -------------------------------------------------------------------
-
   /**
    * Assert (using {@code junit.framework.Assert}} that all extensions of
    * {@code message} are set to the values assigned by {@code setAllExtensions}.
@@ -2867,38 +2494,6 @@ public final class TestUtil {
     assertEqualsExactType("525", message.getExtension(repeatedCordExtensionLite, 1));
   }
 
-  public static void setPackedExtensions(TestPackedExtensionsLite.Builder message) {
-    message.addExtension(packedInt32ExtensionLite   , 601);
-    message.addExtension(packedInt64ExtensionLite   , 602L);
-    message.addExtension(packedUint32ExtensionLite  , 603);
-    message.addExtension(packedUint64ExtensionLite  , 604L);
-    message.addExtension(packedSint32ExtensionLite  , 605);
-    message.addExtension(packedSint64ExtensionLite  , 606L);
-    message.addExtension(packedFixed32ExtensionLite , 607);
-    message.addExtension(packedFixed64ExtensionLite , 608L);
-    message.addExtension(packedSfixed32ExtensionLite, 609);
-    message.addExtension(packedSfixed64ExtensionLite, 610L);
-    message.addExtension(packedFloatExtensionLite   , 611F);
-    message.addExtension(packedDoubleExtensionLite  , 612D);
-    message.addExtension(packedBoolExtensionLite    , true);
-    message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
-    // Add a second one of each field.
-    message.addExtension(packedInt32ExtensionLite   , 701);
-    message.addExtension(packedInt64ExtensionLite   , 702L);
-    message.addExtension(packedUint32ExtensionLite  , 703);
-    message.addExtension(packedUint64ExtensionLite  , 704L);
-    message.addExtension(packedSint32ExtensionLite  , 705);
-    message.addExtension(packedSint64ExtensionLite  , 706L);
-    message.addExtension(packedFixed32ExtensionLite , 707);
-    message.addExtension(packedFixed64ExtensionLite , 708L);
-    message.addExtension(packedSfixed32ExtensionLite, 709);
-    message.addExtension(packedSfixed64ExtensionLite, 710L);
-    message.addExtension(packedFloatExtensionLite   , 711F);
-    message.addExtension(packedDoubleExtensionLite  , 712D);
-    message.addExtension(packedBoolExtensionLite    , false);
-    message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
-  }
-
   public static void assertPackedExtensionsSet(TestPackedExtensionsLite message) {
     Assert.assertEquals(2, message.getExtensionCount(packedInt32ExtensionLite   ));
     Assert.assertEquals(2, message.getExtensionCount(packedInt64ExtensionLite   ));
@@ -4250,7 +3845,7 @@ public final class TestUtil {
 
     private int invalidations;
 
-    //@Override (Java 1.6 override semantics, but we must support 1.5)
+    @Override
     public void markDirty() {
       invalidations++;
     }

+ 559 - 0
java/core/src/test/java/com/google/protobuf/TestUtilLite.java

@@ -0,0 +1,559 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import static com.google.protobuf.UnittestLite.OptionalGroup_extension_lite;
+import static com.google.protobuf.UnittestLite.RepeatedGroup_extension_lite;
+import static com.google.protobuf.UnittestLite.defaultBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultCordExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofStringExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalCordExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalLazyMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalPublicImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.packedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.packedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.packedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedCordExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedLazyMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint64ExtensionLite;
+
+import com.google.protobuf.UnittestImportLite.ImportEnumLite;
+import com.google.protobuf.UnittestImportLite.ImportMessageLite;
+import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
+import com.google.protobuf.UnittestLite.ForeignEnumLite;
+import com.google.protobuf.UnittestLite.ForeignMessageLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+
+/**
+ * Contains methods for setting fields of {@code TestAllTypesLite}, {@code TestAllExtensionsLite},
+ * and {@code TestPackedExtensionsLite}. This is analogous to the functionality in TestUtil.java but
+ * does not depend on the presence of any non-lite protos.
+ *
+ * <p>This code is not to be used outside of {@code com.google.protobuf} and
+ * subpackages.
+ */
+public final class TestUtilLite {
+  private TestUtilLite() {}
+
+  /** Helper to convert a String to ByteString. */
+  static ByteString toBytes(String str) {
+    return ByteString.copyFrom(str.getBytes(Internal.UTF_8));
+  }
+
+  /**
+   * Get a {@code TestAllTypesLite.Builder} with all fields set as they would be by
+   * {@link #setAllFields(TestAllTypesLite.Builder)}.
+   */
+  public static TestAllTypesLite.Builder getAllLiteSetBuilder() {
+    TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder();
+    setAllFields(builder);
+    return builder;
+  }
+
+  /**
+   * Get a {@code TestAllExtensionsLite} with all fields set as they would be by
+   * {@link #setAllExtensions(TestAllExtensionsLite.Builder)}.
+   */
+  public static TestAllExtensionsLite getAllLiteExtensionsSet() {
+    TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+    setAllExtensions(builder);
+    return builder.build();
+  }
+
+  public static TestPackedExtensionsLite getLitePackedExtensionsSet() {
+    TestPackedExtensionsLite.Builder builder = TestPackedExtensionsLite.newBuilder();
+    setPackedExtensions(builder);
+    return builder.build();
+  }
+  
+  /**
+   * Set every field of {@code builder} to the values expected by
+   * {@code assertAllFieldsSet()}.
+   */
+  public static void setAllFields(TestAllTypesLite.Builder builder) {
+    builder.setOptionalInt32   (101);
+    builder.setOptionalInt64   (102);
+    builder.setOptionalUint32  (103);
+    builder.setOptionalUint64  (104);
+    builder.setOptionalSint32  (105);
+    builder.setOptionalSint64  (106);
+    builder.setOptionalFixed32 (107);
+    builder.setOptionalFixed64 (108);
+    builder.setOptionalSfixed32(109);
+    builder.setOptionalSfixed64(110);
+    builder.setOptionalFloat   (111);
+    builder.setOptionalDouble  (112);
+    builder.setOptionalBool    (true);
+    builder.setOptionalString  ("115");
+    builder.setOptionalBytes   (toBytes("116"));
+
+    builder.setOptionalGroup(
+        TestAllTypesLite.OptionalGroup.newBuilder().setA(117).build());
+    builder.setOptionalNestedMessage(
+        TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build());
+    builder.setOptionalForeignMessage(
+        ForeignMessageLite.newBuilder().setC(119).build());
+    builder.setOptionalImportMessage(
+        ImportMessageLite.newBuilder().setD(120).build());
+    builder.setOptionalPublicImportMessage(
+        PublicImportMessageLite.newBuilder().setE(126).build());
+    builder.setOptionalLazyMessage(
+        TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build());
+
+    builder.setOptionalNestedEnum (TestAllTypesLite.NestedEnum.BAZ);
+    builder.setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAZ);
+    builder.setOptionalImportEnum (ImportEnumLite.IMPORT_LITE_BAZ);
+
+    builder.setOptionalStringPiece("124");
+    builder.setOptionalCord("125");
+
+    // -----------------------------------------------------------------
+
+    builder.addRepeatedInt32   (201);
+    builder.addRepeatedInt64   (202);
+    builder.addRepeatedUint32  (203);
+    builder.addRepeatedUint64  (204);
+    builder.addRepeatedSint32  (205);
+    builder.addRepeatedSint64  (206);
+    builder.addRepeatedFixed32 (207);
+    builder.addRepeatedFixed64 (208);
+    builder.addRepeatedSfixed32(209);
+    builder.addRepeatedSfixed64(210);
+    builder.addRepeatedFloat   (211);
+    builder.addRepeatedDouble  (212);
+    builder.addRepeatedBool    (true);
+    builder.addRepeatedString  ("215");
+    builder.addRepeatedBytes   (toBytes("216"));
+
+    builder.addRepeatedGroup(
+        TestAllTypesLite.RepeatedGroup.newBuilder().setA(217).build());
+    builder.addRepeatedNestedMessage(
+        TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build());
+    builder.addRepeatedForeignMessage(
+        ForeignMessageLite.newBuilder().setC(219).build());
+    builder.addRepeatedImportMessage(
+        ImportMessageLite.newBuilder().setD(220).build());
+    builder.addRepeatedLazyMessage(
+        TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build());
+
+    builder.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAR);
+    builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+    builder.addRepeatedImportEnum (ImportEnumLite.IMPORT_LITE_BAR);
+
+    builder.addRepeatedStringPiece("224");
+    builder.addRepeatedCord("225");
+
+    // Add a second one of each field.
+    builder.addRepeatedInt32   (301);
+    builder.addRepeatedInt64   (302);
+    builder.addRepeatedUint32  (303);
+    builder.addRepeatedUint64  (304);
+    builder.addRepeatedSint32  (305);
+    builder.addRepeatedSint64  (306);
+    builder.addRepeatedFixed32 (307);
+    builder.addRepeatedFixed64 (308);
+    builder.addRepeatedSfixed32(309);
+    builder.addRepeatedSfixed64(310);
+    builder.addRepeatedFloat   (311);
+    builder.addRepeatedDouble  (312);
+    builder.addRepeatedBool    (false);
+    builder.addRepeatedString  ("315");
+    builder.addRepeatedBytes   (toBytes("316"));
+
+    builder.addRepeatedGroup(
+        TestAllTypesLite.RepeatedGroup.newBuilder().setA(317).build());
+    builder.addRepeatedNestedMessage(
+        TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build());
+    builder.addRepeatedForeignMessage(
+        ForeignMessageLite.newBuilder().setC(319).build());
+    builder.addRepeatedImportMessage(
+        ImportMessageLite.newBuilder().setD(320).build());
+    builder.addRepeatedLazyMessage(
+        TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build());
+
+    builder.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAZ);
+    builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAZ);
+    builder.addRepeatedImportEnum (ImportEnumLite.IMPORT_LITE_BAZ);
+
+    builder.addRepeatedStringPiece("324");
+    builder.addRepeatedCord("325");
+
+    // -----------------------------------------------------------------
+
+    builder.setDefaultInt32   (401);
+    builder.setDefaultInt64   (402);
+    builder.setDefaultUint32  (403);
+    builder.setDefaultUint64  (404);
+    builder.setDefaultSint32  (405);
+    builder.setDefaultSint64  (406);
+    builder.setDefaultFixed32 (407);
+    builder.setDefaultFixed64 (408);
+    builder.setDefaultSfixed32(409);
+    builder.setDefaultSfixed64(410);
+    builder.setDefaultFloat   (411);
+    builder.setDefaultDouble  (412);
+    builder.setDefaultBool    (false);
+    builder.setDefaultString  ("415");
+    builder.setDefaultBytes   (toBytes("416"));
+
+    builder.setDefaultNestedEnum (TestAllTypesLite.NestedEnum.FOO);
+    builder.setDefaultForeignEnum(ForeignEnumLite.FOREIGN_LITE_FOO);
+    builder.setDefaultImportEnum (ImportEnumLite.IMPORT_LITE_FOO);
+
+    builder.setDefaultStringPiece("424");
+    builder.setDefaultCord("425");
+
+    builder.setOneofUint32(601);
+    builder.setOneofNestedMessage(
+        TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build());
+    builder.setOneofString("603");
+    builder.setOneofBytes(toBytes("604"));
+  }
+
+  /**
+   * Get an unmodifiable {@link ExtensionRegistryLite} containing all the
+   * extensions of {@code TestAllExtensionsLite}.
+   */
+  public static ExtensionRegistryLite getExtensionRegistryLite() {
+    ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance();
+    registerAllExtensionsLite(registry);
+    return registry.getUnmodifiable();
+  }
+
+  /**
+   * Register all of {@code TestAllExtensionsLite}'s extensions with the
+   * given {@link ExtensionRegistryLite}.
+   */
+  public static void registerAllExtensionsLite(ExtensionRegistryLite registry) {
+    UnittestLite.registerAllExtensions(registry);
+  }
+
+  // ===================================================================
+  // Lite extensions
+
+  /**
+   * Set every field of {@code message} to the values expected by
+   * {@code assertAllExtensionsSet()}.
+   */
+  public static void setAllExtensions(TestAllExtensionsLite.Builder message) {
+    message.setExtension(optionalInt32ExtensionLite   , 101);
+    message.setExtension(optionalInt64ExtensionLite   , 102L);
+    message.setExtension(optionalUint32ExtensionLite  , 103);
+    message.setExtension(optionalUint64ExtensionLite  , 104L);
+    message.setExtension(optionalSint32ExtensionLite  , 105);
+    message.setExtension(optionalSint64ExtensionLite  , 106L);
+    message.setExtension(optionalFixed32ExtensionLite , 107);
+    message.setExtension(optionalFixed64ExtensionLite , 108L);
+    message.setExtension(optionalSfixed32ExtensionLite, 109);
+    message.setExtension(optionalSfixed64ExtensionLite, 110L);
+    message.setExtension(optionalFloatExtensionLite   , 111F);
+    message.setExtension(optionalDoubleExtensionLite  , 112D);
+    message.setExtension(optionalBoolExtensionLite    , true);
+    message.setExtension(optionalStringExtensionLite  , "115");
+    message.setExtension(optionalBytesExtensionLite   , toBytes("116"));
+
+    message.setExtension(optionalGroupExtensionLite,
+      OptionalGroup_extension_lite.newBuilder().setA(117).build());
+    message.setExtension(optionalNestedMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build());
+    message.setExtension(optionalForeignMessageExtensionLite,
+      ForeignMessageLite.newBuilder().setC(119).build());
+    message.setExtension(optionalImportMessageExtensionLite,
+      ImportMessageLite.newBuilder().setD(120).build());
+    message.setExtension(optionalPublicImportMessageExtensionLite,
+      PublicImportMessageLite.newBuilder().setE(126).build());
+    message.setExtension(optionalLazyMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build());
+
+    message.setExtension(optionalNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
+    message.setExtension(optionalForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+    message.setExtension(optionalImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ);
+
+    message.setExtension(optionalStringPieceExtensionLite, "124");
+    message.setExtension(optionalCordExtensionLite, "125");
+
+    // -----------------------------------------------------------------
+
+    message.addExtension(repeatedInt32ExtensionLite   , 201);
+    message.addExtension(repeatedInt64ExtensionLite   , 202L);
+    message.addExtension(repeatedUint32ExtensionLite  , 203);
+    message.addExtension(repeatedUint64ExtensionLite  , 204L);
+    message.addExtension(repeatedSint32ExtensionLite  , 205);
+    message.addExtension(repeatedSint64ExtensionLite  , 206L);
+    message.addExtension(repeatedFixed32ExtensionLite , 207);
+    message.addExtension(repeatedFixed64ExtensionLite , 208L);
+    message.addExtension(repeatedSfixed32ExtensionLite, 209);
+    message.addExtension(repeatedSfixed64ExtensionLite, 210L);
+    message.addExtension(repeatedFloatExtensionLite   , 211F);
+    message.addExtension(repeatedDoubleExtensionLite  , 212D);
+    message.addExtension(repeatedBoolExtensionLite    , true);
+    message.addExtension(repeatedStringExtensionLite  , "215");
+    message.addExtension(repeatedBytesExtensionLite   , toBytes("216"));
+
+    message.addExtension(repeatedGroupExtensionLite,
+      RepeatedGroup_extension_lite.newBuilder().setA(217).build());
+    message.addExtension(repeatedNestedMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build());
+    message.addExtension(repeatedForeignMessageExtensionLite,
+      ForeignMessageLite.newBuilder().setC(219).build());
+    message.addExtension(repeatedImportMessageExtensionLite,
+      ImportMessageLite.newBuilder().setD(220).build());
+    message.addExtension(repeatedLazyMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build());
+
+    message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAR);
+    message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
+    message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAR);
+
+    message.addExtension(repeatedStringPieceExtensionLite, "224");
+    message.addExtension(repeatedCordExtensionLite, "225");
+
+    // Add a second one of each field.
+    message.addExtension(repeatedInt32ExtensionLite   , 301);
+    message.addExtension(repeatedInt64ExtensionLite   , 302L);
+    message.addExtension(repeatedUint32ExtensionLite  , 303);
+    message.addExtension(repeatedUint64ExtensionLite  , 304L);
+    message.addExtension(repeatedSint32ExtensionLite  , 305);
+    message.addExtension(repeatedSint64ExtensionLite  , 306L);
+    message.addExtension(repeatedFixed32ExtensionLite , 307);
+    message.addExtension(repeatedFixed64ExtensionLite , 308L);
+    message.addExtension(repeatedSfixed32ExtensionLite, 309);
+    message.addExtension(repeatedSfixed64ExtensionLite, 310L);
+    message.addExtension(repeatedFloatExtensionLite   , 311F);
+    message.addExtension(repeatedDoubleExtensionLite  , 312D);
+    message.addExtension(repeatedBoolExtensionLite    , false);
+    message.addExtension(repeatedStringExtensionLite  , "315");
+    message.addExtension(repeatedBytesExtensionLite   , toBytes("316"));
+
+    message.addExtension(repeatedGroupExtensionLite,
+      RepeatedGroup_extension_lite.newBuilder().setA(317).build());
+    message.addExtension(repeatedNestedMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build());
+    message.addExtension(repeatedForeignMessageExtensionLite,
+      ForeignMessageLite.newBuilder().setC(319).build());
+    message.addExtension(repeatedImportMessageExtensionLite,
+      ImportMessageLite.newBuilder().setD(320).build());
+    message.addExtension(repeatedLazyMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build());
+
+    message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
+    message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+    message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ);
+
+    message.addExtension(repeatedStringPieceExtensionLite, "324");
+    message.addExtension(repeatedCordExtensionLite, "325");
+
+    // -----------------------------------------------------------------
+
+    message.setExtension(defaultInt32ExtensionLite   , 401);
+    message.setExtension(defaultInt64ExtensionLite   , 402L);
+    message.setExtension(defaultUint32ExtensionLite  , 403);
+    message.setExtension(defaultUint64ExtensionLite  , 404L);
+    message.setExtension(defaultSint32ExtensionLite  , 405);
+    message.setExtension(defaultSint64ExtensionLite  , 406L);
+    message.setExtension(defaultFixed32ExtensionLite , 407);
+    message.setExtension(defaultFixed64ExtensionLite , 408L);
+    message.setExtension(defaultSfixed32ExtensionLite, 409);
+    message.setExtension(defaultSfixed64ExtensionLite, 410L);
+    message.setExtension(defaultFloatExtensionLite   , 411F);
+    message.setExtension(defaultDoubleExtensionLite  , 412D);
+    message.setExtension(defaultBoolExtensionLite    , false);
+    message.setExtension(defaultStringExtensionLite  , "415");
+    message.setExtension(defaultBytesExtensionLite   , toBytes("416"));
+
+    message.setExtension(defaultNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.FOO);
+    message.setExtension(defaultForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_FOO);
+    message.setExtension(defaultImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_FOO);
+
+    message.setExtension(defaultStringPieceExtensionLite, "424");
+    message.setExtension(defaultCordExtensionLite, "425");
+
+    message.setExtension(oneofUint32ExtensionLite, 601);
+    message.setExtension(oneofNestedMessageExtensionLite,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build());
+    message.setExtension(oneofStringExtensionLite, "603");
+    message.setExtension(oneofBytesExtensionLite, toBytes("604"));
+  }
+
+  // -------------------------------------------------------------------
+
+  /**
+   * Modify the repeated extensions of {@code message} to contain the values
+   * expected by {@code assertRepeatedExtensionsModified()}.
+   */
+  public static void modifyRepeatedExtensions(
+      TestAllExtensionsLite.Builder message) {
+    message.setExtension(repeatedInt32ExtensionLite   , 1, 501);
+    message.setExtension(repeatedInt64ExtensionLite   , 1, 502L);
+    message.setExtension(repeatedUint32ExtensionLite  , 1, 503);
+    message.setExtension(repeatedUint64ExtensionLite  , 1, 504L);
+    message.setExtension(repeatedSint32ExtensionLite  , 1, 505);
+    message.setExtension(repeatedSint64ExtensionLite  , 1, 506L);
+    message.setExtension(repeatedFixed32ExtensionLite , 1, 507);
+    message.setExtension(repeatedFixed64ExtensionLite , 1, 508L);
+    message.setExtension(repeatedSfixed32ExtensionLite, 1, 509);
+    message.setExtension(repeatedSfixed64ExtensionLite, 1, 510L);
+    message.setExtension(repeatedFloatExtensionLite   , 1, 511F);
+    message.setExtension(repeatedDoubleExtensionLite  , 1, 512D);
+    message.setExtension(repeatedBoolExtensionLite    , 1, true);
+    message.setExtension(repeatedStringExtensionLite  , 1, "515");
+    message.setExtension(repeatedBytesExtensionLite   , 1, toBytes("516"));
+
+    message.setExtension(repeatedGroupExtensionLite, 1,
+      RepeatedGroup_extension_lite.newBuilder().setA(517).build());
+    message.setExtension(repeatedNestedMessageExtensionLite, 1,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(518).build());
+    message.setExtension(repeatedForeignMessageExtensionLite, 1,
+      ForeignMessageLite.newBuilder().setC(519).build());
+    message.setExtension(repeatedImportMessageExtensionLite, 1,
+      ImportMessageLite.newBuilder().setD(520).build());
+    message.setExtension(repeatedLazyMessageExtensionLite, 1,
+      TestAllTypesLite.NestedMessage.newBuilder().setBb(527).build());
+
+    message.setExtension(repeatedNestedEnumExtensionLite , 1, TestAllTypesLite.NestedEnum.FOO);
+    message.setExtension(repeatedForeignEnumExtensionLite, 1, ForeignEnumLite.FOREIGN_LITE_FOO);
+    message.setExtension(repeatedImportEnumExtensionLite , 1, ImportEnumLite.IMPORT_LITE_FOO);
+
+    message.setExtension(repeatedStringPieceExtensionLite, 1, "524");
+    message.setExtension(repeatedCordExtensionLite, 1, "525");
+  }
+
+  public static void setPackedExtensions(TestPackedExtensionsLite.Builder message) {
+    message.addExtension(packedInt32ExtensionLite   , 601);
+    message.addExtension(packedInt64ExtensionLite   , 602L);
+    message.addExtension(packedUint32ExtensionLite  , 603);
+    message.addExtension(packedUint64ExtensionLite  , 604L);
+    message.addExtension(packedSint32ExtensionLite  , 605);
+    message.addExtension(packedSint64ExtensionLite  , 606L);
+    message.addExtension(packedFixed32ExtensionLite , 607);
+    message.addExtension(packedFixed64ExtensionLite , 608L);
+    message.addExtension(packedSfixed32ExtensionLite, 609);
+    message.addExtension(packedSfixed64ExtensionLite, 610L);
+    message.addExtension(packedFloatExtensionLite   , 611F);
+    message.addExtension(packedDoubleExtensionLite  , 612D);
+    message.addExtension(packedBoolExtensionLite    , true);
+    message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
+    // Add a second one of each field.
+    message.addExtension(packedInt32ExtensionLite   , 701);
+    message.addExtension(packedInt64ExtensionLite   , 702L);
+    message.addExtension(packedUint32ExtensionLite  , 703);
+    message.addExtension(packedUint64ExtensionLite  , 704L);
+    message.addExtension(packedSint32ExtensionLite  , 705);
+    message.addExtension(packedSint64ExtensionLite  , 706L);
+    message.addExtension(packedFixed32ExtensionLite , 707);
+    message.addExtension(packedFixed64ExtensionLite , 708L);
+    message.addExtension(packedSfixed32ExtensionLite, 709);
+    message.addExtension(packedSfixed64ExtensionLite, 710L);
+    message.addExtension(packedFloatExtensionLite   , 711F);
+    message.addExtension(packedDoubleExtensionLite  , 712D);
+    message.addExtension(packedBoolExtensionLite    , false);
+    message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+  }
+}

+ 4 - 1
java/core/src/test/java/com/google/protobuf/TextFormatTest.java

@@ -775,11 +775,14 @@ public class TextFormatTest extends TestCase {
   public void testParseBoolean() throws Exception {
     String goodText =
         "repeated_bool: t  repeated_bool : 0\n" +
-        "repeated_bool :f repeated_bool:1";
+        "repeated_bool :f repeated_bool:1\n" +
+        "repeated_bool: False repeated_bool: True";
     String goodTextCanonical =
         "repeated_bool: true\n" +
         "repeated_bool: false\n" +
         "repeated_bool: false\n" +
+        "repeated_bool: true\n" +
+        "repeated_bool: false\n" +
         "repeated_bool: true\n";
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
     TextFormat.merge(goodText, builder);

+ 1 - 0
java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java

@@ -50,6 +50,7 @@ import java.util.Map;
  * @author kenton@google.com (Kenton Varda)
  */
 public class UnknownFieldSetTest extends TestCase {
+  @Override
   public void setUp() throws Exception {
     descriptor = TestAllTypes.getDescriptor();
     allFields = TestUtil.getAllSet();

+ 5 - 5
java/core/src/test/java/com/google/protobuf/WireFormatTest.java

@@ -132,7 +132,7 @@ public class WireFormatTest extends TestCase {
     // so if we serialize a TestAllExtensions then parse it as TestAllTypes
     // it should work.
 
-    TestAllExtensionsLite message = TestUtil.getAllLiteExtensionsSet();
+    TestAllExtensionsLite message = TestUtilLite.getAllLiteExtensionsSet();
     ByteString rawBytes = message.toByteString();
     assertEquals(rawBytes.size(), message.getSerializedSize());
 
@@ -144,7 +144,7 @@ public class WireFormatTest extends TestCase {
   public void testSerializePackedExtensionsLite() throws Exception {
     // TestPackedTypes and TestPackedExtensions should have compatible wire
     // formats; check that they serialize to the same string.
-    TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet();
+    TestPackedExtensionsLite message = TestUtilLite.getLitePackedExtensionsSet();
     ByteString rawBytes = message.toByteString();
 
     TestPackedTypes message2 = TestUtil.getPackedSet();
@@ -190,7 +190,7 @@ public class WireFormatTest extends TestCase {
     TestAllTypes message = TestUtil.getAllSet();
     ByteString rawBytes = message.toByteString();
 
-    ExtensionRegistryLite registry_lite = TestUtil.getExtensionRegistryLite();
+    ExtensionRegistryLite registry_lite = TestUtilLite.getExtensionRegistryLite();
 
     TestAllExtensionsLite message2 =
       TestAllExtensionsLite.parseFrom(rawBytes, registry_lite);
@@ -208,10 +208,10 @@ public class WireFormatTest extends TestCase {
 
   public void testParsePackedExtensionsLite() throws Exception {
     // Ensure that packed extensions can be properly parsed.
-    TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet();
+    TestPackedExtensionsLite message = TestUtilLite.getLitePackedExtensionsSet();
     ByteString rawBytes = message.toByteString();
 
-    ExtensionRegistryLite registry = TestUtil.getExtensionRegistryLite();
+    ExtensionRegistryLite registry = TestUtilLite.getExtensionRegistryLite();
 
     TestPackedExtensionsLite message2 =
         TestPackedExtensionsLite.parseFrom(rawBytes, registry);

+ 0 - 3
java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto

@@ -34,9 +34,6 @@ syntax = "proto2";
 
 package protobuf_unittest.lite_equals_and_hash;
 
-// This proto definition is used to test that java_generate_equals_and_hash
-// works correctly with the LITE_RUNTIME.
-option java_generate_equals_and_hash = true;
 option optimize_for = LITE_RUNTIME;
 
 message TestOneofEquals {

+ 20 - 0
java/lite/generate-sources-build.xml

@@ -0,0 +1,20 @@
+<project name="generate-sources">
+    <echo message="Running protoc ..."/>
+    <mkdir dir="${generated.sources.lite.dir}"/>
+    <exec executable="${protoc}">
+        <arg value="--java_out=lite:${generated.sources.lite.dir}"/>
+        <arg value="--proto_path=${protobuf.source.dir}"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/any.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/api.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/descriptor.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/duration.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/empty.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/field_mask.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/source_context.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/struct.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/timestamp.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/type.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/wrappers.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/compiler/plugin.proto"/>
+    </exec>
+</project>

+ 43 - 0
java/lite/generate-test-sources-build.xml

@@ -0,0 +1,43 @@
+<project name="generate-test-sources">
+    <mkdir dir="${generated.testsources.lite.dir}"/>
+    <exec executable="${protoc}">
+        <arg value="--java_out=lite:${generated.testsources.lite.dir}"/>
+        <arg value="--proto_path=${protobuf.source.dir}"/>
+        <arg value="--proto_path=${test.proto.dir}"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_mset.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_mset_wire_format.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_optimize_for.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_custom_options.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_lite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_lite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public_lite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_lite_imports_nonlite.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_enormous_descriptor.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_no_generic_services.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_well_known_types.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/lazy_fields_lite.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/lite_equals_and_hash.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/multiple_files_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/nested_builders_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/nested_extension.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/nested_extension_lite.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/non_nested_extension.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/non_nested_extension_lite.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test2.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test3.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/test_bad_identifiers.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/test_check_utf8.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/test_check_utf8_size.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/test_custom_options.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/any_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/field_presence_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/map_for_proto2_lite_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/map_for_proto2_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/map_test.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/map_initialization_order_test.proto"/>
+    </exec>
+</project>

+ 4 - 4
java/lite/pom.xml

@@ -50,7 +50,7 @@
             <phase>generate-sources</phase>
             <configuration>
               <target>
-                <ant antfile="${core.root}/generate-sources-build.xml"/>
+                <ant antfile="generate-sources-build.xml"/>
               </target>
             </configuration>
             <goals>
@@ -64,7 +64,7 @@
             <phase>generate-test-sources</phase>
             <configuration>
               <target>
-                <ant antfile="${core.root}/generate-test-sources-build.xml"/>
+                <ant antfile="generate-test-sources-build.xml"/>
               </target>
             </configuration>
             <goals>
@@ -78,8 +78,8 @@
       <plugin>
         <artifactId>maven-compiler-plugin</artifactId>
         <configuration>
-          <generatedSourcesDirectory>${generated.sources.dir}</generatedSourcesDirectory>
-          <generatedTestSourcesDirectory>${generated.testsources.dir}</generatedTestSourcesDirectory>
+          <generatedSourcesDirectory>${generated.sources.lite.dir}</generatedSourcesDirectory>
+          <generatedTestSourcesDirectory>${generated.testsources.lite.dir}</generatedTestSourcesDirectory>
           <includes>
             <include>**/AbstractMessageLite.java</include>
             <include>**/AbstractParser.java</include>

+ 2 - 0
java/pom.xml

@@ -33,6 +33,8 @@
     <test.proto.dir>src/test/proto</test.proto.dir>
     <generated.sources.dir>${project.build.directory}/generated-sources</generated.sources.dir>
     <generated.testsources.dir>${project.build.directory}/generated-test-sources</generated.testsources.dir>
+    <generated.sources.lite.dir>${project.build.directory}/generated-sources-lite</generated.sources.lite.dir>
+    <generated.testsources.lite.dir>${project.build.directory}/generated-test-sources-lite</generated.testsources.lite.dir>
   </properties>
 
   <licenses>

+ 553 - 0
java/src/main/java/com/google/protobuf/AbstractMessage.java

@@ -0,0 +1,553 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+import com.google.protobuf.Internal.EnumLite;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A partial implementation of the {@link Message} interface which implements
+ * as many methods of that interface as possible in terms of other methods.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class AbstractMessage
+    // TODO(dweis): Update GeneratedMessage to parameterize with MessageType and BuilderType.
+    extends AbstractMessageLite
+    implements Message {
+  
+  @Override
+  public boolean isInitialized() {
+    return MessageReflection.isInitialized(this);
+  }
+
+
+  @Override
+  public List<String> findInitializationErrors() {
+    return MessageReflection.findMissingFields(this);
+  }
+
+  @Override
+  public String getInitializationErrorString() {
+    return MessageReflection.delimitWithCommas(findInitializationErrors());
+  }
+
+  /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+  @Override
+  public boolean hasOneof(OneofDescriptor oneof) {
+    throw new UnsupportedOperationException("hasOneof() is not implemented.");
+  }
+
+  /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+  @Override
+  public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
+    throw new UnsupportedOperationException(
+        "getOneofFieldDescriptor() is not implemented.");
+  }
+
+  @Override
+  public final String toString() {
+    return TextFormat.printToString(this);
+  }
+
+  @Override
+  public void writeTo(final CodedOutputStream output) throws IOException {
+    MessageReflection.writeMessageTo(this, getAllFields(), output, false);
+  }
+
+  protected int memoizedSize = -1;
+
+  @Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) {
+      return size;
+    }
+
+    memoizedSize = MessageReflection.getSerializedSize(this, getAllFields());
+    return memoizedSize;
+  }
+
+  @Override
+  public boolean equals(final Object other) {
+    if (other == this) {
+      return true;
+    }
+    if (!(other instanceof Message)) {
+      return false;
+    }
+    final Message otherMessage = (Message) other;
+    if (getDescriptorForType() != otherMessage.getDescriptorForType()) {
+      return false;
+    }
+    return compareFields(getAllFields(), otherMessage.getAllFields()) &&
+        getUnknownFields().equals(otherMessage.getUnknownFields());
+  }
+
+  @Override
+  public int hashCode() {
+    int hash = memoizedHashCode;
+    if (hash == 0) {
+      hash = 41;
+      hash = (19 * hash) + getDescriptorForType().hashCode();
+      hash = hashFields(hash, getAllFields());
+      hash = (29 * hash) + getUnknownFields().hashCode();
+      memoizedHashCode = hash;
+    }
+    return hash;
+  }
+  
+  private static ByteString toByteString(Object value) {
+    if (value instanceof byte[]) {
+      return ByteString.copyFrom((byte[]) value);
+    } else {
+      return (ByteString) value;
+    }
+  }
+ 
+  /**
+   * Compares two bytes fields. The parameters must be either a byte array or a
+   * ByteString object. They can be of different type though.
+   */
+  private static boolean compareBytes(Object a, Object b) {
+    if (a instanceof byte[] && b instanceof byte[]) {
+      return Arrays.equals((byte[])a, (byte[])b);
+    }
+    return toByteString(a).equals(toByteString(b));
+  }
+  
+  /**
+   * Converts a list of MapEntry messages into a Map used for equals() and
+   * hashCode().
+   */
+  @SuppressWarnings({"rawtypes", "unchecked"})
+  private static Map convertMapEntryListToMap(List list) {
+    if (list.isEmpty()) {
+      return Collections.emptyMap();
+    }
+    Map result = new HashMap();
+    Iterator iterator = list.iterator();
+    Message entry = (Message) iterator.next();
+    Descriptors.Descriptor descriptor = entry.getDescriptorForType();
+    Descriptors.FieldDescriptor key = descriptor.findFieldByName("key");
+    Descriptors.FieldDescriptor value = descriptor.findFieldByName("value");
+    Object fieldValue = entry.getField(value);
+    if (fieldValue instanceof EnumValueDescriptor) {
+      fieldValue = ((EnumValueDescriptor) fieldValue).getNumber();
+    }
+    result.put(entry.getField(key), fieldValue);
+    while (iterator.hasNext()) {
+      entry = (Message) iterator.next();
+      fieldValue = entry.getField(value);
+      if (fieldValue instanceof EnumValueDescriptor) {
+        fieldValue = ((EnumValueDescriptor) fieldValue).getNumber();
+      }
+      result.put(entry.getField(key), fieldValue);
+    }
+    return result;
+  }
+  
+  /**
+   * Compares two map fields. The parameters must be a list of MapEntry
+   * messages.
+   */
+  @SuppressWarnings({"rawtypes", "unchecked"})
+  private static boolean compareMapField(Object a, Object b) {
+    Map ma = convertMapEntryListToMap((List) a);
+    Map mb = convertMapEntryListToMap((List) b);
+    return MapFieldLite.equals(ma, mb);
+  }
+  
+  /**
+   * Compares two set of fields.
+   * This method is used to implement {@link AbstractMessage#equals(Object)}
+   * and {@link AbstractMutableMessage#equals(Object)}. It takes special care
+   * of bytes fields because immutable messages and mutable messages use
+   * different Java type to reprensent a bytes field and this method should be
+   * able to compare immutable messages, mutable messages and also an immutable
+   * message to a mutable message.
+   */
+  static boolean compareFields(Map<FieldDescriptor, Object> a,
+      Map<FieldDescriptor, Object> b) {
+    if (a.size() != b.size()) {
+      return false;
+    }
+    for (FieldDescriptor descriptor : a.keySet()) {
+      if (!b.containsKey(descriptor)) {
+        return false;
+      }
+      Object value1 = a.get(descriptor);
+      Object value2 = b.get(descriptor);
+      if (descriptor.getType() == FieldDescriptor.Type.BYTES) {
+        if (descriptor.isRepeated()) {
+          List list1 = (List) value1;
+          List list2 = (List) value2;
+          if (list1.size() != list2.size()) {
+            return false;
+          }
+          for (int i = 0; i < list1.size(); i++) {
+            if (!compareBytes(list1.get(i), list2.get(i))) {
+              return false;
+            }
+          }
+        } else {
+          // Compares a singular bytes field.
+          if (!compareBytes(value1, value2)) {
+            return false;
+          }
+        }
+      } else if (descriptor.isMapField()) {
+        if (!compareMapField(value1, value2)) {
+          return false;
+        }
+      } else {
+        // Compare non-bytes fields.
+        if (!value1.equals(value2)) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+  
+  /**
+   * Calculates the hash code of a map field. {@code value} must be a list of
+   * MapEntry messages.
+   */
+  @SuppressWarnings("unchecked")
+  private static int hashMapField(Object value) {
+    return MapFieldLite.calculateHashCodeForMap(convertMapEntryListToMap((List) value));
+  }
+
+  /** Get a hash code for given fields and values, using the given seed. */
+  @SuppressWarnings("unchecked")
+  protected static int hashFields(int hash, Map<FieldDescriptor, Object> map) {
+    for (Map.Entry<FieldDescriptor, Object> entry : map.entrySet()) {
+      FieldDescriptor field = entry.getKey();
+      Object value = entry.getValue();
+      hash = (37 * hash) + field.getNumber();
+      if (field.isMapField()) {
+        hash = (53 * hash) + hashMapField(value);
+      } else if (field.getType() != FieldDescriptor.Type.ENUM){
+        hash = (53 * hash) + value.hashCode();
+      } else if (field.isRepeated()) {
+        List<? extends EnumLite> list = (List<? extends EnumLite>) value;
+        hash = (53 * hash) + Internal.hashEnumList(list);
+      } else {
+        hash = (53 * hash) + Internal.hashEnum((EnumLite) value);
+      }
+    }
+    return hash;
+  }
+
+  /**
+   * Package private helper method for AbstractParser to create
+   * UninitializedMessageException with missing field information.
+   */
+  @Override
+  UninitializedMessageException newUninitializedMessageException() {
+    return Builder.newUninitializedMessageException(this);
+  }
+
+  // =================================================================
+
+  /**
+   * A partial implementation of the {@link Message.Builder} interface which
+   * implements as many methods of that interface as possible in terms of
+   * other methods.
+   */
+  @SuppressWarnings("unchecked")
+  public static abstract class Builder<BuilderType extends Builder<BuilderType>>
+      extends AbstractMessageLite.Builder
+      implements Message.Builder {
+    // The compiler produces an error if this is not declared explicitly.
+    @Override
+    public abstract BuilderType clone();
+
+    /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+    @Override
+    public boolean hasOneof(OneofDescriptor oneof) {
+      throw new UnsupportedOperationException("hasOneof() is not implemented.");
+    }
+
+    /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+    @Override
+    public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
+      throw new UnsupportedOperationException(
+          "getOneofFieldDescriptor() is not implemented.");
+    }
+
+    /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+    @Override
+    public BuilderType clearOneof(OneofDescriptor oneof) {
+      throw new UnsupportedOperationException("clearOneof() is not implemented.");
+    }
+
+    @Override
+    public BuilderType clear() {
+      for (final Map.Entry<FieldDescriptor, Object> entry :
+           getAllFields().entrySet()) {
+        clearField(entry.getKey());
+      }
+      return (BuilderType) this;
+    }
+
+    @Override
+    public List<String> findInitializationErrors() {
+      return MessageReflection.findMissingFields(this);
+    }
+
+    @Override
+    public String getInitializationErrorString() {
+      return MessageReflection.delimitWithCommas(findInitializationErrors());
+    }
+    
+    @Override
+    protected BuilderType internalMergeFrom(AbstractMessageLite other) {
+      return mergeFrom((Message) other);
+    }
+
+    @Override
+    public BuilderType mergeFrom(final Message other) {
+      if (other.getDescriptorForType() != getDescriptorForType()) {
+        throw new IllegalArgumentException(
+          "mergeFrom(Message) can only merge messages of the same type.");
+      }
+
+      // Note:  We don't attempt to verify that other's fields have valid
+      //   types.  Doing so would be a losing battle.  We'd have to verify
+      //   all sub-messages as well, and we'd have to make copies of all of
+      //   them to insure that they don't change after verification (since
+      //   the Message interface itself cannot enforce immutability of
+      //   implementations).
+      // TODO(kenton):  Provide a function somewhere called makeDeepCopy()
+      //   which allows people to make secure deep copies of messages.
+
+      for (final Map.Entry<FieldDescriptor, Object> entry :
+           other.getAllFields().entrySet()) {
+        final FieldDescriptor field = entry.getKey();
+        if (field.isRepeated()) {
+          for (final Object element : (List)entry.getValue()) {
+            addRepeatedField(field, element);
+          }
+        } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+          final Message existingValue = (Message)getField(field);
+          if (existingValue == existingValue.getDefaultInstanceForType()) {
+            setField(field, entry.getValue());
+          } else {
+            setField(field,
+              existingValue.newBuilderForType()
+                .mergeFrom(existingValue)
+                .mergeFrom((Message)entry.getValue())
+                .build());
+          }
+        } else {
+          setField(field, entry.getValue());
+        }
+      }
+
+      mergeUnknownFields(other.getUnknownFields());
+
+      return (BuilderType) this;
+    }
+
+    @Override
+    public BuilderType mergeFrom(final CodedInputStream input)
+                                 throws IOException {
+      return mergeFrom(input, ExtensionRegistry.getEmptyRegistry());
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final CodedInputStream input,
+        final ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      final UnknownFieldSet.Builder unknownFields =
+        UnknownFieldSet.newBuilder(getUnknownFields());
+      while (true) {
+        final int tag = input.readTag();
+        if (tag == 0) {
+          break;
+        }
+
+        MessageReflection.BuilderAdapter builderAdapter =
+            new MessageReflection.BuilderAdapter(this);
+        if (!MessageReflection.mergeFieldFrom(input, unknownFields,
+                                              extensionRegistry,
+                                              getDescriptorForType(),
+                                              builderAdapter,
+                                              tag)) {
+          // end group tag
+          break;
+        }
+      }
+      setUnknownFields(unknownFields.build());
+      return (BuilderType) this;
+    }
+
+    @Override
+    public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
+      setUnknownFields(
+        UnknownFieldSet.newBuilder(getUnknownFields())
+                       .mergeFrom(unknownFields)
+                       .build());
+      return (BuilderType) this;
+    }
+
+    @Override
+    public Message.Builder getFieldBuilder(final FieldDescriptor field) {
+      throw new UnsupportedOperationException(
+          "getFieldBuilder() called on an unsupported message type.");
+    }
+
+    @Override
+    public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) {
+      throw new UnsupportedOperationException(
+          "getRepeatedFieldBuilder() called on an unsupported message type.");
+    }
+
+    @Override
+    public String toString() {
+      return TextFormat.printToString(this);
+    }
+
+    /**
+     * Construct an UninitializedMessageException reporting missing fields in
+     * the given message.
+     */
+    protected static UninitializedMessageException
+        newUninitializedMessageException(Message message) {
+      return new UninitializedMessageException(
+          MessageReflection.findMissingFields(message));
+    }
+
+    // ===============================================================
+    // The following definitions seem to be required in order to make javac
+    // not produce weird errors like:
+    //
+    // java/com/google/protobuf/DynamicMessage.java:203: types
+    //   com.google.protobuf.AbstractMessage.Builder<
+    //     com.google.protobuf.DynamicMessage.Builder> and
+    //   com.google.protobuf.AbstractMessage.Builder<
+    //     com.google.protobuf.DynamicMessage.Builder> are incompatible; both
+    //   define mergeFrom(com.google.protobuf.ByteString), but with unrelated
+    //   return types.
+    //
+    // Strangely, these lines are only needed if javac is invoked separately
+    // on AbstractMessage.java and AbstractMessageLite.java.  If javac is
+    // invoked on both simultaneously, it works.  (Or maybe the important
+    // point is whether or not DynamicMessage.java is compiled together with
+    // AbstractMessageLite.java -- not sure.)  I suspect this is a compiler
+    // bug.
+
+    @Override
+    public BuilderType mergeFrom(final ByteString data)
+        throws InvalidProtocolBufferException {
+      return (BuilderType) super.mergeFrom(data);
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final ByteString data,
+        final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      return (BuilderType) super.mergeFrom(data, extensionRegistry);
+    }
+
+    @Override
+    public BuilderType mergeFrom(final byte[] data)
+        throws InvalidProtocolBufferException {
+      return (BuilderType) super.mergeFrom(data);
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final byte[] data, final int off, final int len)
+        throws InvalidProtocolBufferException {
+      return (BuilderType) super.mergeFrom(data, off, len);
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final byte[] data,
+        final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      return (BuilderType) super.mergeFrom(data, extensionRegistry);
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final byte[] data, final int off, final int len,
+        final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      return (BuilderType) super.mergeFrom(data, off, len, extensionRegistry);
+    }
+
+    @Override
+    public BuilderType mergeFrom(final InputStream input)
+        throws IOException {
+      return (BuilderType) super.mergeFrom(input);
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final InputStream input,
+        final ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      return (BuilderType) super.mergeFrom(input, extensionRegistry);
+    }
+
+    @Override
+    public boolean mergeDelimitedFrom(final InputStream input)
+        throws IOException {
+      return super.mergeDelimitedFrom(input);
+    }
+
+    @Override
+    public boolean mergeDelimitedFrom(
+        final InputStream input,
+        final ExtensionRegistryLite extensionRegistry)
+        throws IOException {
+      return super.mergeDelimitedFrom(input, extensionRegistry);
+    }
+  }
+}

+ 386 - 0
java/src/main/java/com/google/protobuf/AbstractMessageLite.java

@@ -0,0 +1,386 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+
+/**
+ * A partial implementation of the {@link MessageLite} interface which
+ * implements as many methods of that interface as possible in terms of other
+ * methods.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class AbstractMessageLite<
+    MessageType extends AbstractMessageLite<MessageType, BuilderType>,
+    BuilderType extends AbstractMessageLite.Builder<MessageType, BuilderType>> 
+        implements MessageLite {
+  protected int memoizedHashCode = 0;
+  
+  @Override
+  public ByteString toByteString() {
+    try {
+      final ByteString.CodedBuilder out =
+        ByteString.newCodedBuilder(getSerializedSize());
+      writeTo(out.getCodedOutput());
+      return out.build();
+    } catch (IOException e) {
+      throw new RuntimeException(
+        "Serializing to a ByteString threw an IOException (should " +
+        "never happen).", e);
+    }
+  }
+
+  @Override
+  public byte[] toByteArray() {
+    try {
+      final byte[] result = new byte[getSerializedSize()];
+      final CodedOutputStream output = CodedOutputStream.newInstance(result);
+      writeTo(output);
+      output.checkNoSpaceLeft();
+      return result;
+    } catch (IOException e) {
+      throw new RuntimeException(
+        "Serializing to a byte array threw an IOException " +
+        "(should never happen).", e);
+    }
+  }
+
+  @Override
+  public void writeTo(final OutputStream output) throws IOException {
+    final int bufferSize =
+        CodedOutputStream.computePreferredBufferSize(getSerializedSize());
+    final CodedOutputStream codedOutput =
+        CodedOutputStream.newInstance(output, bufferSize);
+    writeTo(codedOutput);
+    codedOutput.flush();
+  }
+
+  @Override
+  public void writeDelimitedTo(final OutputStream output) throws IOException {
+    final int serialized = getSerializedSize();
+    final int bufferSize = CodedOutputStream.computePreferredBufferSize(
+        CodedOutputStream.computeRawVarint32Size(serialized) + serialized);
+    final CodedOutputStream codedOutput =
+        CodedOutputStream.newInstance(output, bufferSize);
+    codedOutput.writeRawVarint32(serialized);
+    writeTo(codedOutput);
+    codedOutput.flush();
+  }
+
+
+  /**
+   * Package private helper method for AbstractParser to create
+   * UninitializedMessageException.
+   */
+  UninitializedMessageException newUninitializedMessageException() {
+    return new UninitializedMessageException(this);
+  }
+
+  protected static void checkByteStringIsUtf8(ByteString byteString)
+      throws IllegalArgumentException {
+    if (!byteString.isValidUtf8()) {
+      throw new IllegalArgumentException("Byte string is not UTF-8.");
+    }
+  }
+
+  protected static <T> void addAll(final Iterable<T> values,
+      final Collection<? super T> list) {
+    Builder.addAll(values, list);
+  }
+  
+  /**
+   * A partial implementation of the {@link Message.Builder} interface which
+   * implements as many methods of that interface as possible in terms of
+   * other methods.
+   */
+  @SuppressWarnings("unchecked")
+  public abstract static class Builder<
+      MessageType extends AbstractMessageLite<MessageType, BuilderType>,
+      BuilderType extends Builder<MessageType, BuilderType>>
+      implements MessageLite.Builder {
+    // The compiler produces an error if this is not declared explicitly.
+    @Override
+    public abstract BuilderType clone();
+
+    @Override
+    public BuilderType mergeFrom(final CodedInputStream input) throws IOException {
+      return mergeFrom(input, ExtensionRegistryLite.getEmptyRegistry());
+    }
+
+    // Re-defined here for return type covariance.
+    @Override
+    public abstract BuilderType mergeFrom(
+        final CodedInputStream input, final ExtensionRegistryLite extensionRegistry)
+        throws IOException;
+
+    @Override
+    public BuilderType mergeFrom(final ByteString data) throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input = data.newCodedInput();
+        mergeFrom(input);
+        input.checkLastTagWas(0);
+        return (BuilderType) this;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (IOException e) {
+        throw new RuntimeException(
+          "Reading from a ByteString threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final ByteString data, final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input = data.newCodedInput();
+        mergeFrom(input, extensionRegistry);
+        input.checkLastTagWas(0);
+        return (BuilderType) this;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (IOException e) {
+        throw new RuntimeException(
+          "Reading from a ByteString threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    @Override
+    public BuilderType mergeFrom(final byte[] data) throws InvalidProtocolBufferException {
+      return mergeFrom(data, 0, data.length);
+    }
+
+    @Override
+    public BuilderType mergeFrom(final byte[] data, final int off, final int len)
+        throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input =
+            CodedInputStream.newInstance(data, off, len);
+        mergeFrom(input);
+        input.checkLastTagWas(0);
+        return (BuilderType) this;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (IOException e) {
+        throw new RuntimeException(
+          "Reading from a byte array threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    @Override
+    public BuilderType mergeFrom(final byte[] data, final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      return mergeFrom(data, 0, data.length, extensionRegistry);
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final byte[] data,
+        final int off,
+        final int len,
+        final ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      try {
+        final CodedInputStream input =
+            CodedInputStream.newInstance(data, off, len);
+        mergeFrom(input, extensionRegistry);
+        input.checkLastTagWas(0);
+        return (BuilderType) this;
+      } catch (InvalidProtocolBufferException e) {
+        throw e;
+      } catch (IOException e) {
+        throw new RuntimeException(
+          "Reading from a byte array threw an IOException (should " +
+          "never happen).", e);
+      }
+    }
+
+    @Override
+    public BuilderType mergeFrom(final InputStream input) throws IOException {
+      final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+      mergeFrom(codedInput);
+      codedInput.checkLastTagWas(0);
+      return (BuilderType) this;
+    }
+
+    @Override
+    public BuilderType mergeFrom(
+        final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
+      final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+      mergeFrom(codedInput, extensionRegistry);
+      codedInput.checkLastTagWas(0);
+      return (BuilderType) this;
+    }
+
+    /**
+     * An InputStream implementations which reads from some other InputStream
+     * but is limited to a particular number of bytes.  Used by
+     * mergeDelimitedFrom().  This is intentionally package-private so that
+     * UnknownFieldSet can share it.
+     */
+    static final class LimitedInputStream extends FilterInputStream {
+      private int limit;
+
+      LimitedInputStream(InputStream in, int limit) {
+        super(in);
+        this.limit = limit;
+      }
+
+      @Override
+      public int available() throws IOException {
+        return Math.min(super.available(), limit);
+      }
+
+      @Override
+      public int read() throws IOException {
+        if (limit <= 0) {
+          return -1;
+        }
+        final int result = super.read();
+        if (result >= 0) {
+          --limit;
+        }
+        return result;
+      }
+
+      @Override
+      public int read(final byte[] b, final int off, int len)
+                      throws IOException {
+        if (limit <= 0) {
+          return -1;
+        }
+        len = Math.min(len, limit);
+        final int result = super.read(b, off, len);
+        if (result >= 0) {
+          limit -= result;
+        }
+        return result;
+      }
+
+      @Override
+      public long skip(final long n) throws IOException {
+        final long result = super.skip(Math.min(n, limit));
+        if (result >= 0) {
+          limit -= result;
+        }
+        return result;
+      }
+    }
+
+    @Override
+    public boolean mergeDelimitedFrom(
+        final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
+      final int firstByte = input.read();
+      if (firstByte == -1) {
+        return false;
+      }
+      final int size = CodedInputStream.readRawVarint32(firstByte, input);
+      final InputStream limitedInput = new LimitedInputStream(input, size);
+      mergeFrom(limitedInput, extensionRegistry);
+      return true;
+    }
+
+    @Override
+    public boolean mergeDelimitedFrom(final InputStream input) throws IOException {
+      return mergeDelimitedFrom(input,
+          ExtensionRegistryLite.getEmptyRegistry());
+    }
+    
+    @Override
+    @SuppressWarnings("unchecked") // isInstance takes care of this
+    public BuilderType mergeFrom(final MessageLite other) {
+      if (!getDefaultInstanceForType().getClass().isInstance(other)) {
+        throw new IllegalArgumentException(
+            "mergeFrom(MessageLite) can only merge messages of the same type.");
+      }
+        
+      return internalMergeFrom((MessageType) other);
+    }
+    
+    protected abstract BuilderType internalMergeFrom(MessageType message);
+
+    /**
+     * Construct an UninitializedMessageException reporting missing fields in
+     * the given message.
+     */
+    protected static UninitializedMessageException
+        newUninitializedMessageException(MessageLite message) {
+      return new UninitializedMessageException(message);
+    }
+
+    /**
+     * Adds the {@code values} to the {@code list}.  This is a helper method
+     * used by generated code.  Users should ignore it.
+     *
+     * @throws NullPointerException if {@code values} or any of the elements of
+     * {@code values} is null. When that happens, some elements of
+     * {@code values} may have already been added to the result {@code list}.
+     */
+    protected static <T> void addAll(final Iterable<T> values,
+                                     final Collection<? super T> list) {
+      if (values == null) {
+        throw new NullPointerException();
+      }
+      if (values instanceof LazyStringList) {
+        // For StringOrByteStringLists, check the underlying elements to avoid
+        // forcing conversions of ByteStrings to Strings.
+        checkForNullValues(((LazyStringList) values).getUnderlyingElements());
+        list.addAll((Collection<T>) values);
+      } else if (values instanceof Collection) {
+        checkForNullValues(values);
+        list.addAll((Collection<T>) values);
+      } else {
+        for (final T value : values) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          list.add(value);
+        }
+      }
+    }
+
+    private static void checkForNullValues(final Iterable<?> values) {
+      for (final Object value : values) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+      }
+    }
+  }
+}

+ 258 - 0
java/src/main/java/com/google/protobuf/AbstractParser.java

@@ -0,0 +1,258 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A partial implementation of the {@link Parser} interface which implements
+ * as many methods of that interface as possible in terms of other methods.
+ *
+ * Note: This class implements all the convenience methods in the
+ * {@link Parser} interface. See {@link Parser} for related javadocs.
+ * Subclasses need to implement
+ * {@link Parser#parsePartialFrom(CodedInputStream, ExtensionRegistryLite)}
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+public abstract class AbstractParser<MessageType extends MessageLite>
+    implements Parser<MessageType> {
+  /**
+   * Creates an UninitializedMessageException for MessageType.
+   */
+  private UninitializedMessageException
+      newUninitializedMessageException(MessageType message) {
+    if (message instanceof AbstractMessageLite) {
+      return ((AbstractMessageLite) message).newUninitializedMessageException();
+    }
+    return new UninitializedMessageException(message);
+  }
+
+  /**
+   * Helper method to check if message is initialized.
+   *
+   * @throws InvalidProtocolBufferException if it is not initialized.
+   * @return The message to check.
+   */
+  private MessageType checkMessageInitialized(MessageType message)
+      throws InvalidProtocolBufferException {
+    if (message != null && !message.isInitialized()) {
+      throw newUninitializedMessageException(message)
+          .asInvalidProtocolBufferException()
+          .setUnfinishedMessage(message);
+    }
+    return message;
+  }
+
+  private static final ExtensionRegistryLite EMPTY_REGISTRY
+      = ExtensionRegistryLite.getEmptyRegistry();
+
+  @Override
+  public MessageType parsePartialFrom(CodedInputStream input)
+      throws InvalidProtocolBufferException {
+    return parsePartialFrom(input, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parseFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialFrom(input, extensionRegistry));
+  }
+
+  @Override
+  public MessageType parseFrom(CodedInputStream input) throws InvalidProtocolBufferException {
+    return parseFrom(input, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parsePartialFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    MessageType message;
+    try {
+      CodedInputStream input = data.newCodedInput();
+      message = parsePartialFrom(input, extensionRegistry);
+      try {
+        input.checkLastTagWas(0);
+      } catch (InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(message);
+      }
+      return message;
+    } catch (InvalidProtocolBufferException e) {
+      throw e;
+    }
+  }
+
+  @Override
+  public MessageType parsePartialFrom(ByteString data) throws InvalidProtocolBufferException {
+    return parsePartialFrom(data, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parseFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(parsePartialFrom(data, extensionRegistry));
+  }
+
+  @Override
+  public MessageType parseFrom(ByteString data) throws InvalidProtocolBufferException {
+    return parseFrom(data, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parsePartialFrom(
+      byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    try {
+      CodedInputStream input = CodedInputStream.newInstance(data, off, len);
+      MessageType message = parsePartialFrom(input, extensionRegistry);
+      try {
+        input.checkLastTagWas(0);
+      } catch (InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(message);
+      }
+      return message;
+    } catch (InvalidProtocolBufferException e) {
+      throw e;
+    }
+  }
+
+  @Override
+  public MessageType parsePartialFrom(byte[] data, int off, int len)
+      throws InvalidProtocolBufferException {
+    return parsePartialFrom(data, off, len, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parsePartialFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return parsePartialFrom(data, 0, data.length, extensionRegistry);
+  }
+
+  @Override
+  public MessageType parsePartialFrom(byte[] data) throws InvalidProtocolBufferException {
+    return parsePartialFrom(data, 0, data.length, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parseFrom(
+      byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialFrom(data, off, len, extensionRegistry));
+  }
+
+  @Override
+  public MessageType parseFrom(byte[] data, int off, int len)
+      throws InvalidProtocolBufferException {
+    return parseFrom(data, off, len, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parseFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return parseFrom(data, 0, data.length, extensionRegistry);
+  }
+
+  @Override
+  public MessageType parseFrom(byte[] data) throws InvalidProtocolBufferException {
+    return parseFrom(data, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parsePartialFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    CodedInputStream codedInput = CodedInputStream.newInstance(input);
+    MessageType message = parsePartialFrom(codedInput, extensionRegistry);
+    try {
+      codedInput.checkLastTagWas(0);
+    } catch (InvalidProtocolBufferException e) {
+      throw e.setUnfinishedMessage(message);
+    }
+    return message;
+  }
+
+  @Override
+  public MessageType parsePartialFrom(InputStream input) throws InvalidProtocolBufferException {
+    return parsePartialFrom(input, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parseFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialFrom(input, extensionRegistry));
+  }
+
+  @Override
+  public MessageType parseFrom(InputStream input) throws InvalidProtocolBufferException {
+    return parseFrom(input, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parsePartialDelimitedFrom(
+      InputStream input, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    int size;
+    try {
+      int firstByte = input.read();
+      if (firstByte == -1) {
+        return null;
+      }
+      size = CodedInputStream.readRawVarint32(firstByte, input);
+    } catch (IOException e) {
+      throw new InvalidProtocolBufferException(e.getMessage());
+    }
+    InputStream limitedInput = new LimitedInputStream(input, size);
+    return parsePartialFrom(limitedInput, extensionRegistry);
+  }
+
+  @Override
+  public MessageType parsePartialDelimitedFrom(InputStream input)
+      throws InvalidProtocolBufferException {
+    return parsePartialDelimitedFrom(input, EMPTY_REGISTRY);
+  }
+
+  @Override
+  public MessageType parseDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+      throws InvalidProtocolBufferException {
+    return checkMessageInitialized(
+        parsePartialDelimitedFrom(input, extensionRegistry));
+  }
+
+  @Override
+  public MessageType parseDelimitedFrom(InputStream input) throws InvalidProtocolBufferException {
+    return parseDelimitedFrom(input, EMPTY_REGISTRY);
+  }
+}

+ 180 - 0
java/src/main/java/com/google/protobuf/AbstractProtobufList.java

@@ -0,0 +1,180 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Internal.ProtobufList;
+
+import java.util.AbstractList;
+import java.util.Collection;
+import java.util.List;
+import java.util.RandomAccess;
+
+/**
+ * An abstract implementation of {@link ProtobufList} which manages mutability semantics. All mutate
+ * methods must check if the list is mutable before proceeding. Subclasses must invoke
+ * {@link #ensureIsMutable()} manually when overriding those methods.
+ * <p>
+ * This implementation assumes all subclasses are array based, supporting random access.
+ */
+abstract class AbstractProtobufList<E> extends AbstractList<E> implements ProtobufList<E> {
+
+  protected static final int DEFAULT_CAPACITY = 10;
+
+  /**
+   * Whether or not this list is modifiable.
+   */
+  private boolean isMutable;
+
+  /**
+   * Constructs a mutable list by default.
+   */
+  AbstractProtobufList() {
+    isMutable = true;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (o == this) {
+      return true;
+    }
+    if (!(o instanceof List)) {
+      return false;
+    }
+    // Handle lists that do not support RandomAccess as efficiently as possible by using an iterator
+    // based approach in our super class. Otherwise our index based approach will avoid those
+    // allocations.
+    if (!(o instanceof RandomAccess)) {
+      return super.equals(o);
+    }
+
+    List<?> other = (List<?>) o;
+    final int size = size();
+    if (size != other.size()) {
+      return false;
+    }
+    for (int i = 0; i < size; i++) {
+      if (!get(i).equals(other.get(i))) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    final int size = size();
+    int hashCode = 1;
+    for (int i = 0; i < size; i++) {
+      hashCode = (31 * hashCode) + get(i).hashCode();
+    }
+    return hashCode;
+  }
+
+  @Override
+  public boolean add(E e) {
+    ensureIsMutable();
+    return super.add(e);
+  }
+
+  @Override
+  public void add(int index, E element) {
+    ensureIsMutable();
+    super.add(index, element);
+  }
+
+  @Override
+  public boolean addAll(Collection<? extends E> c) {
+    ensureIsMutable();
+    return super.addAll(c);
+  }
+  
+  @Override
+  public boolean addAll(int index, Collection<? extends E> c) {
+    ensureIsMutable();
+    return super.addAll(index, c);
+  }
+
+  @Override
+  public void clear() {
+    ensureIsMutable();
+    super.clear();
+  }
+  
+  @Override
+  public boolean isModifiable() {
+    return isMutable;
+  }
+  
+  @Override
+  public final void makeImmutable() {
+    isMutable = false;
+  }
+  
+  @Override
+  public E remove(int index) {
+    ensureIsMutable();
+    return super.remove(index);
+  }
+  
+  @Override
+  public boolean remove(Object o) {
+    ensureIsMutable();
+    return super.remove(o);
+  }
+  
+  @Override
+  public boolean removeAll(Collection<?> c) {
+    ensureIsMutable();
+    return super.removeAll(c);
+  }
+  
+  @Override
+  public boolean retainAll(Collection<?> c) {
+    ensureIsMutable();
+    return super.retainAll(c);
+  }
+  
+  @Override
+  public E set(int index, E element) {
+    ensureIsMutable();
+    return super.set(index, element);
+  }
+  
+  /**
+   * Throws an {@link UnsupportedOperationException} if the list is immutable. Subclasses are
+   * responsible for invoking this method on mutate operations.
+   */
+  protected void ensureIsMutable() {
+    if (!isMutable) {
+      throw new UnsupportedOperationException();
+    }
+  }
+}

+ 51 - 0
java/src/main/java/com/google/protobuf/BlockingRpcChannel.java

@@ -0,0 +1,51 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+/**
+ * <p>Abstract interface for a blocking RPC channel.  {@code BlockingRpcChannel}
+ * is the blocking equivalent to {@link RpcChannel}.
+ *
+ * @author kenton@google.com Kenton Varda
+ * @author cpovirk@google.com Chris Povirk
+ */
+public interface BlockingRpcChannel {
+  /**
+   * Call the given method of the remote service and blocks until it returns.
+   * {@code callBlockingMethod()} is the blocking equivalent to
+   * {@link RpcChannel#callMethod}.
+   */
+  Message callBlockingMethod(
+      Descriptors.MethodDescriptor method,
+      RpcController controller,
+      Message request,
+      Message responsePrototype) throws ServiceException;
+}

+ 64 - 0
java/src/main/java/com/google/protobuf/BlockingService.java

@@ -0,0 +1,64 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+/**
+ * Blocking equivalent to {@link Service}.
+ *
+ * @author kenton@google.com Kenton Varda
+ * @author cpovirk@google.com Chris Povirk
+ */
+public interface BlockingService {
+  /**
+   * Equivalent to {@link Service#getDescriptorForType}.
+   */
+  Descriptors.ServiceDescriptor getDescriptorForType();
+
+  /**
+   * Equivalent to {@link Service#callMethod}, except that
+   * {@code callBlockingMethod()} returns the result of the RPC or throws a
+   * {@link ServiceException} if there is a failure, rather than passing the
+   * information to a callback.
+   */
+  Message callBlockingMethod(Descriptors.MethodDescriptor method,
+                             RpcController controller,
+                             Message request) throws ServiceException;
+
+  /**
+   * Equivalent to {@link Service#getRequestPrototype}.
+   */
+  Message getRequestPrototype(Descriptors.MethodDescriptor method);
+
+  /**
+   * Equivalent to {@link Service#getResponsePrototype}.
+   */
+  Message getResponsePrototype(Descriptors.MethodDescriptor method);
+}

+ 5 - 1
java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java

@@ -264,7 +264,11 @@ class FieldMaskTree {
             }
           }
         } else {
-          destination.setField(field, source.getField(field));
+          if (source.hasField(field) || !options.replacePrimitiveFields()) {
+            destination.setField(field, source.getField(field));
+          } else {
+            destination.clearField(field);
+          }
         }
       }
     }

+ 37 - 8
java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java

@@ -211,14 +211,19 @@ public class FieldMaskUtil {
   public static FieldMask normalize(FieldMask mask) {
     return new FieldMaskTree(mask).toFieldMask();
   }
-  
+
   /**
-   * Creates an union of two FieldMasks.
+   * Creates a union of two or more FieldMasks.
    */
-  public static FieldMask union(FieldMask mask1, FieldMask mask2) {
-    return new FieldMaskTree(mask1).mergeFromFieldMask(mask2).toFieldMask();
+  public static FieldMask union(
+      FieldMask firstMask, FieldMask secondMask, FieldMask... otherMasks) {
+    FieldMaskTree maskTree = new FieldMaskTree(firstMask).mergeFromFieldMask(secondMask);
+    for (FieldMask mask : otherMasks) {
+      maskTree.mergeFromFieldMask(mask);
+    }
+    return maskTree.toFieldMask();
   }
-  
+
   /**
    * Calculates the intersection of two FieldMasks.
    */
@@ -237,6 +242,9 @@ public class FieldMaskUtil {
   public static final class MergeOptions {
     private boolean replaceMessageFields = false;
     private boolean replaceRepeatedFields = false;
+    // TODO(b/28277137): change the default behavior to always replace primitive fields after
+    // fixing all failing TAP tests.
+    private boolean replacePrimitiveFields = false;
 
     /**
      * Whether to replace message fields (i.e., discard existing content in
@@ -257,7 +265,23 @@ public class FieldMaskUtil {
     public boolean replaceRepeatedFields() {
       return replaceRepeatedFields;
     }
-    
+
+    /**
+     * Whether to replace primitive (non-repeated and non-message) fields in
+     * destination message fields with the source primitive fields (i.e., if the
+     * field is set in the source, the value is copied to the
+     * destination; if the field is unset in the source, the field is cleared
+     * from the destination) when merging.
+     *
+     * <p>Default behavior is to always set the value of the source primitive
+     * field to the destination primitive field, and if the source field is
+     * unset, the default value of the source field is copied to the
+     * destination.
+     */
+    public boolean replacePrimitiveFields() {
+      return replacePrimitiveFields;
+    }
+
     public void setReplaceMessageFields(boolean value) {
       replaceMessageFields = value;
     }
@@ -265,10 +289,15 @@ public class FieldMaskUtil {
     public void setReplaceRepeatedFields(boolean value) {
       replaceRepeatedFields = value;
     }
+
+    public void setReplacePrimitiveFields(boolean value) {
+      replacePrimitiveFields = value;
+    }
   }
-  
+
   /**
-   * Merges fields specified by a FieldMask from one message to another.
+   * Merges fields specified by a FieldMask from one message to another with the
+   * specified merge options.
    */
   public static void merge(FieldMask mask, Message source,
       Message.Builder destination, MergeOptions options) {

+ 20 - 0
java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java

@@ -237,5 +237,25 @@ public class FieldMaskTreeTest extends TestCase {
     builder.getPayloadBuilder().setOptionalUint32(2000);
     new FieldMaskTree().addFieldPath("payload").merge(clearedSource, builder, options);
     assertEquals(false, builder.hasPayload());
+
+    // Test merging unset primitive fields.
+    builder = source.toBuilder();
+    builder.getPayloadBuilder().clearOptionalInt32();
+    NestedTestAllTypes sourceWithPayloadInt32Unset = builder.build();
+    builder = source.toBuilder();
+    new FieldMaskTree()
+        .addFieldPath("payload.optional_int32")
+        .merge(sourceWithPayloadInt32Unset, builder, options);
+    assertEquals(true, builder.getPayload().hasOptionalInt32());
+    assertEquals(0, builder.getPayload().getOptionalInt32());
+
+    // Change to clear unset primitive fields.
+    options.setReplacePrimitiveFields(true);
+    builder = source.toBuilder();
+    new FieldMaskTree()
+        .addFieldPath("payload.optional_int32")
+        .merge(sourceWithPayloadInt32Unset, builder, options);
+    assertEquals(true, builder.hasPayload());
+    assertEquals(false, builder.getPayload().hasOptionalInt32());
   }
 }

+ 9 - 0
java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java

@@ -152,6 +152,15 @@ public class FieldMaskUtilTest extends TestCase {
     FieldMask result = FieldMaskUtil.union(mask1, mask2);
     assertEquals("bar,foo", FieldMaskUtil.toString(result));
   }
+
+  public void testUnion_usingVarArgs() throws Exception {
+    FieldMask mask1 = FieldMaskUtil.fromString("foo");
+    FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar.quz");
+    FieldMask mask3 = FieldMaskUtil.fromString("bar.quz");
+    FieldMask mask4 = FieldMaskUtil.fromString("bar");
+    FieldMask result = FieldMaskUtil.union(mask1, mask2, mask3, mask4);
+    assertEquals("bar,foo", FieldMaskUtil.toString(result));
+  }
   
   public void testIntersection() throws Exception {
     // Only test a simple case here and expect

+ 50 - 0
js/binary/utils.js

@@ -567,6 +567,56 @@ jspb.utils.hash64ArrayToDecimalStrings = function(hashes, signed) {
 };
 
 
+/**
+ * Converts a signed or unsigned decimal string into its hash string
+ * representation.
+ * @param {string} dec
+ * @return {string}
+ */
+jspb.utils.decimalStringToHash64 = function(dec) {
+  goog.asserts.assert(dec.length > 0);
+
+  // Check for minus sign.
+  var minus = false;
+  if (dec[0] === '-') {
+    minus = true;
+    dec = dec.slice(1);
+  }
+
+  // Store result as a byte array.
+  var resultBytes = [0, 0, 0, 0, 0, 0, 0, 0];
+
+  // Set result to m*result + c.
+  function muladd(m, c) {
+    for (var i = 0; i < 8 && (m !== 1 || c > 0); i++) {
+      var r = m * resultBytes[i] + c;
+      resultBytes[i] = r & 0xFF;
+      c = r >>> 8;
+    }
+  }
+
+  // Negate the result bits.
+  function neg() {
+    for (var i = 0; i < 8; i++) {
+      resultBytes[i] = (~resultBytes[i]) & 0xFF;
+    }
+  }
+
+  // For each decimal digit, set result to 10*result + digit.
+  for (var i = 0; i < dec.length; i++) {
+    muladd(10, jspb.utils.DIGITS.indexOf(dec[i]));
+  }
+
+  // If there's a minus sign, convert into two's complement.
+  if (minus) {
+    neg();
+    muladd(1, 1);
+  }
+
+  return String.fromCharCode.apply(null, resultBytes);
+};
+
+
 /**
  * Converts an 8-character hash string into its hexadecimal representation.
  * @param {string} hash

+ 35 - 0
js/binary/utils_test.js

@@ -197,6 +197,41 @@ describe('binaryUtilsTest', function() {
     assertEquals('123456789123456789', result[2]);
   });
 
+  /*
+   * Going from decimal strings to hash strings should be lossless.
+   */
+  it('testDecimalToHashConversion', function() {
+    var result;
+    var convert = jspb.utils.decimalStringToHash64;
+
+    result = convert('0');
+    assertEquals(String.fromCharCode.apply(null,
+      [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result);
+
+    result = convert('-1');
+    assertEquals(String.fromCharCode.apply(null,
+      [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
+
+    result = convert('18446744073709551615');
+    assertEquals(String.fromCharCode.apply(null,
+      [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
+
+    result = convert('9223372036854775808');
+    assertEquals(String.fromCharCode.apply(null,
+      [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result);
+
+    result = convert('-9223372036854775808');
+    assertEquals(String.fromCharCode.apply(null,
+      [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result);
+
+    result = convert('123456789123456789');
+    assertEquals(String.fromCharCode.apply(null,
+      [0x15, 0x5F, 0xD0, 0xAC, 0x4B, 0x9B, 0xB6, 0x01]), result);
+
+    result = convert('-123456789123456789');
+    assertEquals(String.fromCharCode.apply(null,
+      [0xEB, 0xA0, 0x2F, 0x53, 0xB4, 0x64, 0x49, 0xFE]), result);
+  });
 
   /**
    * Going from hash strings to hex strings should be lossless.

+ 2 - 0
objectivec/google/protobuf/Any.pbobjc.h

@@ -106,6 +106,8 @@ typedef GPB_ENUM(GPBAny_FieldNumber) {
 /// * If no schema is provided, `https` is assumed.
 /// * The last segment of the URL's path must represent the fully
 ///   qualified name of the type (as in `path/google.protobuf.Duration`).
+///   The name should be in a canonical form (e.g., leading "." is
+///   not accepted).
 /// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
 ///   value in binary format, or produce an error.
 /// * Applications are allowed to cache lookup results based on the

+ 1 - 1
objectivec/google/protobuf/FieldMask.pbobjc.h

@@ -84,7 +84,7 @@ typedef GPB_ENUM(GPBFieldMask_FieldNumber) {
 /// operation applies to all fields (as if a FieldMask of all fields
 /// had been specified).
 ///
-/// Note that a field mask does not necessarily applies to the
+/// Note that a field mask does not necessarily apply to the
 /// top-level response message. In case of a REST get operation, the
 /// field mask applies directly to the response, but in case of a REST
 /// list operation, the mask instead applies to each individual message

+ 4 - 0
php/tests/autoload.php

@@ -0,0 +1,4 @@
+<?php
+
+require_once('test.pb.php');
+require_once('test_util.php');

+ 7 - 2
python/google/protobuf/descriptor.py

@@ -783,6 +783,8 @@ class FileDescriptor(DescriptorBase):
   serialized_pb: (str) Byte string of serialized
     descriptor_pb2.FileDescriptorProto.
   dependencies: List of other FileDescriptors this FileDescriptor depends on.
+  public_dependencies: A list of FileDescriptors, subset of the dependencies
+    above, which were declared as "public".
   message_types_by_name: Dict of message names of their descriptors.
   enum_types_by_name: Dict of enum names and their descriptors.
   extensions_by_name: Dict of extension names and their descriptors.
@@ -794,7 +796,8 @@ class FileDescriptor(DescriptorBase):
     _C_DESCRIPTOR_CLASS = _message.FileDescriptor
 
     def __new__(cls, name, package, options=None, serialized_pb=None,
-                dependencies=None, syntax=None, pool=None):
+                dependencies=None, public_dependencies=None,
+                syntax=None, pool=None):
       # FileDescriptor() is called from various places, not only from generated
       # files, to register dynamic proto files and messages.
       if serialized_pb:
@@ -805,7 +808,8 @@ class FileDescriptor(DescriptorBase):
         return super(FileDescriptor, cls).__new__(cls)
 
   def __init__(self, name, package, options=None, serialized_pb=None,
-               dependencies=None, syntax=None, pool=None):
+               dependencies=None, public_dependencies=None,
+               syntax=None, pool=None):
     """Constructor."""
     super(FileDescriptor, self).__init__(options, 'FileOptions')
 
@@ -822,6 +826,7 @@ class FileDescriptor(DescriptorBase):
     self.enum_types_by_name = {}
     self.extensions_by_name = {}
     self.dependencies = (dependencies or [])
+    self.public_dependencies = (public_dependencies or [])
 
     if (api_implementation.Type() == 'cpp' and
         self.serialized_pb is not None):

+ 3 - 1
python/google/protobuf/descriptor_pool.py

@@ -319,6 +319,7 @@ class DescriptorPool(object):
     if file_proto.name not in self._file_descriptors:
       built_deps = list(self._GetDeps(file_proto.dependency))
       direct_deps = [self.FindFileByName(n) for n in file_proto.dependency]
+      public_deps = [direct_deps[i] for i in file_proto.public_dependency]
 
       file_descriptor = descriptor.FileDescriptor(
           pool=self,
@@ -327,7 +328,8 @@ class DescriptorPool(object):
           syntax=file_proto.syntax,
           options=file_proto.options,
           serialized_pb=file_proto.SerializeToString(),
-          dependencies=direct_deps)
+          dependencies=direct_deps,
+          public_dependencies=public_deps)
       if _USE_C_DESCRIPTORS:
         # When using C++ descriptors, all objects defined in the file were added
         # to the C++ database when the FileDescriptor was built above.

+ 6 - 0
python/google/protobuf/internal/api_implementation.py

@@ -32,6 +32,7 @@
 """
 
 import os
+import warnings
 import sys
 
 try:
@@ -78,6 +79,11 @@ _implementation_type = os.getenv('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION',
 if _implementation_type != 'python':
   _implementation_type = 'cpp'
 
+if 'PyPy' in sys.version and _implementation_type == 'cpp':
+  warnings.warn('PyPy does not work yet with cpp protocol buffers. '
+                'Falling back to the python implementation.')
+  _implementation_type = 'python'
+
 # This environment variable can be used to switch between the two
 # 'cpp' implementations, overriding the compile-time constants in the
 # _api_implementation module. Right now only '2' is supported. Any other

+ 16 - 30
python/google/protobuf/internal/descriptor_pool_test.py

@@ -51,6 +51,7 @@ from google.protobuf.internal import descriptor_pool_test1_pb2
 from google.protobuf.internal import descriptor_pool_test2_pb2
 from google.protobuf.internal import factory_test1_pb2
 from google.protobuf.internal import factory_test2_pb2
+from google.protobuf.internal import more_messages_pb2
 from google.protobuf import descriptor
 from google.protobuf import descriptor_database
 from google.protobuf import descriptor_pool
@@ -60,11 +61,8 @@ from google.protobuf import symbol_database
 
 class DescriptorPoolTest(unittest.TestCase):
 
-  def CreatePool(self):
-    return descriptor_pool.DescriptorPool()
-
   def setUp(self):
-    self.pool = self.CreatePool()
+    self.pool = descriptor_pool.DescriptorPool()
     self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString(
         factory_test1_pb2.DESCRIPTOR.serialized_pb)
     self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString(
@@ -275,10 +273,13 @@ class DescriptorPoolTest(unittest.TestCase):
     self.testFindMessageTypeByName()
 
   def testComplexNesting(self):
+    more_messages_desc = descriptor_pb2.FileDescriptorProto.FromString(
+        more_messages_pb2.DESCRIPTOR.serialized_pb)
     test1_desc = descriptor_pb2.FileDescriptorProto.FromString(
         descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb)
     test2_desc = descriptor_pb2.FileDescriptorProto.FromString(
         descriptor_pool_test2_pb2.DESCRIPTOR.serialized_pb)
+    self.pool.Add(more_messages_desc)
     self.pool.Add(test1_desc)
     self.pool.Add(test2_desc)
     TEST1_FILE.CheckFile(self, self.pool)
@@ -350,25 +351,15 @@ class DescriptorPoolTest(unittest.TestCase):
     _CheckDefaultValues(message_class())
 
 
-@unittest.skipIf(api_implementation.Type() != 'cpp',
-                 'explicit tests of the C++ implementation')
-class CppDescriptorPoolTest(DescriptorPoolTest):
-  # TODO(amauryfa): remove when descriptor_pool.DescriptorPool() creates true
-  # C++ descriptor pool object for C++ implementation.
-
-  def CreatePool(self):
-    # pylint: disable=g-import-not-at-top
-    from google.protobuf.pyext import _message
-    return _message.DescriptorPool()
-
-
 class ProtoFile(object):
 
-  def __init__(self, name, package, messages, dependencies=None):
+  def __init__(self, name, package, messages, dependencies=None,
+               public_dependencies=None):
     self.name = name
     self.package = package
     self.messages = messages
     self.dependencies = dependencies or []
+    self.public_dependencies = public_dependencies or []
 
   def CheckFile(self, test, pool):
     file_desc = pool.FindFileByName(self.name)
@@ -376,6 +367,8 @@ class ProtoFile(object):
     test.assertEqual(self.package, file_desc.package)
     dependencies_names = [f.name for f in file_desc.dependencies]
     test.assertEqual(self.dependencies, dependencies_names)
+    public_dependencies_names = [f.name for f in file_desc.public_dependencies]
+    test.assertEqual(self.public_dependencies, public_dependencies_names)
     for name, msg_type in self.messages.items():
       msg_type.CheckType(test, None, name, file_desc)
 
@@ -613,18 +606,9 @@ class AddDescriptorTest(unittest.TestCase):
       pool.FindFileContainingSymbol(
           'protobuf_unittest.TestAllTypes')
 
-  def _GetDescriptorPoolClass(self):
-    # Test with both implementations of descriptor pools.
-    if api_implementation.Type() == 'cpp':
-      # pylint: disable=g-import-not-at-top
-      from google.protobuf.pyext import _message
-      return _message.DescriptorPool
-    else:
-      return descriptor_pool.DescriptorPool
-
   def testEmptyDescriptorPool(self):
-    # Check that an empty DescriptorPool() contains no message.
-    pool = self._GetDescriptorPoolClass()()
+    # Check that an empty DescriptorPool() contains no messages.
+    pool = descriptor_pool.DescriptorPool()
     proto_file_name = descriptor_pb2.DESCRIPTOR.name
     self.assertRaises(KeyError, pool.FindFileByName, proto_file_name)
     # Add the above file to the pool
@@ -636,7 +620,7 @@ class AddDescriptorTest(unittest.TestCase):
 
   def testCustomDescriptorPool(self):
     # Create a new pool, and add a file descriptor.
-    pool = self._GetDescriptorPoolClass()()
+    pool = descriptor_pool.DescriptorPool()
     file_desc = descriptor_pb2.FileDescriptorProto(
         name='some/file.proto', package='package')
     file_desc.message_type.add(name='Message')
@@ -757,7 +741,9 @@ TEST2_FILE = ProtoFile(
              ExtensionField(1001, 'DescriptorPoolTest1')),
         ]),
     },
-    dependencies=['google/protobuf/internal/descriptor_pool_test1.proto'])
+    dependencies=['google/protobuf/internal/descriptor_pool_test1.proto',
+                  'google/protobuf/internal/more_messages.proto'],
+    public_dependencies=['google/protobuf/internal/more_messages.proto'])
 
 
 if __name__ == '__main__':

+ 1 - 0
python/google/protobuf/internal/descriptor_pool_test2.proto

@@ -33,6 +33,7 @@ syntax = "proto2";
 package google.protobuf.python.internal;
 
 import "google/protobuf/internal/descriptor_pool_test1.proto";
+import public "google/protobuf/internal/more_messages.proto";
 
 
 message DescriptorPoolTest3 {

+ 54 - 0
python/google/protobuf/internal/message_factory_test.py

@@ -131,6 +131,60 @@ class MessageFactoryTest(unittest.TestCase):
       self.assertEqual('test1', msg1.Extensions[ext1])
       self.assertEqual('test2', msg1.Extensions[ext2])
 
+  def testDuplicateExtensionNumber(self):
+    pool = descriptor_pool.DescriptorPool()
+    factory = message_factory.MessageFactory(pool=pool)
+
+    # Add Container message.
+    f = descriptor_pb2.FileDescriptorProto()
+    f.name = 'google/protobuf/internal/container.proto'
+    f.package = 'google.protobuf.python.internal'
+    msg = f.message_type.add()
+    msg.name = 'Container'
+    rng = msg.extension_range.add()
+    rng.start = 1
+    rng.end = 10
+    pool.Add(f)
+    msgs = factory.GetMessages([f.name])
+    self.assertIn('google.protobuf.python.internal.Container', msgs)
+
+    # Extend container.
+    f = descriptor_pb2.FileDescriptorProto()
+    f.name = 'google/protobuf/internal/extension.proto'
+    f.package = 'google.protobuf.python.internal'
+    f.dependency.append('google/protobuf/internal/container.proto')
+    msg = f.message_type.add()
+    msg.name = 'Extension'
+    ext = msg.extension.add()
+    ext.name = 'extension_field'
+    ext.number = 2
+    ext.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL
+    ext.type_name = 'Extension'
+    ext.extendee = 'Container'
+    pool.Add(f)
+    msgs = factory.GetMessages([f.name])
+    self.assertIn('google.protobuf.python.internal.Extension', msgs)
+
+    # Add Duplicate extending the same field number.
+    f = descriptor_pb2.FileDescriptorProto()
+    f.name = 'google/protobuf/internal/duplicate.proto'
+    f.package = 'google.protobuf.python.internal'
+    f.dependency.append('google/protobuf/internal/container.proto')
+    msg = f.message_type.add()
+    msg.name = 'Duplicate'
+    ext = msg.extension.add()
+    ext.name = 'extension_field'
+    ext.number = 2
+    ext.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL
+    ext.type_name = 'Duplicate'
+    ext.extendee = 'Container'
+    pool.Add(f)
+
+    with self.assertRaises(Exception) as cm:
+      factory.GetMessages([f.name])
+
+    self.assertIsInstance(cm.exception, (AssertionError, ValueError))
+
 
 if __name__ == '__main__':
   unittest.main()

+ 30 - 4
python/google/protobuf/internal/message_test.py

@@ -57,18 +57,18 @@ try:
 except ImportError:
   import unittest
 
-from google.protobuf.internal import _parameterized
+from google.protobuf import map_unittest_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf import unittest_proto3_arena_pb2
 from google.protobuf import descriptor_pb2
 from google.protobuf import descriptor_pool
-from google.protobuf import map_unittest_pb2
 from google.protobuf import message_factory
 from google.protobuf import text_format
-from google.protobuf import unittest_pb2
-from google.protobuf import unittest_proto3_arena_pb2
 from google.protobuf.internal import api_implementation
 from google.protobuf.internal import packed_field_test_pb2
 from google.protobuf.internal import test_util
 from google.protobuf import message
+from google.protobuf.internal import _parameterized
 
 if six.PY3:
   long = int
@@ -1265,7 +1265,10 @@ class Proto3Test(unittest.TestCase):
     self.assertFalse(-2**33 in msg.map_int64_int64)
     self.assertFalse(123 in msg.map_uint32_uint32)
     self.assertFalse(2**33 in msg.map_uint64_uint64)
+    self.assertFalse(123 in msg.map_int32_double)
+    self.assertFalse(False in msg.map_bool_bool)
     self.assertFalse('abc' in msg.map_string_string)
+    self.assertFalse(111 in msg.map_int32_bytes)
     self.assertFalse(888 in msg.map_int32_enum)
 
     # Accessing an unset key returns the default.
@@ -1273,7 +1276,12 @@ class Proto3Test(unittest.TestCase):
     self.assertEqual(0, msg.map_int64_int64[-2**33])
     self.assertEqual(0, msg.map_uint32_uint32[123])
     self.assertEqual(0, msg.map_uint64_uint64[2**33])
+    self.assertEqual(0.0, msg.map_int32_double[123])
+    self.assertTrue(isinstance(msg.map_int32_double[123], float))
+    self.assertEqual(False, msg.map_bool_bool[False])
+    self.assertTrue(isinstance(msg.map_bool_bool[False], bool))
     self.assertEqual('', msg.map_string_string['abc'])
+    self.assertEqual(b'', msg.map_int32_bytes[111])
     self.assertEqual(0, msg.map_int32_enum[888])
 
     # It also sets the value in the map
@@ -1281,7 +1289,10 @@ class Proto3Test(unittest.TestCase):
     self.assertTrue(-2**33 in msg.map_int64_int64)
     self.assertTrue(123 in msg.map_uint32_uint32)
     self.assertTrue(2**33 in msg.map_uint64_uint64)
+    self.assertTrue(123 in msg.map_int32_double)
+    self.assertTrue(False in msg.map_bool_bool)
     self.assertTrue('abc' in msg.map_string_string)
+    self.assertTrue(111 in msg.map_int32_bytes)
     self.assertTrue(888 in msg.map_int32_enum)
 
     self.assertIsInstance(msg.map_string_string['abc'], six.text_type)
@@ -1587,6 +1598,21 @@ class Proto3Test(unittest.TestCase):
     matching_dict = {2: 4, 3: 6, 4: 8}
     self.assertMapIterEquals(msg.map_int32_int32.items(), matching_dict)
 
+  def testMapItems(self):
+    # Map items used to have strange behaviors when use c extension. Because
+    # [] may reorder the map and invalidate any exsting iterators.
+    # TODO(jieluo): Check if [] reordering the map is a bug or intended
+    # behavior.
+    msg = map_unittest_pb2.TestMap()
+    msg.map_string_string['local_init_op'] = ''
+    msg.map_string_string['trainable_variables'] = ''
+    msg.map_string_string['variables'] = ''
+    msg.map_string_string['init_op'] = ''
+    msg.map_string_string['summaries'] = ''
+    items1 = msg.map_string_string.items()
+    items2 = msg.map_string_string.items()
+    self.assertEqual(items1, items2)
+
   def testMapIterationClearMessage(self):
     # Iterator needs to work even if message and map are deleted.
     msg = map_unittest_pb2.TestMap()

+ 1 - 0
python/google/protobuf/internal/proto_builder_test.py

@@ -40,6 +40,7 @@ try:
   import unittest2 as unittest
 except ImportError:
   import unittest
+
 from google.protobuf import descriptor_pb2
 from google.protobuf import descriptor_pool
 from google.protobuf import proto_builder

+ 52 - 24
python/google/protobuf/internal/python_message.py

@@ -56,7 +56,14 @@ import struct
 import weakref
 
 import six
-import six.moves.copyreg as copyreg
+try:
+  import six.moves.copyreg as copyreg
+except ImportError:
+  # On some platforms, for example gMac, we run native Python because there is
+  # nothing like hermetic Python. This means lesser control on the system and
+  # the six.moves package may be missing (is missing on 20150321 on gMac). Be
+  # extra conservative and try to load the old replacement if it fails.
+  import copy_reg as copyreg
 
 # We use "as" to avoid name collisions with variables.
 from google.protobuf.internal import containers
@@ -490,6 +497,9 @@ def _AddInitMethod(message_descriptor, cls):
       if field is None:
         raise TypeError("%s() got an unexpected keyword argument '%s'" %
                         (message_descriptor.name, field_name))
+      if field_value is None:
+        # field=None is the same as no field at all.
+        continue
       if field.label == _FieldDescriptor.LABEL_REPEATED:
         copy = field._default_constructor(self)
         if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:  # Composite
@@ -889,17 +899,6 @@ def _AddClearExtensionMethod(cls):
   cls.ClearExtension = ClearExtension
 
 
-def _AddClearMethod(message_descriptor, cls):
-  """Helper for _AddMessageMethods()."""
-  def Clear(self):
-    # Clear fields.
-    self._fields = {}
-    self._unknown_fields = ()
-    self._oneofs = {}
-    self._Modified()
-  cls.Clear = Clear
-
-
 def _AddHasExtensionMethod(cls):
   """Helper for _AddMessageMethods()."""
   def HasExtension(self, extension_handle):
@@ -999,16 +998,6 @@ def _AddUnicodeMethod(unused_message_descriptor, cls):
   cls.__unicode__ = __unicode__
 
 
-def _AddSetListenerMethod(cls):
-  """Helper for _AddMessageMethods()."""
-  def SetListener(self, listener):
-    if listener is None:
-      self._listener = message_listener_mod.NullMessageListener()
-    else:
-      self._listener = listener
-  cls._SetListener = SetListener
-
-
 def _BytesForNonRepeatedElement(value, field_number, field_type):
   """Returns the number of bytes needed to serialize a non-repeated element.
   The returned byte count includes space for tag information and any
@@ -1288,6 +1277,32 @@ def _AddWhichOneofMethod(message_descriptor, cls):
   cls.WhichOneof = WhichOneof
 
 
+def _Clear(self):
+  # Clear fields.
+  self._fields = {}
+  self._unknown_fields = ()
+  self._oneofs = {}
+  self._Modified()
+
+
+def _DiscardUnknownFields(self):
+  self._unknown_fields = []
+  for field, value in self.ListFields():
+    if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+      if field.label == _FieldDescriptor.LABEL_REPEATED:
+        for sub_message in value:
+          sub_message.DiscardUnknownFields()
+      else:
+        value.DiscardUnknownFields()
+
+
+def _SetListener(self, listener):
+  if listener is None:
+    self._listener = message_listener_mod.NullMessageListener()
+  else:
+    self._listener = listener
+
+
 def _AddMessageMethods(message_descriptor, cls):
   """Adds implementations of all Message methods to cls."""
   _AddListFieldsMethod(message_descriptor, cls)
@@ -1296,12 +1311,10 @@ def _AddMessageMethods(message_descriptor, cls):
   if message_descriptor.is_extendable:
     _AddClearExtensionMethod(cls)
     _AddHasExtensionMethod(cls)
-  _AddClearMethod(message_descriptor, cls)
   _AddEqualsMethod(message_descriptor, cls)
   _AddStrMethod(message_descriptor, cls)
   _AddReprMethod(message_descriptor, cls)
   _AddUnicodeMethod(message_descriptor, cls)
-  _AddSetListenerMethod(cls)
   _AddByteSizeMethod(message_descriptor, cls)
   _AddSerializeToStringMethod(message_descriptor, cls)
   _AddSerializePartialToStringMethod(message_descriptor, cls)
@@ -1309,6 +1322,10 @@ def _AddMessageMethods(message_descriptor, cls):
   _AddIsInitializedMethod(message_descriptor, cls)
   _AddMergeFromMethod(cls)
   _AddWhichOneofMethod(message_descriptor, cls)
+  # Adds methods which do not depend on cls.
+  cls.Clear = _Clear
+  cls.DiscardUnknownFields = _DiscardUnknownFields
+  cls._SetListener = _SetListener
 
 
 def _AddPrivateHelperMethods(message_descriptor, cls):
@@ -1518,3 +1535,14 @@ class _ExtensionDict(object):
       Extension field descriptor.
     """
     return self._extended_message._extensions_by_name.get(name, None)
+
+  def _FindExtensionByNumber(self, number):
+    """Tries to find a known extension with the field number.
+
+    Args:
+      number: Extension field number.
+
+    Returns:
+      Extension field descriptor.
+    """
+    return self._extended_message._extensions_by_number.get(number, None)

+ 9 - 3
python/google/protobuf/internal/reflection_test.py

@@ -120,11 +120,13 @@ class ReflectionTest(unittest.TestCase):
     proto = unittest_pb2.TestAllTypes(
         optional_int32=24,
         optional_double=54.321,
-        optional_string='optional_string')
+        optional_string='optional_string',
+        optional_float=None)
 
     self.assertEqual(24, proto.optional_int32)
     self.assertEqual(54.321, proto.optional_double)
     self.assertEqual('optional_string', proto.optional_string)
+    self.assertFalse(proto.HasField("optional_float"))
 
   def testRepeatedScalarConstructor(self):
     # Constructor with only repeated scalar types should succeed.
@@ -132,12 +134,14 @@ class ReflectionTest(unittest.TestCase):
         repeated_int32=[1, 2, 3, 4],
         repeated_double=[1.23, 54.321],
         repeated_bool=[True, False, False],
-        repeated_string=["optional_string"])
+        repeated_string=["optional_string"],
+        repeated_float=None)
 
     self.assertEqual([1, 2, 3, 4], list(proto.repeated_int32))
     self.assertEqual([1.23, 54.321], list(proto.repeated_double))
     self.assertEqual([True, False, False], list(proto.repeated_bool))
     self.assertEqual(["optional_string"], list(proto.repeated_string))
+    self.assertEqual([], list(proto.repeated_float))
 
   def testRepeatedCompositeConstructor(self):
     # Constructor with only repeated composite types should succeed.
@@ -188,7 +192,8 @@ class ReflectionTest(unittest.TestCase):
         repeated_foreign_message=[
             unittest_pb2.ForeignMessage(c=-43),
             unittest_pb2.ForeignMessage(c=45324),
-            unittest_pb2.ForeignMessage(c=12)])
+            unittest_pb2.ForeignMessage(c=12)],
+        optional_nested_message=None)
 
     self.assertEqual(24, proto.optional_int32)
     self.assertEqual('optional_string', proto.optional_string)
@@ -205,6 +210,7 @@ class ReflectionTest(unittest.TestCase):
          unittest_pb2.ForeignMessage(c=45324),
          unittest_pb2.ForeignMessage(c=12)],
         list(proto.repeated_foreign_message))
+    self.assertFalse(proto.HasField("optional_nested_message"))
 
   def testConstructorTypeError(self):
     self.assertRaises(

+ 93 - 0
python/google/protobuf/internal/text_format_test.py

@@ -250,6 +250,36 @@ class TextFormatTest(TextFormatBase):
     message.c = 123
     self.assertEqual('c: 123\n', str(message))
 
+  def testPrintField(self, message_module):
+    message = message_module.TestAllTypes()
+    field = message.DESCRIPTOR.fields_by_name['optional_float']
+    value = message.optional_float
+    out = text_format.TextWriter(False)
+    text_format.PrintField(field, value, out)
+    self.assertEqual('optional_float: 0.0\n', out.getvalue())
+    out.close()
+    # Test Printer
+    out = text_format.TextWriter(False)
+    printer = text_format._Printer(out)
+    printer.PrintField(field, value)
+    self.assertEqual('optional_float: 0.0\n', out.getvalue())
+    out.close()
+
+  def testPrintFieldValue(self, message_module):
+    message = message_module.TestAllTypes()
+    field = message.DESCRIPTOR.fields_by_name['optional_float']
+    value = message.optional_float
+    out = text_format.TextWriter(False)
+    text_format.PrintFieldValue(field, value, out)
+    self.assertEqual('0.0', out.getvalue())
+    out.close()
+    # Test Printer
+    out = text_format.TextWriter(False)
+    printer = text_format._Printer(out)
+    printer.PrintFieldValue(field, value)
+    self.assertEqual('0.0', out.getvalue())
+    out.close()
+
   def testParseAllFields(self, message_module):
     message = message_module.TestAllTypes()
     test_util.SetAllFields(message)
@@ -616,6 +646,26 @@ class Proto2Tests(TextFormatBase):
         '  text: \"bar\"\n'
         '}\n')
 
+  def testPrintMessageSetByFieldNumber(self):
+    out = text_format.TextWriter(False)
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    message.message_set.Extensions[ext1].i = 23
+    message.message_set.Extensions[ext2].str = 'foo'
+    text_format.PrintMessage(message, out, use_field_number=True)
+    self.CompareToGoldenText(
+        out.getvalue(),
+        '1 {\n'
+        '  1545008 {\n'
+        '    15: 23\n'
+        '  }\n'
+        '  1547769 {\n'
+        '    25: \"foo\"\n'
+        '  }\n'
+        '}\n')
+    out.close()
+
   def testPrintMessageSetAsOneLine(self):
     message = unittest_mset_pb2.TestMessageSetContainer()
     ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
@@ -656,6 +706,48 @@ class Proto2Tests(TextFormatBase):
     self.assertEqual(23, message.message_set.Extensions[ext1].i)
     self.assertEqual('foo', message.message_set.Extensions[ext2].str)
 
+  def testParseMessageByFieldNumber(self):
+    message = unittest_pb2.TestAllTypes()
+    text = ('34: 1\n'
+            'repeated_uint64: 2\n')
+    text_format.Parse(text, message, allow_field_number=True)
+    self.assertEqual(1, message.repeated_uint64[0])
+    self.assertEqual(2, message.repeated_uint64[1])
+
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    text = ('1 {\n'
+            '  1545008 {\n'
+            '    15: 23\n'
+            '  }\n'
+            '  1547769 {\n'
+            '    25: \"foo\"\n'
+            '  }\n'
+            '}\n')
+    text_format.Parse(text, message, allow_field_number=True)
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    self.assertEqual(23, message.message_set.Extensions[ext1].i)
+    self.assertEqual('foo', message.message_set.Extensions[ext2].str)
+
+    # Can't parse field number without set allow_field_number=True.
+    message = unittest_pb2.TestAllTypes()
+    text = '34:1\n'
+    six.assertRaisesRegex(
+        self,
+        text_format.ParseError,
+        (r'1:1 : Message type "\w+.TestAllTypes" has no field named '
+         r'"34".'),
+        text_format.Parse, text, message)
+
+    # Can't parse if field number is not found.
+    text = '1234:1\n'
+    six.assertRaisesRegex(
+        self,
+        text_format.ParseError,
+        (r'1:1 : Message type "\w+.TestAllTypes" has no field named '
+         r'"1234".'),
+        text_format.Parse, text, message, allow_field_number=True)
+
   def testPrintAllExtensions(self):
     message = unittest_pb2.TestAllExtensions()
     test_util.SetAllExtensions(message)
@@ -696,6 +788,7 @@ class Proto2Tests(TextFormatBase):
     text = ('message_set {\n'
             '  [unknown_extension] {\n'
             '    i: 23\n'
+            '    bin: "\xe0"'
             '    [nested_unknown_ext]: {\n'
             '      i: 23\n'
             '      test: "test_string"\n'

+ 17 - 6
python/google/protobuf/internal/type_checkers.py

@@ -109,6 +109,16 @@ class TypeChecker(object):
     return proposed_value
 
 
+class TypeCheckerWithDefault(TypeChecker):
+
+  def __init__(self, default_value, *acceptable_types):
+    TypeChecker.__init__(self, acceptable_types)
+    self._default_value = default_value
+
+  def DefaultValue(self):
+    return self._default_value
+
+
 # IntValueChecker and its subclasses perform integer type-checks
 # and bounds-checks.
 class IntValueChecker(object):
@@ -212,12 +222,13 @@ _VALUE_CHECKERS = {
     _FieldDescriptor.CPPTYPE_INT64: Int64ValueChecker(),
     _FieldDescriptor.CPPTYPE_UINT32: Uint32ValueChecker(),
     _FieldDescriptor.CPPTYPE_UINT64: Uint64ValueChecker(),
-    _FieldDescriptor.CPPTYPE_DOUBLE: TypeChecker(
-        float, int, long),
-    _FieldDescriptor.CPPTYPE_FLOAT: TypeChecker(
-        float, int, long),
-    _FieldDescriptor.CPPTYPE_BOOL: TypeChecker(bool, int),
-    _FieldDescriptor.CPPTYPE_STRING: TypeChecker(bytes),
+    _FieldDescriptor.CPPTYPE_DOUBLE: TypeCheckerWithDefault(
+        0.0, float, int, long),
+    _FieldDescriptor.CPPTYPE_FLOAT: TypeCheckerWithDefault(
+        0.0, float, int, long),
+    _FieldDescriptor.CPPTYPE_BOOL: TypeCheckerWithDefault(
+        False, bool, int),
+    _FieldDescriptor.CPPTYPE_STRING: TypeCheckerWithDefault(b'', bytes),
     }
 
 

+ 20 - 0
python/google/protobuf/internal/unknown_fields_test.py

@@ -119,6 +119,26 @@ class UnknownFieldsTest(unittest.TestCase):
     message.ParseFromString(self.all_fields.SerializeToString())
     self.assertNotEqual(self.empty_message, message)
 
+  def testDiscardUnknownFields(self):
+    self.empty_message.DiscardUnknownFields()
+    self.assertEqual(b'', self.empty_message.SerializeToString())
+    # Test message field and repeated message field.
+    message = unittest_pb2.TestAllTypes()
+    other_message = unittest_pb2.TestAllTypes()
+    other_message.optional_string = 'discard'
+    message.optional_nested_message.ParseFromString(
+        other_message.SerializeToString())
+    message.repeated_nested_message.add().ParseFromString(
+        other_message.SerializeToString())
+    self.assertNotEqual(
+        b'', message.optional_nested_message.SerializeToString())
+    self.assertNotEqual(
+        b'', message.repeated_nested_message[0].SerializeToString())
+    message.DiscardUnknownFields()
+    self.assertEqual(b'', message.optional_nested_message.SerializeToString())
+    self.assertEqual(
+        b'', message.repeated_nested_message[0].SerializeToString())
+
 
 class UnknownFieldsAccessorsTest(unittest.TestCase):
 

+ 6 - 2
python/google/protobuf/internal/well_known_types.py

@@ -82,10 +82,14 @@ class Any(object):
     msg.ParseFromString(self.value)
     return True
 
+  def TypeName(self):
+    """Returns the protobuf type name of the inner message."""
+    # Only last part is to be used: b/25630112
+    return self.type_url.split('/')[-1]
+
   def Is(self, descriptor):
     """Checks if this Any represents the given protobuf type."""
-    # Only last part is to be used: b/25630112
-    return self.type_url.split('/')[-1] == descriptor.full_name
+    return self.TypeName() == descriptor.full_name
 
 
 class Timestamp(object):

+ 8 - 0
python/google/protobuf/internal/well_known_types_test.py

@@ -610,6 +610,14 @@ class AnyTest(unittest.TestCase):
       raise AttributeError('%s should not have Pack method.' %
                            msg_descriptor.full_name)
 
+  def testMessageName(self):
+    # Creates and sets message.
+    submessage = any_test_pb2.TestAny()
+    submessage.int_value = 12345
+    msg = any_pb2.Any()
+    msg.Pack(submessage)
+    self.assertEqual(msg.TypeName(), 'google.protobuf.internal.TestAny')
+
   def testPackWithCustomTypeUrl(self):
     submessage = any_test_pb2.TestAny()
     submessage.int_value = 12345

+ 3 - 0
python/google/protobuf/message.py

@@ -255,6 +255,9 @@ class Message(object):
   def ClearExtension(self, extension_handle):
     raise NotImplementedError
 
+  def DiscardUnknownFields(self):
+    raise NotImplementedError
+
   def ByteSize(self):
     """Returns the serialized size of this message.
     Recursively calls ByteSize() on all contained messages.

+ 6 - 5
python/google/protobuf/pyext/descriptor.cc

@@ -200,8 +200,8 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
   // read-only instance.
   const Message& options(descriptor->options());
   const Descriptor *message_type = options.GetDescriptor();
-  PyObject* message_class(cdescriptor_pool::GetMessageClass(
-      pool, message_type));
+  CMessageClass* message_class(
+      cdescriptor_pool::GetMessageClass(pool, message_type));
   if (message_class == NULL) {
     // The Options message was not found in the current DescriptorPool.
     // In this case, there cannot be extensions to these options, and we can
@@ -215,7 +215,8 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
                  message_type->full_name().c_str());
     return NULL;
   }
-  ScopedPyObjectPtr value(PyEval_CallObject(message_class, NULL));
+  ScopedPyObjectPtr value(
+      PyEval_CallObject(message_class->AsPyObject(), NULL));
   if (value == NULL) {
     return NULL;
   }
@@ -433,11 +434,11 @@ static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) {
   // which contains this descriptor.
   // This might not be the one you expect! For example the returned object does
   // not know about extensions defined in a custom pool.
-  PyObject* concrete_class(cdescriptor_pool::GetMessageClass(
+  CMessageClass* concrete_class(cdescriptor_pool::GetMessageClass(
       GetDescriptorPool_FromPool(_GetDescriptor(self)->file()->pool()),
       _GetDescriptor(self)));
   Py_XINCREF(concrete_class);
-  return concrete_class;
+  return concrete_class->AsPyObject();
 }
 
 static PyObject* GetFieldsByName(PyBaseDescriptor* self, void *closure) {

+ 4 - 4
python/google/protobuf/pyext/descriptor_pool.cc

@@ -190,8 +190,8 @@ PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) {
 
 // Add a message class to our database.
 int RegisterMessageClass(PyDescriptorPool* self,
-                         const Descriptor *message_descriptor,
-                         PyObject *message_class) {
+                         const Descriptor* message_descriptor,
+                         CMessageClass* message_class) {
   Py_INCREF(message_class);
   typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
   std::pair<iterator, bool> ret = self->classes_by_descriptor->insert(
@@ -205,8 +205,8 @@ int RegisterMessageClass(PyDescriptorPool* self,
 }
 
 // Retrieve the message class added to our database.
-PyObject *GetMessageClass(PyDescriptorPool* self,
-                          const Descriptor *message_descriptor) {
+CMessageClass* GetMessageClass(PyDescriptorPool* self,
+                               const Descriptor* message_descriptor) {
   typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
   iterator ret = self->classes_by_descriptor->find(message_descriptor);
   if (ret == self->classes_by_descriptor->end()) {

+ 7 - 4
python/google/protobuf/pyext/descriptor_pool.h

@@ -42,6 +42,9 @@ class MessageFactory;
 
 namespace python {
 
+// The (meta) type of all Messages classes.
+struct CMessageClass;
+
 // Wraps operations to the global DescriptorPool which contains information
 // about all messages and fields.
 //
@@ -78,7 +81,7 @@ typedef struct PyDescriptorPool {
   //
   // Descriptor pointers stored here are owned by the DescriptorPool above.
   // Python references to classes are owned by this PyDescriptorPool.
-  typedef hash_map<const Descriptor*, PyObject*> ClassesByMessageMap;
+  typedef hash_map<const Descriptor*, CMessageClass*> ClassesByMessageMap;
   ClassesByMessageMap* classes_by_descriptor;
 
   // Cache the options for any kind of descriptor.
@@ -101,14 +104,14 @@ const Descriptor* FindMessageTypeByName(PyDescriptorPool* self,
 // On error, returns -1 with a Python exception set.
 int RegisterMessageClass(PyDescriptorPool* self,
                          const Descriptor* message_descriptor,
-                         PyObject* message_class);
+                         CMessageClass* message_class);
 
 // Retrieves the Python class registered with the given message descriptor.
 //
 // Returns a *borrowed* reference if found, otherwise returns NULL with an
 // exception set.
-PyObject* GetMessageClass(PyDescriptorPool* self,
-                          const Descriptor* message_descriptor);
+CMessageClass* GetMessageClass(PyDescriptorPool* self,
+                               const Descriptor* message_descriptor);
 
 // The functions below are also exposed as methods of the DescriptorPool type.
 

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác