avro-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ieme...@apache.org
Subject [avro] branch master updated: AVRO-2344: Handle timestamp logical types corresponding to proto Timestamp
Date Fri, 19 Apr 2019 12:05:45 GMT
This is an automated email from the ASF dual-hosted git repository.

iemejia pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/master by this push:
     new da50f7f  AVRO-2344: Handle timestamp logical types corresponding to proto Timestamp
da50f7f is described below

commit da50f7f205a7c3f8f69096fd27652d69066224e8
Author: syucream <syucream@mercari.com>
AuthorDate: Tue Mar 12 19:23:33 2019 +0900

    AVRO-2344: Handle timestamp logical types corresponding to proto Timestamp
---
 .../org/apache/avro/protobuf/ProtoConversions.java | 141 ++++++++++
 .../org/apache/avro/protobuf/ProtobufData.java     |  28 ++
 .../apache/avro/protobuf/TestProtoConversions.java | 170 ++++++++++++
 .../org/apache/avro/protobuf/TestProtobuf.java     |  20 ++
 .../org/apache/avro/protobuf/multiplefiles/A.java  |   2 +-
 .../apache/avro/protobuf/multiplefiles/Foo.java    | 273 ++++++++++++++++---
 .../avro/protobuf/multiplefiles/FooOrBuilder.java  |  29 +-
 .../org/apache/avro/protobuf/multiplefiles/M.java  |  27 +-
 .../avro/protobuf/multiplefiles/MOrBuilder.java    |   2 +-
 .../protobuf/multiplefiles/TestMultipleFiles.java  |  39 +--
 .../java/org/apache/avro/protobuf/noopt/Test.java  | 293 ++++++++++++++++++++-
 lang/java/protobuf/src/test/protobuf/test.proto    |   4 +
 .../src/test/protobuf/test_multiple_files.proto    |   4 +
 13 files changed, 936 insertions(+), 96 deletions(-)

diff --git a/lang/java/protobuf/src/main/java/org/apache/avro/protobuf/ProtoConversions.java b/lang/java/protobuf/src/main/java/org/apache/avro/protobuf/ProtoConversions.java
new file mode 100644
index 0000000..1e7ad79
--- /dev/null
+++ b/lang/java/protobuf/src/main/java/org/apache/avro/protobuf/ProtoConversions.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.avro.protobuf;
+
+import com.google.protobuf.Timestamp;
+import org.apache.avro.Conversion;
+import org.apache.avro.LogicalType;
+import org.apache.avro.LogicalTypes;
+import org.apache.avro.Schema;
+
+public class ProtoConversions {
+
+  private static final int THOUSAND = 1000;
+  private static final int MILLION = 1000000;
+
+  // second value must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z
+  // inclusive.
+  static final long SECONDS_LOWERLIMIT = -62135596800L;
+  static final long SECONDS_UPPERLIMIT = 253402300799L;
+
+  // nano value Must be from 0 to 999,999,999 inclusive.
+  private static final int NANOSECONDS_LOWERLIMIT = 0;
+  private static final int NANOSECONDS_UPPERLIMIT = 999999999;
+
+  // timestamp precise of conversion from long
+  private enum TimestampPrecise {
+    Millis, Micros
+  };
+
+  public static class TimestampMillisConversion extends Conversion<Timestamp> {
+    @Override
+    public Class<Timestamp> getConvertedType() {
+      return Timestamp.class;
+    }
+
+    @Override
+    public String getLogicalTypeName() {
+      return "timestamp-millis";
+    }
+
+    @Override
+    public Timestamp fromLong(Long millisFromEpoch, Schema schema, LogicalType type) throws IllegalArgumentException {
+      return ProtoConversions.fromLong(millisFromEpoch, TimestampPrecise.Millis);
+    }
+
+    @Override
+    public Long toLong(Timestamp value, Schema schema, LogicalType type) {
+      return ProtoConversions.toLong(value, TimestampPrecise.Millis);
+    }
+
+    @Override
+    public Schema getRecommendedSchema() {
+      return LogicalTypes.timestampMillis().addToSchema(Schema.create(Schema.Type.LONG));
+    }
+  }
+
+  public static class TimestampMicrosConversion extends Conversion<Timestamp> {
+    @Override
+    public Class<Timestamp> getConvertedType() {
+      return Timestamp.class;
+    }
+
+    @Override
+    public String getLogicalTypeName() {
+      return "timestamp-micros";
+    }
+
+    @Override
+    public Timestamp fromLong(Long microsFromEpoch, Schema schema, LogicalType type) throws IllegalArgumentException {
+      return ProtoConversions.fromLong(microsFromEpoch, TimestampPrecise.Micros);
+    }
+
+    @Override
+    public Long toLong(Timestamp value, Schema schema, LogicalType type) {
+      return ProtoConversions.toLong(value, TimestampPrecise.Micros);
+    }
+
+    @Override
+    public Schema getRecommendedSchema() {
+      return LogicalTypes.timestampMicros().addToSchema(Schema.create(Schema.Type.LONG));
+    }
+  }
+
+  private static long toLong(Timestamp value, TimestampPrecise precise) {
+    long rv = 0L;
+
+    switch (precise) {
+    case Millis:
+      rv = value.getSeconds() * THOUSAND + value.getNanos() / MILLION;
+      break;
+    case Micros:
+      rv = value.getSeconds() * MILLION + value.getNanos() / THOUSAND;
+      break;
+    }
+
+    return rv;
+  }
+
+  private static Timestamp fromLong(Long elapsedSinceEpoch, TimestampPrecise precise) throws IllegalArgumentException {
+    long seconds = 0L;
+    int nanos = 0;
+
+    switch (precise) {
+    case Millis:
+      seconds = Math.floorDiv(elapsedSinceEpoch, THOUSAND);
+      nanos = (int) Math.floorMod(elapsedSinceEpoch, THOUSAND) * MILLION;
+      break;
+    case Micros:
+      seconds = Math.floorDiv(elapsedSinceEpoch, MILLION);
+      nanos = (int) Math.floorMod(elapsedSinceEpoch, MILLION) * THOUSAND;
+      break;
+    }
+
+    if (seconds < SECONDS_LOWERLIMIT || seconds > SECONDS_UPPERLIMIT) {
+      throw new IllegalArgumentException("given seconds is out of range");
+    }
+
+    if (nanos < NANOSECONDS_LOWERLIMIT || nanos > NANOSECONDS_UPPERLIMIT) {
+      // NOTE here is unexpected cases because exceeded part is
+      // moved to seconds by floor methods
+      throw new IllegalArgumentException("given nanos is out of range");
+    }
+
+    return Timestamp.newBuilder().setSeconds(seconds).setNanos(nanos).build();
+  }
+}
diff --git a/lang/java/protobuf/src/main/java/org/apache/avro/protobuf/ProtobufData.java b/lang/java/protobuf/src/main/java/org/apache/avro/protobuf/ProtobufData.java
index f01f7fa..53806d5 100644
--- a/lang/java/protobuf/src/main/java/org/apache/avro/protobuf/ProtobufData.java
+++ b/lang/java/protobuf/src/main/java/org/apache/avro/protobuf/ProtobufData.java
@@ -27,6 +27,7 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.io.IOException;
 import java.io.File;
 
+import org.apache.avro.Conversion;
 import org.apache.avro.Schema;
 import org.apache.avro.Schema.Field;
 import org.apache.avro.generic.GenericData;
@@ -45,6 +46,7 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor;
 import com.google.protobuf.Descriptors.FileDescriptor;
 import com.google.protobuf.DescriptorProtos.FileOptions;
 
+import org.apache.avro.util.ClassUtils;
 import org.apache.avro.util.internal.Accessor;
 import com.fasterxml.jackson.core.JsonFactory;
 import com.fasterxml.jackson.databind.JsonNode;
