Browse Source

Versioning Java GeneratedMessage.

Starting from 3.0.0 release, generated Java code will subclass
GeneratedMessageV3 and when we need to make a change to the
interface between generated code and GeneratedMessageV3, we
will create another versioned GeneratedMessageV3_1 and so on.

Change-Id: I178c9671beb78ef33901a133caaa5c765433126e
Feng Xiao 9 năm trước cách đây
mục cha
commit
35271766fb

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

@@ -972,7 +972,7 @@ public class GeneratedMessageTest extends TestCase {
     TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
     TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
 
 
     TestAllTypes.Builder builder = (TestAllTypes.Builder)
     TestAllTypes.Builder builder = (TestAllTypes.Builder)
-        ((GeneratedMessage) TestAllTypes.getDefaultInstance()).
+        ((AbstractMessage) TestAllTypes.getDefaultInstance()).
             newBuilderForType(mockParent);
             newBuilderForType(mockParent);
     builder.setOptionalInt32(1);
     builder.setOptionalInt32(1);
     builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR);
     builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR);
@@ -1027,7 +1027,7 @@ public class GeneratedMessageTest extends TestCase {
     TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
     TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
 
 
     TestAllExtensions.Builder builder = (TestAllExtensions.Builder)
     TestAllExtensions.Builder builder = (TestAllExtensions.Builder)
-        ((GeneratedMessage) TestAllExtensions.getDefaultInstance()).
+        ((AbstractMessage) TestAllExtensions.getDefaultInstance()).
             newBuilderForType(mockParent);
             newBuilderForType(mockParent);
 
 
     builder.addExtension(UnittestProto.repeatedInt32Extension, 1);
     builder.addExtension(UnittestProto.repeatedInt32Extension, 1);

+ 0 - 190
java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java

@@ -1,190 +0,0 @@
-// 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 protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
-
-import junit.framework.TestCase;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Tests for {@link RepeatedFieldBuilder}. This tests basic functionality.
- * More extensive testing is provided via other tests that exercise the
- * builder.
- *
- * @author jonp@google.com (Jon Perlow)
- */
-public class RepeatedFieldBuilderTest extends TestCase {
-
-  public void testBasicUse() {
-    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
-    RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
-        TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
-    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
-    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
-    assertEquals(0, builder.getMessage(0).getOptionalInt32());
-    assertEquals(1, builder.getMessage(1).getOptionalInt32());
-
-    List<TestAllTypes> list = builder.build();
-    assertEquals(2, list.size());
-    assertEquals(0, list.get(0).getOptionalInt32());
-    assertEquals(1, list.get(1).getOptionalInt32());
-    assertIsUnmodifiable(list);
-
-    // Make sure it doesn't change.
-    List<TestAllTypes> list2 = builder.build();
-    assertSame(list, list2);
-    assertEquals(0, mockParent.getInvalidationCount());
-  }
-
-  public void testGoingBackAndForth() {
-    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
-    RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
-        TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
-    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
-    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
-    assertEquals(0, builder.getMessage(0).getOptionalInt32());
-    assertEquals(1, builder.getMessage(1).getOptionalInt32());
-
-    // Convert to list
-    List<TestAllTypes> list = builder.build();
-    assertEquals(2, list.size());
-    assertEquals(0, list.get(0).getOptionalInt32());
-    assertEquals(1, list.get(1).getOptionalInt32());
-    assertIsUnmodifiable(list);
-
-    // Update 0th item
-    assertEquals(0, mockParent.getInvalidationCount());
-    builder.getBuilder(0).setOptionalString("foo");
-    assertEquals(1, mockParent.getInvalidationCount());
-    list = builder.build();
-    assertEquals(2, list.size());
-    assertEquals(0, list.get(0).getOptionalInt32());
-      assertEquals("foo", list.get(0).getOptionalString());
-    assertEquals(1, list.get(1).getOptionalInt32());
-    assertIsUnmodifiable(list);
-    assertEquals(1, mockParent.getInvalidationCount());
-  }
-
-  public void testVariousMethods() {
-    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
-    RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
-        TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
-    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
-    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(2).build());
-    builder.addBuilder(0, TestAllTypes.getDefaultInstance())
-        .setOptionalInt32(0);
-    builder.addBuilder(TestAllTypes.getDefaultInstance()).setOptionalInt32(3);
-
-    assertEquals(0, builder.getMessage(0).getOptionalInt32());
-    assertEquals(1, builder.getMessage(1).getOptionalInt32());
-    assertEquals(2, builder.getMessage(2).getOptionalInt32());
-    assertEquals(3, builder.getMessage(3).getOptionalInt32());
-
-    assertEquals(0, mockParent.getInvalidationCount());
-    List<TestAllTypes> messages = builder.build();
-    assertEquals(4, messages.size());
-    assertSame(messages, builder.build()); // expect same list
-
-    // Remove a message.
-    builder.remove(2);
-    assertEquals(1, mockParent.getInvalidationCount());
-    assertEquals(3, builder.getCount());
-    assertEquals(0, builder.getMessage(0).getOptionalInt32());
-    assertEquals(1, builder.getMessage(1).getOptionalInt32());
-    assertEquals(3, builder.getMessage(2).getOptionalInt32());
-
-    // Remove a builder.
-    builder.remove(0);
-    assertEquals(1, mockParent.getInvalidationCount());
-    assertEquals(2, builder.getCount());
-    assertEquals(1, builder.getMessage(0).getOptionalInt32());
-    assertEquals(3, builder.getMessage(1).getOptionalInt32());
-
-    // Test clear.
-    builder.clear();
-    assertEquals(1, mockParent.getInvalidationCount());
-    assertEquals(0, builder.getCount());
-    assertTrue(builder.isEmpty());
-  }
-
-  public void testLists() {
-    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
-    RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
-        TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
-    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
-    builder.addMessage(0,
-        TestAllTypes.newBuilder().setOptionalInt32(0).build());
-    assertEquals(0, builder.getMessage(0).getOptionalInt32());
-    assertEquals(1, builder.getMessage(1).getOptionalInt32());
-
-    // Use list of builders.
-    List<TestAllTypes.Builder> builders = builder.getBuilderList();
-    assertEquals(0, builders.get(0).getOptionalInt32());
-    assertEquals(1, builders.get(1).getOptionalInt32());
-    builders.get(0).setOptionalInt32(10);
-    builders.get(1).setOptionalInt32(11);
-
-    // Use list of protos
-    List<TestAllTypes> protos = builder.getMessageList();
-    assertEquals(10, protos.get(0).getOptionalInt32());
-    assertEquals(11, protos.get(1).getOptionalInt32());
-
-    // Add an item to the builders and verify it's updated in both
-    builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(12).build());
-    assertEquals(3, builders.size());
-    assertEquals(3, protos.size());
-  }
-
-  private void assertIsUnmodifiable(List<?> list) {
-    if (list == Collections.emptyList()) {
-      // OKAY -- Need to check this b/c EmptyList allows you to call clear.
-    } else {
-      try {
-        list.clear();
-        fail("List wasn't immutable");
-      } catch (UnsupportedOperationException e) {
-        // good
-      }
-    }
-  }
-
-  private RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
-      TestAllTypesOrBuilder>
-      newRepeatedFieldBuilder(GeneratedMessage.BuilderParent parent) {
-    return new RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
-        TestAllTypesOrBuilder>(Collections.<TestAllTypes>emptyList(), false,
-        parent, false);
-  }
-}