@@ -198,6 +200,14 @@ public class ProtobufData extends GenericData {
     if (seen.containsKey(descriptor)) // stop recursion
       return seen.get(descriptor);
     boolean first = seen.isEmpty();
+
+    Conversion conversion = getConversionByDescriptor(descriptor);
+    if (conversion != null) {
+      Schema converted = conversion.getRecommendedSchema();
+      seen.put(descriptor, converted);
+      return converted;
+    }
+
     try {
       Schema result = Schema.createRecord(descriptor.getName(), null,
           getNamespace(descriptor.getFile(), descriptor.getContainingType()), false);
@@ -367,4 +377,22 @@ public class ProtobufData extends GenericData {
 
   }
 
+  /**
+   * Get Conversion from protobuf descriptor via protobuf classname.
+   *
+   * @param descriptor protobuf descriptor
+   * @return Conversion | null
+   */
+  private Conversion getConversionByDescriptor(Descriptor descriptor) {
+    String namespace = getNamespace(descriptor.getFile(), descriptor.getContainingType());
+    String name = descriptor.getName();
+    String dot = namespace.endsWith("$") ? "" : "."; // back-compatibly handle $
+
+    try {
+      Class clazz = ClassUtils.forName(getClassLoader(), namespace + dot + name);
+      return getConversionByClass(clazz);
+    } catch (ClassNotFoundException e) {
+      return null;
+    }
+  }
 }
diff --git a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/TestProtoConversions.java b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/TestProtoConversions.java
new file mode 100644
index 0000000..56afd08
--- /dev/null
+++ b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/TestProtoConversions.java
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.avro.protobuf;
+
+import com.google.protobuf.Timestamp;
+import org.apache.avro.Conversion;
+import org.apache.avro.LogicalTypes;
+import org.apache.avro.Schema;
+import org.apache.avro.protobuf.ProtoConversions.*;
+import org.apache.avro.reflect.ReflectData;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+
+public class TestProtoConversions {
+
+  private static Schema TIMESTAMP_MILLIS_SCHEMA;
+  private static Schema TIMESTAMP_MICROS_SCHEMA;
+
+  private static Calendar Jan_2_1900_3_4_5_678 = Calendar.getInstance();
+  private static Calendar May_28_2015_21_46_53_221 = Calendar.getInstance();
+
+  static {
+    May_28_2015_21_46_53_221.setTimeZone(TimeZone.getTimeZone("UTC"));
+    May_28_2015_21_46_53_221.set(2015, Calendar.MAY, 28, 21, 46, 53);
+    May_28_2015_21_46_53_221.set(Calendar.MILLISECOND, 221);
+
+    Jan_2_1900_3_4_5_678.setTimeZone(TimeZone.getTimeZone("UTC"));
+    Jan_2_1900_3_4_5_678.set(1900, Calendar.JANUARY, 2, 3, 4, 5);
+    Jan_2_1900_3_4_5_678.set(Calendar.MILLISECOND, 678);
+  }
+
+  @BeforeClass
+  public static void createSchemas() {
+    TestProtoConversions.TIMESTAMP_MILLIS_SCHEMA = LogicalTypes.timestampMillis()
+        .addToSchema(Schema.create(Schema.Type.LONG));
+    TestProtoConversions.TIMESTAMP_MICROS_SCHEMA = LogicalTypes.timestampMicros()
+        .addToSchema(Schema.create(Schema.Type.LONG));
+  }
+
+  @Test
+  public void testTimestampMillisConversion() throws Exception {
+    TimestampMillisConversion conversion = new TimestampMillisConversion();
+    Timestamp May_28_2015_21_46_53_221_ts = Timestamp.newBuilder().setSeconds(1432849613L).setNanos(221000000).build();
+    Timestamp Jan_2_1900_3_4_5_678_ts = Timestamp.newBuilder().setSeconds(-2208891355L).setNanos(678000000).build();
+
+    long instant = May_28_2015_21_46_53_221.getTimeInMillis();
+    Timestamp tsFromInstant = conversion.fromLong(instant, TIMESTAMP_MILLIS_SCHEMA, LogicalTypes.timestampMillis());
+    long roundTrip = conversion.toLong(tsFromInstant, TIMESTAMP_MILLIS_SCHEMA, LogicalTypes.timestampMillis());
+
+    Assert.assertEquals("Round-trip conversion should work", instant, roundTrip);
+    Assert.assertEquals("Known timestamp should be correct", May_28_2015_21_46_53_221_ts,
+        conversion.fromLong(instant, TIMESTAMP_MILLIS_SCHEMA, LogicalTypes.timestampMillis()));
+    Assert.assertEquals("Known timestamp should be correct", instant,
+        (long) conversion.toLong(May_28_2015_21_46_53_221_ts, TIMESTAMP_MILLIS_SCHEMA, LogicalTypes.timestampMillis()));
+
+    instant = Jan_2_1900_3_4_5_678.getTimeInMillis();
+    tsFromInstant = conversion.fromLong(instant, TIMESTAMP_MILLIS_SCHEMA, LogicalTypes.timestampMillis());
+    roundTrip = conversion.toLong(tsFromInstant, TIMESTAMP_MILLIS_SCHEMA, LogicalTypes.timestampMillis());
+
+    Assert.assertEquals("Round-trip conversion should work", instant, roundTrip);
+    Assert.assertEquals("Known timestamp should be correct", Jan_2_1900_3_4_5_678_ts,
+        conversion.fromLong(instant, TIMESTAMP_MILLIS_SCHEMA, LogicalTypes.timestampMillis()));
+    Assert.assertEquals("Known timestamp should be correct", instant,
+        (long) conversion.toLong(Jan_2_1900_3_4_5_678_ts, TIMESTAMP_MILLIS_SCHEMA, LogicalTypes.timestampMillis()));
+  }
+
+  @Test
+  public void testTimestampMicrosConversion() {
+    TimestampMicrosConversion conversion = new TimestampMicrosConversion();
+    Timestamp May_28_2015_21_46_53_221_843_ts = Timestamp.newBuilder().setSeconds(1432849613L).setNanos(221843000)
+        .build();
+    Timestamp Jan_2_1900_3_4_5_678_901_ts = Timestamp.newBuilder().setSeconds(-2208891355L).setNanos(678901000).build();
+
+    long instant = May_28_2015_21_46_53_221.getTimeInMillis() * 1000 + 843;
+    Timestamp tsFromInstant = conversion.fromLong(instant, TIMESTAMP_MICROS_SCHEMA, LogicalTypes.timestampMicros());
+    long roundTrip = conversion.toLong(tsFromInstant, TIMESTAMP_MICROS_SCHEMA, LogicalTypes.timestampMicros());
+
+    Assert.assertEquals("Round-trip conversion should work", instant, roundTrip);
+    Assert.assertEquals("Known timestamp should be correct", May_28_2015_21_46_53_221_843_ts,
+        conversion.fromLong(instant, TIMESTAMP_MICROS_SCHEMA, LogicalTypes.timestampMicros()));
+    Assert.assertEquals("Known timestamp should be correct", instant, (long) conversion
+        .toLong(May_28_2015_21_46_53_221_843_ts, TIMESTAMP_MICROS_SCHEMA, LogicalTypes.timestampMicros()));
+
+    instant = Jan_2_1900_3_4_5_678.getTimeInMillis() * 1000 + 901;
+    tsFromInstant = conversion.fromLong(instant, TIMESTAMP_MICROS_SCHEMA, LogicalTypes.timestampMicros());
+    roundTrip = conversion.toLong(tsFromInstant, TIMESTAMP_MICROS_SCHEMA, LogicalTypes.timestampMicros());
+
+    Assert.assertEquals("Round-trip conversion should work", instant, roundTrip);
+    Assert.assertEquals("Known timestamp should be correct", Jan_2_1900_3_4_5_678_901_ts,
+        conversion.fromLong(instant, TIMESTAMP_MICROS_SCHEMA, LogicalTypes.timestampMicros()));
+    Assert.assertEquals("Known timestamp should be correct", instant,
+        (long) conversion.toLong(Jan_2_1900_3_4_5_678_901_ts, TIMESTAMP_MICROS_SCHEMA, LogicalTypes.timestampMicros()));
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testTimestampMillisConversionSecondsLowerLimit() throws Exception {
+    TimestampMillisConversion conversion = new TimestampMillisConversion();
+    long exceeded = (ProtoConversions.SECONDS_LOWERLIMIT - 1) * 1000;
+    conversion.fromLong(exceeded, TIMESTAMP_MILLIS_SCHEMA, LogicalTypes.timestampMillis());
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testTimestampMillisConversionSecondsUpperLimit() throws Exception {
+    TimestampMillisConversion conversion = new TimestampMillisConversion();
+    long exceeded = (ProtoConversions.SECONDS_UPPERLIMIT + 1) * 1000;
+    conversion.fromLong(exceeded, TIMESTAMP_MILLIS_SCHEMA, LogicalTypes.timestampMillis());
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testTimestampMicrosConversionSecondsLowerLimit() throws Exception {
+    TimestampMicrosConversion conversion = new TimestampMicrosConversion();
+    long exceeded = (ProtoConversions.SECONDS_LOWERLIMIT - 1) * 1000000;
+    conversion.fromLong(exceeded, TIMESTAMP_MICROS_SCHEMA, LogicalTypes.timestampMicros());
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testTimestampMicrosConversionSecondsUpperLimit() throws Exception {
+    TimestampMicrosConversion conversion = new TimestampMicrosConversion();
+    long exceeded = (ProtoConversions.SECONDS_UPPERLIMIT + 1) * 1000000;
+    conversion.fromLong(exceeded, TIMESTAMP_MICROS_SCHEMA, LogicalTypes.timestampMicros());
+  }
+
+  /*
+   * model.addLogicalTypeConversion(new ProtoConversions.TimeMicrosConversion());
+   * model.addLogicalTypeConversion(new
+   * ProtoConversions.TimestampMicrosConversion());
+   */
+  @Test
+  public void testDynamicSchemaWithDateTimeConversion() throws ClassNotFoundException {
+    Schema schema = getReflectedSchemaByName("com.google.protobuf.Timestamp", new TimestampMillisConversion());
+    Assert.assertEquals("Reflected schema should be logicalType timestampMillis", TIMESTAMP_MILLIS_SCHEMA, schema);
+  }
+
+  @Test
+  public void testDynamicSchemaWithDateTimeMicrosConversion() throws ClassNotFoundException {
+    Schema schema = getReflectedSchemaByName("com.google.protobuf.Timestamp", new TimestampMicrosConversion());
+    Assert.assertEquals("Reflected schema should be logicalType timestampMicros", TIMESTAMP_MICROS_SCHEMA, schema);
+  }
+
+  private Schema getReflectedSchemaByName(String className, Conversion<?> conversion) throws ClassNotFoundException {
+    // one argument: a fully qualified class name
+    Class<?> cls = Class.forName(className);
+
+    // get the reflected schema for the given class
+    ReflectData model = new ReflectData();
+    model.addLogicalTypeConversion(conversion);
+    return model.getSchema(cls);
+  }
+
+}
diff --git a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/TestProtobuf.java b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/TestProtobuf.java
index f749026..7e419c2 100644
--- a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/TestProtobuf.java
+++ b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/TestProtobuf.java
@@ -28,6 +28,7 @@ import org.apache.avro.specific.SpecificData;
 
 import org.junit.Test;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 
 import com.google.protobuf.ByteString;
 
@@ -65,6 +66,9 @@ public class TestProtobuf {
     builder = Foo.newBuilder(fooInArray);
     builder.addFooArray(fooInArray);
 
+    com.google.protobuf.Timestamp ts = com.google.protobuf.Timestamp.newBuilder().setSeconds(1L).setNanos(2).build();
+    builder.setTimestamp(ts);
+
     builder = Foo.newBuilder(fooInner);
     builder.setFoo(fooInner);
     Foo foo = builder.build();
@@ -103,4 +107,20 @@ public class TestProtobuf {
     Schema nSchema = ProtobufData.get().getSchema(org.apache.avro.protobuf.multiplefiles.M.N.class);
     assertEquals(org.apache.avro.protobuf.multiplefiles.M.class.getName(), nSchema.getNamespace());
   }
+
+  @Test
+  public void testGetNonRepeatedSchemaWithLogicalType() throws Exception {
+    ProtoConversions.TimestampMillisConversion conversion = new ProtoConversions.TimestampMillisConversion();
+
+    // Don't convert to logical type if conversion isn't set
+    ProtobufData instance1 = new ProtobufData();
+    Schema s1 = instance1.getSchema(com.google.protobuf.Timestamp.class);
+    assertNotEquals(conversion.getRecommendedSchema(), s1);
+
+    // Convert to logical type if conversion is set
+    ProtobufData instance2 = new ProtobufData();
+    instance2.addLogicalTypeConversion(conversion);
+    Schema s2 = instance2.getSchema(com.google.protobuf.Timestamp.class);
+    assertEquals(conversion.getRecommendedSchema(), s2);
+  }
 }
diff --git a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/A.java b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/A.java
index 948916b..20633d5 100644
--- a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/A.java
+++ b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/A.java
@@ -1,5 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: lang/java/protobuf/src/test/protobuf/test_multiple_files.proto
+// source: src/test/protobuf/test_multiple_files.proto
 
 package org.apache.avro.protobuf.multiplefiles;
 
diff --git a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/Foo.java b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/Foo.java
index c876a23..5840150 100644
--- a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/Foo.java
+++ b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/Foo.java
@@ -1,5 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: lang/java/protobuf/src/test/protobuf/test_multiple_files.proto
+// source: src/test/protobuf/test_multiple_files.proto
 
 package org.apache.avro.protobuf.multiplefiles;
 
@@ -59,6 +59,12 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
         case 0:
           done = true;
           break;
+        default: {
+          if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) {
+            done = true;
+          }
+          break;
+        }
         case 8: {
           bitField0_ |= 0x00000001;
           int32_ = input.readInt32();
@@ -137,7 +143,6 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
         }
         case 128: {
           int rawValue = input.readEnum();
-          @SuppressWarnings("deprecation")
           org.apache.avro.protobuf.multiplefiles.A value = org.apache.avro.protobuf.multiplefiles.A.valueOf(rawValue);
           if (value == null) {
             unknownFields.mergeVarintField(16, rawValue);
@@ -183,7 +188,6 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
         }
         case 152: {
           int rawValue = input.readEnum();
-          @SuppressWarnings("deprecation")
           org.apache.avro.protobuf.multiplefiles.A value = org.apache.avro.protobuf.multiplefiles.A.valueOf(rawValue);
           if (value == null) {
             unknownFields.mergeVarintField(19, rawValue);
@@ -201,7 +205,6 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
           int oldLimit = input.pushLimit(length);
           while (input.getBytesUntilLimit() > 0) {
             int rawValue = input.readEnum();
-            @SuppressWarnings("deprecation")
             org.apache.avro.protobuf.multiplefiles.A value = org.apache.avro.protobuf.multiplefiles.A.valueOf(rawValue);
             if (value == null) {
               unknownFields.mergeVarintField(19, rawValue);
@@ -224,10 +227,17 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
           fooArray_.add(input.readMessage(org.apache.avro.protobuf.multiplefiles.Foo.PARSER, extensionRegistry));
           break;
         }
-        default: {
-          if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) {
-            done = true;
+        case 170: {
+          com.google.protobuf.Timestamp.Builder subBuilder = null;
+          if (((bitField0_ & 0x00020000) == 0x00020000)) {
+            subBuilder = timestamp_.toBuilder();
           }
+          timestamp_ = input.readMessage(com.google.protobuf.Timestamp.parser(), extensionRegistry);
+          if (subBuilder != null) {
+            subBuilder.mergeFrom(timestamp_);
+            timestamp_ = subBuilder.buildPartial();
+          }
+          bitField0_ |= 0x00020000;
           break;
         }
         }
@@ -255,7 +265,6 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
     return org.apache.avro.protobuf.multiplefiles.TestMultipleFiles.internal_static_org_apache_avro_protobuf_multiplefiles_Foo_descriptor;
   }
 
-  @java.lang.Override
   protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() {
     return org.apache.avro.protobuf.multiplefiles.TestMultipleFiles.internal_static_org_apache_avro_protobuf_multiplefiles_Foo_fieldAccessorTable
         .ensureFieldAccessorsInitialized(org.apache.avro.protobuf.multiplefiles.Foo.class,
@@ -564,7 +573,6 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
    * <code>optional .org.apache.avro.protobuf.multiplefiles.A enum = 16 [default = Z];</code>
    */
   public org.apache.avro.protobuf.multiplefiles.A getEnum() {
-    @SuppressWarnings("deprecation")
     org.apache.avro.protobuf.multiplefiles.A result = org.apache.avro.protobuf.multiplefiles.A.valueOf(enum_);
     return result == null ? org.apache.avro.protobuf.multiplefiles.A.Z : result;
   }
@@ -647,7 +655,6 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
   private java.util.List<java.lang.Integer> syms_;
   private static final com.google.protobuf.Internal.ListAdapter.Converter<java.lang.Integer, org.apache.avro.protobuf.multiplefiles.A> syms_converter_ = new com.google.protobuf.Internal.ListAdapter.Converter<java.lang.Integer, org.apache.avro.protobuf.multiplefiles.A>() {
     public org.apache.avro.protobuf.multiplefiles.A convert(java.lang.Integer from) {
-      @SuppressWarnings("deprecation")
       org.apache.avro.protobuf.multiplefiles.A result = org.apache.avro.protobuf.multiplefiles.A.valueOf(from);
       return result == null ? org.apache.avro.protobuf.multiplefiles.A.X : result;
     }
@@ -711,9 +718,44 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
     return foo_ == null ? org.apache.avro.protobuf.multiplefiles.Foo.getDefaultInstance() : foo_;
   }
 
+  public static final int TIMESTAMP_FIELD_NUMBER = 21;
+  private com.google.protobuf.Timestamp timestamp_;
+
+  /**
+   * <pre>
+   * a predefined message type
+   * </pre>
+   *
+   * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+   */
+  public boolean hasTimestamp() {
+    return ((bitField0_ & 0x00020000) == 0x00020000);
+  }
+
+  /**
+   * <pre>
+   * a predefined message type
+   * </pre>
+   *
+   * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+   */
+  public com.google.protobuf.Timestamp getTimestamp() {
+    return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_;
+  }
+
+  /**
+   * <pre>
+   * a predefined message type
+   * </pre>
+   *
+   * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+   */
+  public com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder() {
+    return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_;
+  }
+
   private byte memoizedIsInitialized = -1;
 
-  @java.lang.Override
   public final boolean isInitialized() {
     byte isInitialized = memoizedIsInitialized;
     if (isInitialized == 1)
@@ -741,7 +783,6 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
     return true;
   }
 
-  @java.lang.Override
   public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
     if (((bitField0_ & 0x00000001) == 0x00000001)) {
       output.writeInt32(1, int32_);
@@ -803,10 +844,12 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
     for (int i = 0; i < fooArray_.size(); i++) {
       output.writeMessage(20, fooArray_.get(i));
     }
+    if (((bitField0_ & 0x00020000) == 0x00020000)) {
+      output.writeMessage(21, getTimestamp());
+    }
     unknownFields.writeTo(output);
   }
 
-  @java.lang.Override
   public int getSerializedSize() {
     int size = memoizedSize;
     if (size != -1)
@@ -883,6 +926,9 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
     for (int i = 0; i < fooArray_.size(); i++) {
       size += com.google.protobuf.CodedOutputStream.computeMessageSize(20, fooArray_.get(i));
     }
+    if (((bitField0_ & 0x00020000) == 0x00020000)) {
+      size += com.google.protobuf.CodedOutputStream.computeMessageSize(21, getTimestamp());
+    }
     size += unknownFields.getSerializedSize();
     memoizedSize = size;
     return size;
@@ -972,6 +1018,10 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
     if (hasFoo()) {
       result = result && getFoo().equals(other.getFoo());
     }
+    result = result && (hasTimestamp() == other.hasTimestamp());
+    if (hasTimestamp()) {
+      result = result && getTimestamp().equals(other.getTimestamp());
+    }
     result = result && unknownFields.equals(other.unknownFields);
     return result;
   }
@@ -1063,6 +1113,10 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
       hash = (37 * hash) + FOO_FIELD_NUMBER;
       hash = (53 * hash) + getFoo().hashCode();
     }
+    if (hasTimestamp()) {
+      hash = (37 * hash) + TIMESTAMP_FIELD_NUMBER;
+      hash = (53 * hash) + getTimestamp().hashCode();
+    }
     hash = (29 * hash) + unknownFields.hashCode();
     memoizedHashCode = hash;
     return hash;
@@ -1131,7 +1185,6 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
     return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input, extensionRegistry);
   }
 
-  @java.lang.Override
   public Builder newBuilderForType() {
     return newBuilder();
   }
@@ -1144,7 +1197,6 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
     return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
   }
 
-  @java.lang.Override
   public Builder toBuilder() {
     return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this);
   }
@@ -1165,7 +1217,6 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
       return org.apache.avro.protobuf.multiplefiles.TestMultipleFiles.internal_static_org_apache_avro_protobuf_multiplefiles_Foo_descriptor;
     }
 
-    @java.lang.Override
     protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() {
       return org.apache.avro.protobuf.multiplefiles.TestMultipleFiles.internal_static_org_apache_avro_protobuf_multiplefiles_Foo_fieldAccessorTable
           .ensureFieldAccessorsInitialized(org.apache.avro.protobuf.multiplefiles.Foo.class,
@@ -1186,10 +1237,10 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
       if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) {
         getFooArrayFieldBuilder();
         getFooFieldBuilder();
+        getTimestampFieldBuilder();
       }
     }
 
-    @java.lang.Override
     public Builder clear() {
       super.clear();
       int32_ = 0;
@@ -1240,20 +1291,23 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
         fooBuilder_.clear();
       }
       bitField0_ = (bitField0_ & ~0x00080000);
+      if (timestampBuilder_ == null) {
+        timestamp_ = null;
+      } else {
+        timestampBuilder_.clear();
+      }
+      bitField0_ = (bitField0_ & ~0x00100000);
       return this;
     }
 
-    @java.lang.Override
     public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
       return org.apache.avro.protobuf.multiplefiles.TestMultipleFiles.internal_static_org_apache_avro_protobuf_multiplefiles_Foo_descriptor;
     }
 
-    @java.lang.Override
     public org.apache.avro.protobuf.multiplefiles.Foo getDefaultInstanceForType() {
       return org.apache.avro.protobuf.multiplefiles.Foo.getDefaultInstance();
     }
 
-    @java.lang.Override
     public org.apache.avro.protobuf.multiplefiles.Foo build() {
       org.apache.avro.protobuf.multiplefiles.Foo result = buildPartial();
       if (!result.isInitialized()) {
@@ -1262,7 +1316,6 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
       return result;
     }
 
-    @java.lang.Override
     public org.apache.avro.protobuf.multiplefiles.Foo buildPartial() {
       org.apache.avro.protobuf.multiplefiles.Foo result = new org.apache.avro.protobuf.multiplefiles.Foo(this);
       int from_bitField0_ = bitField0_;
@@ -1358,43 +1411,44 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
       } else {
         result.foo_ = fooBuilder_.build();
       }
+      if (((from_bitField0_ & 0x00100000) == 0x00100000)) {
+        to_bitField0_ |= 0x00020000;
+      }
+      if (timestampBuilder_ == null) {
+        result.timestamp_ = timestamp_;
+      } else {
+        result.timestamp_ = timestampBuilder_.build();
+      }
       result.bitField0_ = to_bitField0_;
       onBuilt();
       return result;
     }
 
-    @java.lang.Override
     public Builder clone() {
       return (Builder) super.clone();
     }
 
-    @java.lang.Override
     public Builder setField(com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
       return (Builder) super.setField(field, value);
     }
 
-    @java.lang.Override
     public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) {
       return (Builder) super.clearField(field);
     }
 
-    @java.lang.Override
     public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) {
       return (Builder) super.clearOneof(oneof);
     }
 
-    @java.lang.Override
     public Builder setRepeatedField(com.google.protobuf.Descriptors.FieldDescriptor field, int index,
         java.lang.Object value) {
       return (Builder) super.setRepeatedField(field, index, value);
     }
 
-    @java.lang.Override
     public Builder addRepeatedField(com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
       return (Builder) super.addRepeatedField(field, value);
     }
 
-    @java.lang.Override
     public Builder mergeFrom(com.google.protobuf.Message other) {
       if (other instanceof org.apache.avro.protobuf.multiplefiles.Foo) {
         return mergeFrom((org.apache.avro.protobuf.multiplefiles.Foo) other);
@@ -1505,12 +1559,14 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
       if (other.hasFoo()) {
         mergeFoo(other.getFoo());
       }
+      if (other.hasTimestamp()) {
+        mergeTimestamp(other.getTimestamp());
+      }
       this.mergeUnknownFields(other.unknownFields);
       onChanged();
       return this;
     }
 
-    @java.lang.Override
     public final boolean isInitialized() {
       if (!hasInt32()) {
         return false;
@@ -1528,7 +1584,6 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
       return true;
     }
 
-    @java.lang.Override
     public Builder mergeFrom(com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException {
       org.apache.avro.protobuf.multiplefiles.Foo parsedMessage = null;
@@ -2159,7 +2214,6 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
      * <code>optional .org.apache.avro.protobuf.multiplefiles.A enum = 16 [default = Z];</code>
      */
     public org.apache.avro.protobuf.multiplefiles.A getEnum() {
-      @SuppressWarnings("deprecation")
       org.apache.avro.protobuf.multiplefiles.A result = org.apache.avro.protobuf.multiplefiles.A.valueOf(enum_);
       return result == null ? org.apache.avro.protobuf.multiplefiles.A.Z : result;
     }
@@ -2756,12 +2810,163 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
       return fooBuilder_;
     }
 
-    @java.lang.Override
+    private com.google.protobuf.Timestamp timestamp_ = null;
+    private com.google.protobuf.SingleFieldBuilderV3<com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> timestampBuilder_;
+
+    /**
+     * <pre>
+     * a predefined message type
+     * </pre>
+     *
+     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+     */
+    public boolean hasTimestamp() {
+      return ((bitField0_ & 0x00100000) == 0x00100000);
+    }
+
+    /**
+     * <pre>
+     * a predefined message type
+     * </pre>
+     *
+     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+     */
+    public com.google.protobuf.Timestamp getTimestamp() {
+      if (timestampBuilder_ == null) {
+        return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_;
+      } else {
+        return timestampBuilder_.getMessage();
+      }
+    }
+
+    /**
+     * <pre>
+     * a predefined message type
+     * </pre>
+     *
+     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+     */
+    public Builder setTimestamp(com.google.protobuf.Timestamp value) {
+      if (timestampBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        timestamp_ = value;
+        onChanged();
+      } else {
+        timestampBuilder_.setMessage(value);
+      }
+      bitField0_ |= 0x00100000;
+      return this;
+    }
+
+    /**
+     * <pre>
+     * a predefined message type
+     * </pre>
+     *
+     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+     */
+    public Builder setTimestamp(com.google.protobuf.Timestamp.Builder builderForValue) {
+      if (timestampBuilder_ == null) {
+        timestamp_ = builderForValue.build();
+        onChanged();
+      } else {
+        timestampBuilder_.setMessage(builderForValue.build());
+      }
+      bitField0_ |= 0x00100000;
+      return this;
+    }
+
+    /**
+     * <pre>
+     * a predefined message type
+     * </pre>
+     *
+     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+     */
+    public Builder mergeTimestamp(com.google.protobuf.Timestamp value) {
+      if (timestampBuilder_ == null) {
+        if (((bitField0_ & 0x00100000) == 0x00100000) && timestamp_ != null
+            && timestamp_ != com.google.protobuf.Timestamp.getDefaultInstance()) {
+          timestamp_ = com.google.protobuf.Timestamp.newBuilder(timestamp_).mergeFrom(value).buildPartial();
+        } else {
+          timestamp_ = value;
+        }
+        onChanged();
+      } else {
+        timestampBuilder_.mergeFrom(value);
+      }
+      bitField0_ |= 0x00100000;
+      return this;
+    }
+
+    /**
+     * <pre>
+     * a predefined message type
+     * </pre>
+     *
+     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+     */
+    public Builder clearTimestamp() {
+      if (timestampBuilder_ == null) {
+        timestamp_ = null;
+        onChanged();
+      } else {
+        timestampBuilder_.clear();
+      }
+      bitField0_ = (bitField0_ & ~0x00100000);
+      return this;
+    }
+
+    /**
+     * <pre>
+     * a predefined message type
+     * </pre>
+     *
+     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+     */
+    public com.google.protobuf.Timestamp.Builder getTimestampBuilder() {
+      bitField0_ |= 0x00100000;
+      onChanged();
+      return getTimestampFieldBuilder().getBuilder();
+    }
+
+    /**
+     * <pre>
+     * a predefined message type
+     * </pre>
+     *
+     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+     */
+    public com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder() {
+      if (timestampBuilder_ != null) {
+        return timestampBuilder_.getMessageOrBuilder();
+      } else {
+        return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_;
+      }
+    }
+
+    /**
+     * <pre>
+     * a predefined message type
+     * </pre>
+     *
+     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> getTimestampFieldBuilder() {
+      if (timestampBuilder_ == null) {
+        timestampBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder>(
+            getTimestamp(), getParentForChildren(), isClean());
+        timestamp_ = null;
+      }
+      return timestampBuilder_;
+    }
+
     public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) {
       return super.setUnknownFields(unknownFields);
     }
 
-    @java.lang.Override
     public final Builder mergeUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) {
       return super.mergeUnknownFields(unknownFields);
     }
@@ -2781,7 +2986,6 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
 
   @java.lang.Deprecated
   public static final com.google.protobuf.Parser<Foo> PARSER = new com.google.protobuf.AbstractParser<Foo>() {
-    @java.lang.Override
     public Foo parsePartialFrom(com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -2798,7 +3002,6 @@ public final class Foo extends com.google.protobuf.GeneratedMessageV3 implements
     return PARSER;
   }
 
-  @java.lang.Override
   public org.apache.avro.protobuf.multiplefiles.Foo getDefaultInstanceForType() {
     return DEFAULT_INSTANCE;
   }
diff --git a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/FooOrBuilder.java b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/FooOrBuilder.java
index a6678aa..66c8692 100644
--- a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/FooOrBuilder.java
+++ b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/FooOrBuilder.java
@@ -1,5 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: lang/java/protobuf/src/test/protobuf/test_multiple_files.proto
+// source: src/test/protobuf/test_multiple_files.proto
 
 package org.apache.avro.protobuf.multiplefiles;
 
@@ -273,4 +273,31 @@ public interface FooOrBuilder extends
    * <code>optional .org.apache.avro.protobuf.multiplefiles.Foo foo = 18;</code>
    */
   org.apache.avro.protobuf.multiplefiles.FooOrBuilder getFooOrBuilder();
+
+  /**
+   * <pre>
+   * a predefined message type
+   * </pre>
+   *
+   * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+   */
+  boolean hasTimestamp();
+
+  /**
+   * <pre>
+   * a predefined message type
+   * </pre>
+   *
+   * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+   */
+  com.google.protobuf.Timestamp getTimestamp();
+
+  /**
+   * <pre>
+   * a predefined message type
+   * </pre>
+   *
+   * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+   */
+  com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder();
 }
diff --git a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/M.java b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/M.java
index 130ed15..4f2ae42 100644
--- a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/M.java
+++ b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/M.java
@@ -1,5 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: lang/java/protobuf/src/test/protobuf/test_multiple_files.proto
+// source: src/test/protobuf/test_multiple_files.proto
 
 package org.apache.avro.protobuf.multiplefiles;
 
@@ -65,7 +65,6 @@ public final class M extends com.google.protobuf.GeneratedMessageV3 implements
     return org.apache.avro.protobuf.multiplefiles.TestMultipleFiles.internal_static_org_apache_avro_protobuf_multiplefiles_M_descriptor;
   }
 
-  @java.lang.Override
   protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() {
     return org.apache.avro.protobuf.multiplefiles.TestMultipleFiles.internal_static_org_apache_avro_protobuf_multiplefiles_M_fieldAccessorTable
         .ensureFieldAccessorsInitialized(org.apache.avro.protobuf.multiplefiles.M.class,
@@ -149,7 +148,6 @@ public final class M extends com.google.protobuf.GeneratedMessageV3 implements
 
   private byte memoizedIsInitialized = -1;
 
-  @java.lang.Override
   public final boolean isInitialized() {
     byte isInitialized = memoizedIsInitialized;
     if (isInitialized == 1)
@@ -161,12 +159,10 @@ public final class M extends com.google.protobuf.GeneratedMessageV3 implements
     return true;
   }
 
-  @java.lang.Override
   public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
     unknownFields.writeTo(output);
   }
 
-  @java.lang.Override
   public int getSerializedSize() {
     int size = memoizedSize;
     if (size != -1)
@@ -268,7 +264,6 @@ public final class M extends com.google.protobuf.GeneratedMessageV3 implements
     return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input, extensionRegistry);
   }
 
-  @java.lang.Override
   public Builder newBuilderForType() {
     return newBuilder();
   }
@@ -281,7 +276,6 @@ public final class M extends com.google.protobuf.GeneratedMessageV3 implements
     return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
   }
 