+ 0 - 155
java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java

@@ -1,155 +0,0 @@
-// 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 protobuf_unittest.UnittestProto.TestAllTypes;
-import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
-
-import junit.framework.TestCase;
-
-/**
- * Tests for {@link SingleFieldBuilder}. This tests basic functionality.
- * More extensive testing is provided via other tests that exercise the
- * builder.
- *
- * @author jonp@google.com (Jon Perlow)
- */
-public class SingleFieldBuilderTest extends TestCase {
-
-  public void testBasicUseAndInvalidations() {
-    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
-    SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
-        TestAllTypesOrBuilder> builder =
-        new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
-            TestAllTypesOrBuilder>(
-            TestAllTypes.getDefaultInstance(),
-            mockParent,
-            false);
-    assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
-    assertEquals(TestAllTypes.getDefaultInstance(),
-        builder.getBuilder().buildPartial());
-    assertEquals(0, mockParent.getInvalidationCount());
-
-    builder.getBuilder().setOptionalInt32(10);
-    assertEquals(0, mockParent.getInvalidationCount());
-    TestAllTypes message = builder.build();
-    assertEquals(10, message.getOptionalInt32());
-
-    // Test that we receive invalidations now that build has been called.
-    assertEquals(0, mockParent.getInvalidationCount());
-    builder.getBuilder().setOptionalInt32(20);
-    assertEquals(1, mockParent.getInvalidationCount());
-
-    // Test that we don't keep getting invalidations on every change
-    builder.getBuilder().setOptionalInt32(30);
-    assertEquals(1, mockParent.getInvalidationCount());
-
-  }
-
-  public void testSetMessage() {
-    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
-    SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
-        TestAllTypesOrBuilder> builder =
-        new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
-            TestAllTypesOrBuilder>(
-            TestAllTypes.getDefaultInstance(),
-            mockParent,
-            false);
-    builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
-    assertEquals(0, builder.getMessage().getOptionalInt32());
-
-    // Update message using the builder
-    builder.getBuilder().setOptionalInt32(1);
-    assertEquals(0, mockParent.getInvalidationCount());
-    assertEquals(1, builder.getBuilder().getOptionalInt32());
-    assertEquals(1, builder.getMessage().getOptionalInt32());
-    builder.build();
-    builder.getBuilder().setOptionalInt32(2);
-    assertEquals(2, builder.getBuilder().getOptionalInt32());
-    assertEquals(2, builder.getMessage().getOptionalInt32());
-
-    // Make sure message stays cached
-    assertSame(builder.getMessage(), builder.getMessage());
-  }
-
-  public void testClear() {
-    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
-    SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
-        TestAllTypesOrBuilder> builder =
-        new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
-            TestAllTypesOrBuilder>(
-            TestAllTypes.getDefaultInstance(),
-            mockParent,
-            false);
-    builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
-    assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
-    builder.clear();
-    assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
-
-    builder.getBuilder().setOptionalInt32(1);
-    assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
-    builder.clear();
-    assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
-  }
-
-  public void testMerge() {
-    TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
-    SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
-        TestAllTypesOrBuilder> builder =
-        new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
-            TestAllTypesOrBuilder>(
-            TestAllTypes.getDefaultInstance(),
-            mockParent,
-            false);
-
-    // Merge into default field.
-    builder.mergeFrom(TestAllTypes.getDefaultInstance());
-    assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
-
-    // Merge into non-default field on existing builder.
-    builder.getBuilder().setOptionalInt32(2);
-    builder.mergeFrom(TestAllTypes.newBuilder()
-        .setOptionalDouble(4.0)
-        .buildPartial());
-    assertEquals(2, builder.getMessage().getOptionalInt32());
-    assertEquals(4.0, builder.getMessage().getOptionalDouble());
-
-    // Merge into non-default field on existing message
-    builder.setMessage(TestAllTypes.newBuilder()
-        .setOptionalInt32(10)
-        .buildPartial());
-    builder.mergeFrom(TestAllTypes.newBuilder()
-        .setOptionalDouble(5.0)
-        .buildPartial());
-    assertEquals(10, builder.getMessage().getOptionalInt32());
-    assertEquals(5.0, builder.getMessage().getOptionalDouble());
-  }
-}