-  @java.lang.Override
   public Builder toBuilder() {
     return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this);
   }
@@ -306,7 +300,6 @@ public final class M extends com.google.protobuf.GeneratedMessageV3 implements
       return org.apache.avro.protobuf.multiplefiles.TestMultipleFiles.internal_static_org_apache_avro_protobuf_multiplefiles_M_descriptor;
     }
 
-    @java.lang.Override
     protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() {
       return org.apache.avro.protobuf.multiplefiles.TestMultipleFiles.internal_static_org_apache_avro_protobuf_multiplefiles_M_fieldAccessorTable
           .ensureFieldAccessorsInitialized(org.apache.avro.protobuf.multiplefiles.M.class,
@@ -328,23 +321,19 @@ public final class M extends com.google.protobuf.GeneratedMessageV3 implements
       }
     }
 
-    @java.lang.Override
     public Builder clear() {
       super.clear();
       return this;
     }
 
-    @java.lang.Override
     public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
       return org.apache.avro.protobuf.multiplefiles.TestMultipleFiles.internal_static_org_apache_avro_protobuf_multiplefiles_M_descriptor;
     }
 
-    @java.lang.Override
     public org.apache.avro.protobuf.multiplefiles.M getDefaultInstanceForType() {
       return org.apache.avro.protobuf.multiplefiles.M.getDefaultInstance();
     }
 
-    @java.lang.Override
     public org.apache.avro.protobuf.multiplefiles.M build() {
       org.apache.avro.protobuf.multiplefiles.M result = buildPartial();
       if (!result.isInitialized()) {
@@ -353,45 +342,37 @@ public final class M extends com.google.protobuf.GeneratedMessageV3 implements
       return result;
     }
 
-    @java.lang.Override
     public org.apache.avro.protobuf.multiplefiles.M buildPartial() {
       org.apache.avro.protobuf.multiplefiles.M result = new org.apache.avro.protobuf.multiplefiles.M(this);
       onBuilt();
       return result;
     }
 
-    @java.lang.Override
     public Builder clone() {
       return (Builder) super.clone();
     }
 
-    @java.lang.Override
     public Builder setField(com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
       return (Builder) super.setField(field, value);
     }
 
-    @java.lang.Override
     public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) {
       return (Builder) super.clearField(field);
     }
 
-    @java.lang.Override
     public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) {
       return (Builder) super.clearOneof(oneof);
     }
 
-    @java.lang.Override
     public Builder setRepeatedField(com.google.protobuf.Descriptors.FieldDescriptor field, int index,
         java.lang.Object value) {
       return (Builder) super.setRepeatedField(field, index, value);
     }
 
-    @java.lang.Override
     public Builder addRepeatedField(com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
       return (Builder) super.addRepeatedField(field, value);
     }
 