+ 36 - 26
src/google/protobuf/compiler/java/java_message.cc

@@ -205,9 +205,10 @@ GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate) {
   } else {
   } else {
     vars["final"] = "";
     vars["final"] = "";
   }
   }
+  vars["ver"] = GeneratedCodeVersionSuffix();
   printer->Print(vars,
   printer->Print(vars,
     "$private$static $final$\n"
     "$private$static $final$\n"
-    "  com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+    "  com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
     "    internal_$identifier$_fieldAccessorTable;\n");
     "    internal_$identifier$_fieldAccessorTable;\n");
 
 
   // 6 bytes per field and oneof
   // 6 bytes per field and oneof
@@ -220,11 +221,11 @@ GenerateFieldAccessorTableInitializer(io::Printer* printer) {
   int bytecode_estimate = 10;
   int bytecode_estimate = 10;
   printer->Print(
   printer->Print(
     "internal_$identifier$_fieldAccessorTable = new\n"
     "internal_$identifier$_fieldAccessorTable = new\n"
-    "  com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n"
+    "  com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable(\n"
     "    internal_$identifier$_descriptor,\n"
     "    internal_$identifier$_descriptor,\n"
     "    new java.lang.String[] { ",
     "    new java.lang.String[] { ",
-    "identifier",
-    UniqueFileScopeIdentifier(descriptor_));
+    "identifier", UniqueFileScopeIdentifier(descriptor_),
+    "ver", GeneratedCodeVersionSuffix());
   for (int i = 0; i < descriptor_->field_count(); i++) {
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
     const FieldDescriptor* field = descriptor_->field(i);
     const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
     const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
@@ -254,11 +255,11 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
     printer->Print(
     printer->Print(
         "public interface $classname$OrBuilder$idend$ extends\n"
         "public interface $classname$OrBuilder$idend$ extends\n"
         "    $extra_interfaces$\n"
         "    $extra_interfaces$\n"
-        "    com.google.protobuf.GeneratedMessage.\n"
+        "    com.google.protobuf.GeneratedMessage$ver$.\n"
         "        ExtendableMessageOrBuilder<$classname$> {\n",
         "        ExtendableMessageOrBuilder<$classname$> {\n",
         "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
         "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
         "classname", descriptor_->name(),
         "classname", descriptor_->name(),
-        "idend", "");
+        "idend", "", "ver", GeneratedCodeVersionSuffix());
   } else {
   } else {
     printer->Print(
     printer->Print(
         "public interface $classname$OrBuilder$idend$ extends\n"
         "public interface $classname$OrBuilder$idend$ extends\n"
@@ -302,6 +303,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
   variables["static"] = is_own_file ? " " : " static ";
   variables["static"] = is_own_file ? " " : " static ";
   variables["classname"] = descriptor_->name();
   variables["classname"] = descriptor_->name();
   variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
   variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
+  variables["ver"] = GeneratedCodeVersionSuffix();
 
 
   WriteMessageDocComment(printer, descriptor_);
   WriteMessageDocComment(printer, descriptor_);
   MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
   MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
@@ -315,22 +317,25 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
     printer->Annotate("classname", descriptor_);
     printer->Annotate("classname", descriptor_);
     printer->Print(
     printer->Print(
         variables,
         variables,
-        "    com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
+        "    com.google.protobuf.GeneratedMessage$ver$.ExtendableMessage<\n"
         "      $classname$> implements\n"
         "      $classname$> implements\n"
         "    $extra_interfaces$\n"
         "    $extra_interfaces$\n"
         "    $classname$OrBuilder {\n");
         "    $classname$OrBuilder {\n");
     builder_type = strings::Substitute(
     builder_type = strings::Substitute(
-             "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>",
-             name_resolver_->GetImmutableClassName(descriptor_));
+        "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
+        name_resolver_->GetImmutableClassName(descriptor_),
+        GeneratedCodeVersionSuffix());
   } else {
   } else {
     printer->Print(variables,
     printer->Print(variables,
                    "public $static$final class $classname$ extends\n");
                    "public $static$final class $classname$ extends\n");
     printer->Annotate("classname", descriptor_);
     printer->Annotate("classname", descriptor_);
     printer->Print(variables,
     printer->Print(variables,
-      "    com.google.protobuf.GeneratedMessage implements\n"
+      "    com.google.protobuf.GeneratedMessage$ver$ implements\n"
       "    $extra_interfaces$\n"
       "    $extra_interfaces$\n"
       "    $classname$OrBuilder {\n");
       "    $classname$OrBuilder {\n");
-    builder_type = "com.google.protobuf.GeneratedMessage.Builder<?>";
+    builder_type = strings::Substitute(
+        "com.google.protobuf.GeneratedMessage$0.Builder<?>",
+        GeneratedCodeVersionSuffix());
   }
   }
   printer->Indent();
   printer->Indent();
   // Using builder_type, instead of Builder, prevents the Builder class from
   // Using builder_type, instead of Builder, prevents the Builder class from
@@ -581,16 +586,18 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
   if (descriptor_->extension_range_count() > 0) {
   if (descriptor_->extension_range_count() > 0) {
     if (descriptor_->options().message_set_wire_format()) {
     if (descriptor_->options().message_set_wire_format()) {
       printer->Print(
       printer->Print(
-        "com.google.protobuf.GeneratedMessage\n"
+        "com.google.protobuf.GeneratedMessage$ver$\n"
         "  .ExtendableMessage<$classname$>.ExtensionWriter\n"
         "  .ExtendableMessage<$classname$>.ExtensionWriter\n"
         "    extensionWriter = newMessageSetExtensionWriter();\n",
         "    extensionWriter = newMessageSetExtensionWriter();\n",
-        "classname", name_resolver_->GetImmutableClassName(descriptor_));
+        "classname", name_resolver_->GetImmutableClassName(descriptor_),
+        "ver", GeneratedCodeVersionSuffix());
     } else {
     } else {
       printer->Print(
       printer->Print(
-        "com.google.protobuf.GeneratedMessage\n"
+        "com.google.protobuf.GeneratedMessage$ver$\n"
         "  .ExtendableMessage<$classname$>.ExtensionWriter\n"
         "  .ExtendableMessage<$classname$>.ExtensionWriter\n"
         "    extensionWriter = newExtensionWriter();\n",
         "    extensionWriter = newExtensionWriter();\n",
-        "classname", name_resolver_->GetImmutableClassName(descriptor_));
+        "classname", name_resolver_->GetImmutableClassName(descriptor_),
+        "ver", GeneratedCodeVersionSuffix());
     }
     }
   }
   }
 
 
@@ -694,43 +701,44 @@ GenerateParseFromMethods(io::Printer* printer) {
     "}\n"
     "}\n"
     "public static $classname$ parseFrom(java.io.InputStream input)\n"
     "public static $classname$ parseFrom(java.io.InputStream input)\n"
     "    throws java.io.IOException {\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage\n"
+    "  return com.google.protobuf.GeneratedMessage$ver$\n"
     "      .parseWithIOException(PARSER, input);\n"
     "      .parseWithIOException(PARSER, input);\n"
     "}\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "public static $classname$ parseFrom(\n"
     "    java.io.InputStream input,\n"
     "    java.io.InputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage\n"
+    "  return com.google.protobuf.GeneratedMessage$ver$\n"
     "      .parseWithIOException(PARSER, input, extensionRegistry);\n"
     "      .parseWithIOException(PARSER, input, extensionRegistry);\n"
     "}\n"
     "}\n"
     "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
     "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
     "    throws java.io.IOException {\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage\n"
+    "  return com.google.protobuf.GeneratedMessage$ver$\n"
     "      .parseDelimitedWithIOException(PARSER, input);\n"
     "      .parseDelimitedWithIOException(PARSER, input);\n"
     "}\n"
     "}\n"
     "public static $classname$ parseDelimitedFrom(\n"
     "public static $classname$ parseDelimitedFrom(\n"
     "    java.io.InputStream input,\n"
     "    java.io.InputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage\n"
+    "  return com.google.protobuf.GeneratedMessage$ver$\n"
     "      .parseDelimitedWithIOException(PARSER, input, extensionRegistry);\n"
     "      .parseDelimitedWithIOException(PARSER, input, extensionRegistry);\n"
     "}\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.CodedInputStream input)\n"
     "    com.google.protobuf.CodedInputStream input)\n"
     "    throws java.io.IOException {\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage\n"
+    "  return com.google.protobuf.GeneratedMessage$ver$\n"
     "      .parseWithIOException(PARSER, input);\n"
     "      .parseWithIOException(PARSER, input);\n"
     "}\n"
     "}\n"
     "public static $classname$ parseFrom(\n"
     "public static $classname$ parseFrom(\n"
     "    com.google.protobuf.CodedInputStream input,\n"
     "    com.google.protobuf.CodedInputStream input,\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
     "    throws java.io.IOException {\n"
     "    throws java.io.IOException {\n"
-    "  return com.google.protobuf.GeneratedMessage\n"
+    "  return com.google.protobuf.GeneratedMessage$ver$\n"
     "      .parseWithIOException(PARSER, input, extensionRegistry);\n"
     "      .parseWithIOException(PARSER, input, extensionRegistry);\n"
     "}\n"
     "}\n"
     "\n",
     "\n",
-    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+    "classname", name_resolver_->GetImmutableClassName(descriptor_),
+    "ver", GeneratedCodeVersionSuffix());
 }
 }
 
 
 void ImmutableMessageGenerator::GenerateSerializeOneField(
 void ImmutableMessageGenerator::GenerateSerializeOneField(
@@ -769,10 +777,11 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
   printer->Print(
   printer->Print(
     "@java.lang.Override\n"
     "@java.lang.Override\n"
     "protected Builder newBuilderForType(\n"
     "protected Builder newBuilderForType(\n"
-    "    com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
+    "    com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n"
     "  Builder builder = new Builder(parent);\n"
     "  Builder builder = new Builder(parent);\n"
     "  return builder;\n"
     "  return builder;\n"
-    "}\n");
+    "}\n",
+    "ver", GeneratedCodeVersionSuffix());
 
 
   MessageBuilderGenerator builderGenerator(descriptor_, context_);
   MessageBuilderGenerator builderGenerator(descriptor_, context_);
   builderGenerator.Generate(printer);
   builderGenerator.Generate(printer);
@@ -826,7 +835,7 @@ GenerateDescriptorMethods(io::Printer* printer) {
         "}\n");
         "}\n");
   }
   }
   printer->Print(
   printer->Print(
-    "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+    "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
     "    internalGetFieldAccessorTable() {\n"
     "    internalGetFieldAccessorTable() {\n"
     "  return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
     "  return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
     "      .ensureFieldAccessorsInitialized(\n"
     "      .ensureFieldAccessorsInitialized(\n"
@@ -835,7 +844,8 @@ GenerateDescriptorMethods(io::Printer* printer) {
     "\n",
     "\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_),
     "classname", name_resolver_->GetImmutableClassName(descriptor_),
     "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
     "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
-    "identifier", UniqueFileScopeIdentifier(descriptor_));
+    "identifier", UniqueFileScopeIdentifier(descriptor_),
+    "ver", GeneratedCodeVersionSuffix());
 }
 }
 
 
 // ===================================================================
 // ===================================================================