-    @java.lang.Override
     public Builder mergeFrom(com.google.protobuf.Message other) {
       if (other instanceof org.apache.avro.protobuf.multiplefiles.M) {
         return mergeFrom((org.apache.avro.protobuf.multiplefiles.M) other);
@@ -409,12 +390,10 @@ public final class M extends com.google.protobuf.GeneratedMessageV3 implements
       return this;
     }
 
-    @java.lang.Override
     public final boolean isInitialized() {
       return true;
     }
 
-    @java.lang.Override
     public Builder mergeFrom(com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException {
       org.apache.avro.protobuf.multiplefiles.M parsedMessage = null;
@@ -431,12 +410,10 @@ public final class M extends com.google.protobuf.GeneratedMessageV3 implements
       return this;
     }
 
-    @java.lang.Override
     public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) {
       return super.setUnknownFields(unknownFields);
     }
 
-    @java.lang.Override
     public final Builder mergeUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) {
       return super.mergeUnknownFields(unknownFields);
     }
@@ -456,7 +433,6 @@ public final class M extends com.google.protobuf.GeneratedMessageV3 implements
 
   @java.lang.Deprecated
   public static final com.google.protobuf.Parser<M> PARSER = new com.google.protobuf.AbstractParser<M>() {
-    @java.lang.Override
     public M parsePartialFrom(com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -473,7 +449,6 @@ public final class M extends com.google.protobuf.GeneratedMessageV3 implements
     return PARSER;
   }
 
-  @java.lang.Override
   public org.apache.avro.protobuf.multiplefiles.M getDefaultInstanceForType() {
     return DEFAULT_INSTANCE;
   }
diff --git a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/MOrBuilder.java b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/MOrBuilder.java
index 4981185..9694ec2 100644
--- a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/MOrBuilder.java
+++ b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/MOrBuilder.java
@@ -1,5 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: lang/java/protobuf/src/test/protobuf/test_multiple_files.proto
+// source: src/test/protobuf/test_multiple_files.proto
 
 package org.apache.avro.protobuf.multiplefiles;
 
diff --git a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/TestMultipleFiles.java b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/TestMultipleFiles.java
index 63e4d3c..879d34f 100644
--- a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/TestMultipleFiles.java
+++ b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/multiplefiles/TestMultipleFiles.java
@@ -1,5 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: lang/java/protobuf/src/test/protobuf/test_multiple_files.proto
+// source: src/test/protobuf/test_multiple_files.proto
 
 package org.apache.avro.protobuf.multiplefiles;
 
@@ -25,21 +25,22 @@ public final class TestMultipleFiles {
 
   private static com.google.protobuf.Descriptors.FileDescriptor descriptor;
   static {
-    java.lang.String[] descriptorData = { "\n>lang/java/protobuf/src/test/protobuf/t"
-        + "est_multiple_files.proto\022&org.apache.avr" + "o.protobuf.multiplefiles\"\365\003\n\003Foo\022\r\n\005int3"
-        + "2\030\001 \002(\005\022\r\n\005int64\030\002 \001(\003\022\016\n\006uint32\030\003 \001(\r\022\016"
-        + "\n\006uint64\030\004 \001(\004\022\016\n\006sint32\030\005 \001(\021\022\016\n\006sint64"
-        + "\030\006 \001(\022\022\017\n\007fixed32\030\007 \001(\007\022\017\n\007fixed64\030\010 \001(\006"
-        + "\022\020\n\010sfixed32\030\t \001(\017\022\020\n\010sfixed64\030\n \001(\020\022\r\n\005"
-        + "float\030\013 \001(\002\022\016\n\006double\030\014 \001(\001\022\014\n\004bool\030\r \001("
-        + "\010\022\016\n\006string\030\016 \001(\t\022\r\n\005bytes\030\017 \001(\014\022:\n\004enum"
-        + "\030\020 \001(\0162).org.apache.avro.protobuf.multip"
-        + "lefiles.A:\001Z\022\020\n\010intArray\030\021 \003(\005\022=\n\010fooArr"
-        + "ay\030\024 \003(\0132+.org.apache.avro.protobuf.mult"
-        + "iplefiles.Foo\0227\n\004syms\030\023 \003(\0162).org.apache"
-        + ".avro.protobuf.multiplefiles.A\0228\n\003foo\030\022 " + "\001(\0132+.org.apache.avro.protobuf.multiplef"
-        + "iles.Foo\"\017\n\001M\"\n\n\001N\022\005\n\001A\020\001*\030\n\001A\022\005\n\001X\020\001\022\005\n"
-        + "\001Y\020\002\022\005\n\001Z\020\003B\002P\001" };
+    java.lang.String[] descriptorData = { "\n+src/test/protobuf/test_multiple_files."
+        + "proto\022&org.apache.avro.protobuf.multiple" + "files\032\037google/protobuf/timestamp.proto\"\244"
+        + "\004\n\003Foo\022\r\n\005int32\030\001 \002(\005\022\r\n\005int64\030\002 \001(\003\022\016\n\006"
+        + "uint32\030\003 \001(\r\022\016\n\006uint64\030\004 \001(\004\022\016\n\006sint32\030\005"
+        + " \001(\021\022\016\n\006sint64\030\006 \001(\022\022\017\n\007fixed32\030\007 \001(\007\022\017\n"
+        + "\007fixed64\030\010 \001(\006\022\020\n\010sfixed32\030\t \001(\017\022\020\n\010sfix"
+        + "ed64\030\n \001(\020\022\r\n\005float\030\013 \001(\002\022\016\n\006double\030\014 \001("
+        + "\001\022\014\n\004bool\030\r \001(\010\022\016\n\006string\030\016 \001(\t\022\r\n\005bytes"
+        + "\030\017 \001(\014\022:\n\004enum\030\020 \001(\0162).org.apache.avro.p"
+        + "rotobuf.multiplefiles.A:\001Z\022\020\n\010intArray\030\021"
+        + " \003(\005\022=\n\010fooArray\030\024 \003(\0132+.org.apache.avro"
+        + ".protobuf.multiplefiles.Foo\0227\n\004syms\030\023 \003(" + "\0162).org.apache.avro.protobuf.multiplefil"
+        + "es.A\0228\n\003foo\030\022 \001(\0132+.org.apache.avro.prot"
+        + "obuf.multiplefiles.Foo\022-\n\ttimestamp\030\025 \001("
+        + "\0132\032.google.protobuf.Timestamp\"\017\n\001M\"\n\n\001N\022"
+        + "\005\n\001A\020\001*\030\n\001A\022\005\n\001X\020\001\022\005\n\001Y\020\002\022\005\n\001Z\020\003B\002P\001" };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
       public com.google.protobuf.ExtensionRegistry assignDescriptors(
           com.google.protobuf.Descriptors.FileDescriptor root) {
@@ -48,16 +49,18 @@ public final class TestMultipleFiles {
       }
     };
     com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(descriptorData,
-        new com.google.protobuf.Descriptors.FileDescriptor[] {}, assigner);
+        new com.google.protobuf.Descriptors.FileDescriptor[] { com.google.protobuf.TimestampProto.getDescriptor(), },
+        assigner);
     internal_static_org_apache_avro_protobuf_multiplefiles_Foo_descriptor = getDescriptor().getMessageTypes().get(0);
     internal_static_org_apache_avro_protobuf_multiplefiles_Foo_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         internal_static_org_apache_avro_protobuf_multiplefiles_Foo_descriptor,
         new java.lang.String[] { "Int32", "Int64", "Uint32", "Uint64", "Sint32", "Sint64", "Fixed32", "Fixed64",
             "Sfixed32", "Sfixed64", "Float", "Double", "Bool", "String", "Bytes", "Enum", "IntArray", "FooArray",
-            "Syms", "Foo", });
+            "Syms", "Foo", "Timestamp", });
     internal_static_org_apache_avro_protobuf_multiplefiles_M_descriptor = getDescriptor().getMessageTypes().get(1);
     internal_static_org_apache_avro_protobuf_multiplefiles_M_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         internal_static_org_apache_avro_protobuf_multiplefiles_M_descriptor, new java.lang.String[] {});
+    com.google.protobuf.TimestampProto.getDescriptor();
   }
 
   // @@protoc_insertion_point(outer_class_scope)
diff --git a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/noopt/Test.java b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/noopt/Test.java
index 3fed419..8255719 100644
--- a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/noopt/Test.java
+++ b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/noopt/Test.java
@@ -383,6 +383,33 @@ public final class Test {
      * <code>optional .org.apache.avro.protobuf.noopt.Foo foo = 18;</code>
      */
     org.apache.avro.protobuf.noopt.Test.FooOrBuilder getFooOrBuilder();
+
+    /**
+     * <pre>
+     * a predefined message type
+     * </pre>
+     *
+     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+     */
+    boolean hasTimestamp();
+
+    /**
+     * <pre>
+     * a predefined message type
+     * </pre>
+     *
+     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+     */
+    com.google.protobuf.Timestamp getTimestamp();
+
+    /**
+     * <pre>
+     * a predefined message type
+     * </pre>
+     *
+     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+     */
+    com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder();
   }
 
   /**
@@ -609,6 +636,19 @@ public final class Test {
             fooArray_.add(input.readMessage(org.apache.avro.protobuf.noopt.Test.Foo.PARSER, extensionRegistry));
             break;
           }
+          case 170: {
+            com.google.protobuf.Timestamp.Builder subBuilder = null;
+            if (((bitField0_ & 0x00020000) == 0x00020000)) {
+              subBuilder = timestamp_.toBuilder();
+            }
+            timestamp_ = input.readMessage(com.google.protobuf.Timestamp.parser(), extensionRegistry);
+            if (subBuilder != null) {
+              subBuilder.mergeFrom(timestamp_);
+              timestamp_ = subBuilder.buildPartial();
+            }
+            bitField0_ |= 0x00020000;
+            break;
+          }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -1087,6 +1127,42 @@ public final class Test {
       return foo_ == null ? org.apache.avro.protobuf.noopt.Test.Foo.getDefaultInstance() : foo_;
     }
 
+    public static final int TIMESTAMP_FIELD_NUMBER = 21;
+    private com.google.protobuf.Timestamp timestamp_;
+
+    /**
+     * <pre>
+     * a predefined message type
+     * </pre>
+     *
+     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+     */
+    public boolean hasTimestamp() {
+      return ((bitField0_ & 0x00020000) == 0x00020000);
+    }
+
+    /**
+     * <pre>
+     * a predefined message type
+     * </pre>
+     *
+     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+     */
+    public com.google.protobuf.Timestamp getTimestamp() {
+      return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_;
+    }
+
+    /**
+     * <pre>
+     * a predefined message type
+     * </pre>
+     *
+     * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+     */
+    public com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder() {
+      return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_;
+    }
+
     private byte memoizedIsInitialized = -1;
 
     public final boolean isInitialized() {
@@ -1177,6 +1253,9 @@ public final class Test {
       for (int i = 0; i < fooArray_.size(); i++) {
         output.writeMessage(20, fooArray_.get(i));
       }
+      if (((bitField0_ & 0x00020000) == 0x00020000)) {
+        output.writeMessage(21, getTimestamp());
+      }
       unknownFields.writeTo(output);
     }
 
@@ -1256,6 +1335,9 @@ public final class Test {
       for (int i = 0; i < fooArray_.size(); i++) {
         size += com.google.protobuf.CodedOutputStream.computeMessageSize(20, fooArray_.get(i));
       }
+      if (((bitField0_ & 0x00020000) == 0x00020000)) {
+        size += com.google.protobuf.CodedOutputStream.computeMessageSize(21, getTimestamp());
+      }
       size += unknownFields.getSerializedSize();
       memoizedSize = size;
       return size;
@@ -1345,6 +1427,10 @@ public final class Test {
       if (hasFoo()) {
         result = result && getFoo().equals(other.getFoo());
       }
+      result = result && (hasTimestamp() == other.hasTimestamp());
+      if (hasTimestamp()) {
+        result = result && getTimestamp().equals(other.getTimestamp());
+      }
       result = result && unknownFields.equals(other.unknownFields);
       return result;
     }
@@ -1436,6 +1522,10 @@ public final class Test {
         hash = (37 * hash) + FOO_FIELD_NUMBER;
         hash = (53 * hash) + getFoo().hashCode();
       }
+      if (hasTimestamp()) {
+        hash = (37 * hash) + TIMESTAMP_FIELD_NUMBER;
+        hash = (53 * hash) + getTimestamp().hashCode();
+      }
       hash = (29 * hash) + unknownFields.hashCode();
       memoizedHashCode = hash;
       return hash;
@@ -1556,6 +1646,7 @@ public final class Test {
         if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) {
           getFooArrayFieldBuilder();
           getFooFieldBuilder();
+          getTimestampFieldBuilder();
         }
       }
 
@@ -1609,6 +1700,12 @@ public final class Test {
           fooBuilder_.clear();
         }
         bitField0_ = (bitField0_ & ~0x00080000);
+        if (timestampBuilder_ == null) {
+          timestamp_ = null;
+        } else {
+          timestampBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00100000);
         return this;
       }
 
@@ -1723,6 +1820,14 @@ public final class Test {
         } else {
           result.foo_ = fooBuilder_.build();
         }