+ 15 - 9
src/google/protobuf/compiler/java/java_message_builder.cc

@@ -94,20 +94,22 @@ Generate(io::Printer* printer) {
   if (descriptor_->extension_range_count() > 0) {
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
     printer->Print(
       "public static final class Builder extends\n"
       "public static final class Builder extends\n"
-      "    com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
+      "    com.google.protobuf.GeneratedMessage$ver$.ExtendableBuilder<\n"
       "      $classname$, Builder> implements\n"
       "      $classname$, Builder> implements\n"
       "    $extra_interfaces$\n"
       "    $extra_interfaces$\n"
       "    $classname$OrBuilder {\n",
       "    $classname$OrBuilder {\n",
       "classname", name_resolver_->GetImmutableClassName(descriptor_),
       "classname", name_resolver_->GetImmutableClassName(descriptor_),
-      "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
+      "extra_interfaces", ExtraBuilderInterfaces(descriptor_),
+      "ver", GeneratedCodeVersionSuffix());
   } else {
   } else {
     printer->Print(
     printer->Print(
       "public static final class Builder extends\n"
       "public static final class Builder extends\n"
-      "    com.google.protobuf.GeneratedMessage.Builder<Builder> implements\n"
+      "    com.google.protobuf.GeneratedMessage$ver$.Builder<Builder> implements\n"
       "    $extra_interfaces$\n"
       "    $extra_interfaces$\n"
       "    $classname$OrBuilder {\n",
       "    $classname$OrBuilder {\n",
       "classname", name_resolver_->GetImmutableClassName(descriptor_),
       "classname", name_resolver_->GetImmutableClassName(descriptor_),
-      "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
+      "extra_interfaces", ExtraBuilderInterfaces(descriptor_),
+      "ver", GeneratedCodeVersionSuffix());
   }
   }
   printer->Indent();
   printer->Indent();
 
 
@@ -268,7 +270,7 @@ GenerateDescriptorMethods(io::Printer* printer) {
         "}\n");
         "}\n");
   }
   }
   printer->Print(
   printer->Print(
-    "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+    "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
     "    internalGetFieldAccessorTable() {\n"
     "    internalGetFieldAccessorTable() {\n"
     "  return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
     "  return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
     "      .ensureFieldAccessorsInitialized(\n"
     "      .ensureFieldAccessorsInitialized(\n"
@@ -277,7 +279,8 @@ GenerateDescriptorMethods(io::Printer* printer) {
     "\n",
     "\n",
     "classname", name_resolver_->GetImmutableClassName(descriptor_),
     "classname", name_resolver_->GetImmutableClassName(descriptor_),
     "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
     "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
-    "identifier", UniqueFileScopeIdentifier(descriptor_));
+    "identifier", UniqueFileScopeIdentifier(descriptor_),
+    "ver", GeneratedCodeVersionSuffix());
 }
 }
 
 
 // ===================================================================
 // ===================================================================