+        if (((from_bitField0_ & 0x00100000) == 0x00100000)) {
+          to_bitField0_ |= 0x00020000;
+        }
+        if (timestampBuilder_ == null) {
+          result.timestamp_ = timestamp_;
+        } else {
+          result.timestamp_ = timestampBuilder_.build();
+        }
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
@@ -1864,6 +1969,9 @@ public final class Test {
         if (other.hasFoo()) {
           mergeFoo(other.getFoo());
         }
+        if (other.hasTimestamp()) {
+          mergeTimestamp(other.getTimestamp());
+        }
         this.mergeUnknownFields(other.unknownFields);
         onChanged();
         return this;
@@ -3112,6 +3220,159 @@ public final class Test {
         return fooBuilder_;
       }
 
+      private com.google.protobuf.Timestamp timestamp_ = null;
+      private com.google.protobuf.SingleFieldBuilderV3<com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> timestampBuilder_;
+
+      /**
+       * <pre>
+       * a predefined message type
+       * </pre>
+       *
+       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+       */
+      public boolean hasTimestamp() {
+        return ((bitField0_ & 0x00100000) == 0x00100000);
+      }
+
+      /**
+       * <pre>
+       * a predefined message type
+       * </pre>
+       *
+       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+       */
+      public com.google.protobuf.Timestamp getTimestamp() {
+        if (timestampBuilder_ == null) {
+          return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_;
+        } else {
+          return timestampBuilder_.getMessage();
+        }
+      }
+
+      /**
+       * <pre>
+       * a predefined message type
+       * </pre>
+       *
+       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+       */
+      public Builder setTimestamp(com.google.protobuf.Timestamp value) {
+        if (timestampBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          timestamp_ = value;
+          onChanged();
+        } else {
+          timestampBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00100000;
+        return this;
+      }
+
+      /**
+       * <pre>
+       * a predefined message type
+       * </pre>
+       *
+       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+       */
+      public Builder setTimestamp(com.google.protobuf.Timestamp.Builder builderForValue) {
+        if (timestampBuilder_ == null) {
+          timestamp_ = builderForValue.build();
+          onChanged();
+        } else {
+          timestampBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00100000;
+        return this;
+      }
+
+      /**
+       * <pre>
+       * a predefined message type
+       * </pre>
+       *
+       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+       */
+      public Builder mergeTimestamp(com.google.protobuf.Timestamp value) {
+        if (timestampBuilder_ == null) {
+          if (((bitField0_ & 0x00100000) == 0x00100000) && timestamp_ != null
+              && timestamp_ != com.google.protobuf.Timestamp.getDefaultInstance()) {
+            timestamp_ = com.google.protobuf.Timestamp.newBuilder(timestamp_).mergeFrom(value).buildPartial();
+          } else {
+            timestamp_ = value;
+          }
+          onChanged();
+        } else {
+          timestampBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00100000;
+        return this;
+      }
+
+      /**
+       * <pre>
+       * a predefined message type
+       * </pre>
+       *
+       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+       */
+      public Builder clearTimestamp() {
+        if (timestampBuilder_ == null) {
+          timestamp_ = null;
+          onChanged();
+        } else {
+          timestampBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00100000);
+        return this;
+      }
+
+      /**
+       * <pre>
+       * a predefined message type
+       * </pre>
+       *
+       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+       */
+      public com.google.protobuf.Timestamp.Builder getTimestampBuilder() {
+        bitField0_ |= 0x00100000;
+        onChanged();
+        return getTimestampFieldBuilder().getBuilder();
+      }
+
+      /**
+       * <pre>
+       * a predefined message type
+       * </pre>
+       *
+       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+       */
+      public com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder() {
+        if (timestampBuilder_ != null) {
+          return timestampBuilder_.getMessageOrBuilder();
+        } else {
+          return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_;
+        }
+      }
+
+      /**
+       * <pre>
+       * a predefined message type
+       * </pre>
+       *
+       * <code>optional .google.protobuf.Timestamp timestamp = 21;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilderV3<com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> getTimestampFieldBuilder() {
+        if (timestampBuilder_ == null) {
+          timestampBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder>(
+              getTimestamp(), getParentForChildren(), isClean());
+          timestamp_ = null;
+        }
+        return timestampBuilder_;
+      }
+
       public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) {
         return super.setUnknownFields(unknownFields);
       }
@@ -3626,18 +3887,20 @@ public final class Test {
   private static com.google.protobuf.Descriptors.FileDescriptor descriptor;
   static {
     java.lang.String[] descriptorData = { "\n\034src/test/protobuf/test.proto\022\036org.apac"
-        + "he.avro.protobuf.noopt\"\325\003\n\003Foo\022\r\n\005int32\030"
-        + "\001 \002(\005\022\r\n\005int64\030\002 \001(\003\022\016\n\006uint32\030\003 \001(\r\022\016\n\006"
-        + "uint64\030\004 \001(\004\022\016\n\006sint32\030\005 \001(\021\022\016\n\006sint64\030\006"
-        + " \001(\022\022\017\n\007fixed32\030\007 \001(\007\022\017\n\007fixed64\030\010 \001(\006\022\020"
-        + "\n\010sfixed32\030\t \001(\017\022\020\n\010sfixed64\030\n \001(\020\022\r\n\005fl"
-        + "oat\030\013 \001(\002\022\016\n\006double\030\014 \001(\001\022\014\n\004bool\030\r \001(\010\022"
-        + "\016\n\006string\030\016 \001(\t\022\r\n\005bytes\030\017 \001(\014\0222\n\004enum\030\020"
-        + " \001(\0162!.org.apache.avro.protobuf.noopt.A:"
-        + "\001Z\022\020\n\010intArray\030\021 \003(\005\0225\n\010fooArray\030\024 \003(\0132#"
-        + ".org.apache.avro.protobuf.noopt.Foo\022/\n\004s" + "yms\030\023 \003(\0162!.org.apache.avro.protobuf.noo"
-        + "pt.A\0220\n\003foo\030\022 \001(\0132#.org.apache.avro.prot"
-        + "obuf.noopt.Foo\"\017\n\001M\"\n\n\001N\022\005\n\001A\020\001*\030\n\001A\022\005\n\001"
+        + "he.avro.protobuf.noopt\032\037google/protobuf/"
+        + "timestamp.proto\"\204\004\n\003Foo\022\r\n\005int32\030\001 \002(\005\022\r"
+        + "\n\005int64\030\002 \001(\003\022\016\n\006uint32\030\003 \001(\r\022\016\n\006uint64\030"
+        + "\004 \001(\004\022\016\n\006sint32\030\005 \001(\021\022\016\n\006sint64\030\006 \001(\022\022\017\n"
+        + "\007fixed32\030\007 \001(\007\022\017\n\007fixed64\030\010 \001(\006\022\020\n\010sfixe"
+        + "d32\030\t \001(\017\022\020\n\010sfixed64\030\n \001(\020\022\r\n\005float\030\013 \001"
+        + "(\002\022\016\n\006double\030\014 \001(\001\022\014\n\004bool\030\r \001(\010\022\016\n\006stri"
+        + "ng\030\016 \001(\t\022\r\n\005bytes\030\017 \001(\014\0222\n\004enum\030\020 \001(\0162!."
+        + "org.apache.avro.protobuf.noopt.A:\001Z\022\020\n\010i"
+        + "ntArray\030\021 \003(\005\0225\n\010fooArray\030\024 \003(\0132#.org.ap"
+        + "ache.avro.protobuf.noopt.Foo\022/\n\004syms\030\023 \003" + "(\0162!.org.apache.avro.protobuf.noopt.A\0220\n"
+        + "\003foo\030\022 \001(\0132#.org.apache.avro.protobuf.no"
+        + "opt.Foo\022-\n\ttimestamp\030\025 \001(\0132\032.google.prot"
+        + "obuf.Timestamp\"\017\n\001M\"\n\n\001N\022\005\n\001A\020\001*\030\n\001A\022\005\n\001"
         + "X\020\001\022\005\n\001Y\020\002\022\005\n\001Z\020\003" };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
       public com.google.protobuf.ExtensionRegistry assignDescriptors(
@@ -3647,16 +3910,18 @@ public final class Test {
       }
     };
     com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(descriptorData,
-        new com.google.protobuf.Descriptors.FileDescriptor[] {}, assigner);
+        new com.google.protobuf.Descriptors.FileDescriptor[] { com.google.protobuf.TimestampProto.getDescriptor(), },
+        assigner);
     internal_static_org_apache_avro_protobuf_noopt_Foo_descriptor = getDescriptor().getMessageTypes().get(0);
     internal_static_org_apache_avro_protobuf_noopt_Foo_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         internal_static_org_apache_avro_protobuf_noopt_Foo_descriptor,
         new java.lang.String[] { "Int32", "Int64", "Uint32", "Uint64", "Sint32", "Sint64", "Fixed32", "Fixed64",
             "Sfixed32", "Sfixed64", "Float", "Double", "Bool", "String", "Bytes", "Enum", "IntArray", "FooArray",
-            "Syms", "Foo", });
+            "Syms", "Foo", "Timestamp", });
     internal_static_org_apache_avro_protobuf_noopt_M_descriptor = getDescriptor().getMessageTypes().get(1);
     internal_static_org_apache_avro_protobuf_noopt_M_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         internal_static_org_apache_avro_protobuf_noopt_M_descriptor, new java.lang.String[] {});
+    com.google.protobuf.TimestampProto.getDescriptor();
   }
 
   // @@protoc_insertion_point(outer_class_scope)
diff --git a/lang/java/protobuf/src/test/protobuf/test.proto b/lang/java/protobuf/src/test/protobuf/test.proto
index 26caff4..81a4f62 100644
--- a/lang/java/protobuf/src/test/protobuf/test.proto
+++ b/lang/java/protobuf/src/test/protobuf/test.proto
@@ -18,6 +18,8 @@
 
 package org.apache.avro.protobuf.noopt;
 
+import "google/protobuf/timestamp.proto";
+
 message Foo {
   // all the primitive types
   required    int32 int32    =  1;
@@ -45,6 +47,8 @@ message Foo {
   // a recursive type
   optional     Foo  foo      = 18;
 
+  // a predefined message type
+  optional google.protobuf.Timestamp timestamp = 21;
 }
 
 // an enum
diff --git a/lang/java/protobuf/src/test/protobuf/test_multiple_files.proto b/lang/java/protobuf/src/test/protobuf/test_multiple_files.proto
index d57dff5..cdbff7f 100644
--- a/lang/java/protobuf/src/test/protobuf/test_multiple_files.proto
+++ b/lang/java/protobuf/src/test/protobuf/test_multiple_files.proto
@@ -18,6 +18,8 @@
 
 package org.apache.avro.protobuf.multiplefiles;
 
+import "google/protobuf/timestamp.proto";
+
 option java_multiple_files = true;
 
 message Foo {
@@ -47,6 +49,8 @@ message Foo {
   // a recursive type
   optional     Foo  foo      = 18;
 
+  // a predefined message type
+  optional google.protobuf.Timestamp timestamp = 21;
 }
 
 // an enum


Mime
View raw message