@@ -294,15 +297,18 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
 
 
   printer->Print(
   printer->Print(
     "private Builder(\n"
     "private Builder(\n"
-    "    com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
+    "    com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n"
     "  super(parent);\n"
     "  super(parent);\n"
     "  maybeForceBuilderInitialization();\n"
     "  maybeForceBuilderInitialization();\n"
     "}\n",
     "}\n",
-    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+    "classname", name_resolver_->GetImmutableClassName(descriptor_),
+    "ver", GeneratedCodeVersionSuffix());
 
 
   printer->Print(
   printer->Print(
     "private void maybeForceBuilderInitialization() {\n"
     "private void maybeForceBuilderInitialization() {\n"
-    "  if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n");
+    "  if (com.google.protobuf.GeneratedMessage$ver$\n"
+    "          .alwaysUseFieldBuilders) {\n",
+    "ver", GeneratedCodeVersionSuffix());
 
 
   printer->Indent();
   printer->Indent();
   printer->Indent();
   printer->Indent();

+ 1 - 1
src/google/protobuf/compiler/java/java_message_field.cc

@@ -1203,7 +1203,7 @@ GenerateMergingCode(io::Printer* printer) const {
     "    $name$_ = other.$name$_;\n"
     "    $name$_ = other.$name$_;\n"
     "    $clear_mutable_bit_builder$;\n"
     "    $clear_mutable_bit_builder$;\n"
     "    $name$Builder_ = \n"
     "    $name$Builder_ = \n"
-    "      com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?\n"
+    "      com.google.protobuf.GeneratedMessage$ver$.alwaysUseFieldBuilders ?\n"
     "         get$capitalized_name$FieldBuilder() : null;\n"
     "         get$capitalized_name$FieldBuilder() : null;\n"
     "  } else {\n"
     "  } else {\n"
     "    $name$Builder_.addAllMessages(other.$name$_);\n"
     "    $name$Builder_.addAllMessages(other.$name$_);\n"

+ 4 - 2
src/google/protobuf/compiler/java/java_string_field.cc

@@ -79,9 +79,11 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
       "    throw new NullPointerException();\n"
       "    throw new NullPointerException();\n"
       "  }\n";
       "  }\n";
   (*variables)["writeString"] =
   (*variables)["writeString"] =
-      "com.google.protobuf.GeneratedMessage.writeString";
+      "com.google.protobuf.GeneratedMessage" + GeneratedCodeVersionSuffix() +
+      ".writeString";
   (*variables)["computeStringSize"] =
   (*variables)["computeStringSize"] =
-      "com.google.protobuf.GeneratedMessage.computeStringSize";
+      "com.google.protobuf.GeneratedMessage" + GeneratedCodeVersionSuffix() +
+      ".computeStringSize";
 
 
   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
   // by the proto compiler
   // by the proto compiler