Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 33D1B200CD7 for ; Mon, 17 Jul 2017 19:58:07 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 3248516558F; Mon, 17 Jul 2017 17:58:07 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 36330165591 for ; Mon, 17 Jul 2017 19:58:05 +0200 (CEST) Received: (qmail 74044 invoked by uid 500); 17 Jul 2017 17:58:04 -0000 Mailing-List: contact commits-help@hbase.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@hbase.apache.org Delivered-To: mailing list commits@hbase.apache.org Received: (qmail 68365 invoked by uid 99); 17 Jul 2017 17:57:55 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 17 Jul 2017 17:57:55 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id DF336F5550; Mon, 17 Jul 2017 17:57:54 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: appy@apache.org To: commits@hbase.apache.org Date: Mon, 17 Jul 2017 17:58:19 -0000 Message-Id: In-Reply-To: <7015d67bb4404c3487d0d943c7817331@git.apache.org> References: <7015d67bb4404c3487d0d943c7817331@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [26/94] [abbrv] [partial] hbase git commit: Revert "HBASE-17056 Remove checked in PB generated files Selective add of dependency on" Revert for now. Build unstable and some interesting issues around CLASSPATH archived-at: Mon, 17 Jul 2017 17:58:07 -0000 http://git-wip-us.apache.org/repos/asf/hbase/blob/6786b2b6/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/GeneratedMessage.java ---------------------------------------------------------------------- diff --git a/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/GeneratedMessage.java b/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/GeneratedMessage.java new file mode 100644 index 0000000..4a0f93a --- /dev/null +++ b/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/com/google/protobuf/GeneratedMessage.java @@ -0,0 +1,3047 @@ +// 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 org.apache.hadoop.hbase.shaded.com.google.protobuf; + +import org.apache.hadoop.hbase.shaded.com.google.protobuf.Descriptors.Descriptor; +import org.apache.hadoop.hbase.shaded.com.google.protobuf.Descriptors.EnumDescriptor; +import org.apache.hadoop.hbase.shaded.com.google.protobuf.Descriptors.EnumValueDescriptor; +import org.apache.hadoop.hbase.shaded.com.google.protobuf.Descriptors.FieldDescriptor; +import org.apache.hadoop.hbase.shaded.com.google.protobuf.Descriptors.FileDescriptor; +import org.apache.hadoop.hbase.shaded.com.google.protobuf.Descriptors.OneofDescriptor; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + * All generated protocol message classes extend this class. This class + * implements most of the Message and Builder interfaces using Java reflection. + * Users can ignore this class and pretend that generated messages implement + * the Message interface directly. + * + * @author kenton@google.com Kenton Varda + */ +public abstract class GeneratedMessage extends AbstractMessage + implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * For testing. Allows a test to disable the optimization that avoids using + * field builders for nested messages until they are requested. By disabling + * this optimization, existing tests can be reused to test the field builders. + */ + protected static boolean alwaysUseFieldBuilders = false; + + /** For use by generated code only. */ + protected UnknownFieldSet unknownFields; + + protected GeneratedMessage() { + unknownFields = UnknownFieldSet.getDefaultInstance(); + } + + protected GeneratedMessage(Builder builder) { + unknownFields = builder.getUnknownFields(); + } + + @Override + public Parser getParserForType() { + throw new UnsupportedOperationException( + "This is supposed to be overridden by subclasses."); + } + + /** + * For testing. Allows a test to disable the optimization that avoids using + * field builders for nested messages until they are requested. By disabling + * this optimization, existing tests can be reused to test the field builders. + * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}. + */ + static void enableAlwaysUseFieldBuildersForTesting() { + alwaysUseFieldBuilders = true; + } + + /** + * Get the FieldAccessorTable for this type. We can't have the message + * class pass this in to the constructor because of bootstrapping trouble + * with DescriptorProtos. + */ + protected abstract FieldAccessorTable internalGetFieldAccessorTable(); + + @Override + public Descriptor getDescriptorForType() { + return internalGetFieldAccessorTable().descriptor; + } + + /** + * Internal helper to return a modifiable map containing all the fields. + * The returned Map is modifialbe so that the caller can add additional + * extension fields to implement {@link #getAllFields()}. + * + * @param getBytesForString whether to generate ByteString for string fields + */ + private Map getAllFieldsMutable( + boolean getBytesForString) { + final TreeMap result = + new TreeMap(); + final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; + final List fields = descriptor.getFields(); + + for (int i = 0; i < fields.size(); i++) { + FieldDescriptor field = fields.get(i); + final OneofDescriptor oneofDescriptor = field.getContainingOneof(); + + /* + * If the field is part of a Oneof, then at maximum one field in the Oneof is set + * and it is not repeated. There is no need to iterate through the others. + */ + if (oneofDescriptor != null) { + // Skip other fields in the Oneof we know are not set + i += oneofDescriptor.getFieldCount() - 1; + if (!hasOneof(oneofDescriptor)) { + // If no field is set in the Oneof, skip all the fields in the Oneof + continue; + } + // Get the pointer to the only field which is set in the Oneof + field = getOneofFieldDescriptor(oneofDescriptor); + } else { + // If we are not in a Oneof, we need to check if the field is set and if it is repeated + if (field.isRepeated()) { + final List value = (List) getField(field); + if (!value.isEmpty()) { + result.put(field, value); + } + continue; + } + if (!hasField(field)) { + continue; + } + } + // Add the field to the map + if (getBytesForString && field.getJavaType() == FieldDescriptor.JavaType.STRING) { + result.put(field, getFieldRaw(field)); + } else { + result.put(field, getField(field)); + } + } + return result; + } + + @Override + public boolean isInitialized() { + for (final FieldDescriptor field : getDescriptorForType().getFields()) { + // Check that all required fields are present. + if (field.isRequired()) { + if (!hasField(field)) { + return false; + } + } + // Check that embedded messages are initialized. + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + if (field.isRepeated()) { + @SuppressWarnings("unchecked") final + List messageList = (List) getField(field); + for (final Message element : messageList) { + if (!element.isInitialized()) { + return false; + } + } + } else { + if (hasField(field) && !((Message) getField(field)).isInitialized()) { + return false; + } + } + } + } + + return true; + } + + @Override + public Map getAllFields() { + return Collections.unmodifiableMap( + getAllFieldsMutable(/* getBytesForString = */ false)); + } + + /** + * Returns a collection of all the fields in this message which are set + * and their corresponding values. A singular ("required" or "optional") + * field is set iff hasField() returns true for that field. A "repeated" + * field is set iff getRepeatedFieldCount() is greater than zero. The + * values are exactly what would be returned by calling + * {@link #getFieldRaw(Descriptors.FieldDescriptor)} for each field. The map + * is guaranteed to be a sorted map, so iterating over it will return fields + * in order by field number. + */ + Map getAllFieldsRaw() { + return Collections.unmodifiableMap( + getAllFieldsMutable(/* getBytesForString = */ true)); + } + + @Override + public boolean hasOneof(final OneofDescriptor oneof) { + return internalGetFieldAccessorTable().getOneof(oneof).has(this); + } + + @Override + public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) { + return internalGetFieldAccessorTable().getOneof(oneof).get(this); + } + + @Override + public boolean hasField(final FieldDescriptor field) { + return internalGetFieldAccessorTable().getField(field).has(this); + } + + @Override + public Object getField(final FieldDescriptor field) { + return internalGetFieldAccessorTable().getField(field).get(this); + } + + /** + * Obtains the value of the given field, or the default value if it is + * not set. For primitive fields, the boxed primitive value is returned. + * For enum fields, the EnumValueDescriptor for the value is returned. For + * embedded message fields, the sub-message is returned. For repeated + * fields, a java.util.List is returned. For present string fields, a + * ByteString is returned representing the bytes that the field contains. + */ + Object getFieldRaw(final FieldDescriptor field) { + return internalGetFieldAccessorTable().getField(field).getRaw(this); + } + + @Override + public int getRepeatedFieldCount(final FieldDescriptor field) { + return internalGetFieldAccessorTable().getField(field) + .getRepeatedCount(this); + } + + @Override + public Object getRepeatedField(final FieldDescriptor field, final int index) { + return internalGetFieldAccessorTable().getField(field) + .getRepeated(this, index); + } + + @Override + public UnknownFieldSet getUnknownFields() { + throw new UnsupportedOperationException( + "This is supposed to be overridden by subclasses."); + } + + /** + * Called by subclasses to parse an unknown field. + * @return {@code true} unless the tag is an end-group tag. + */ + protected boolean parseUnknownField( + CodedInputStream input, + UnknownFieldSet.Builder unknownFields, + ExtensionRegistryLite extensionRegistry, + int tag) throws IOException { + return unknownFields.mergeFieldFrom(tag, input); + } + + protected static M parseWithIOException(Parser parser, InputStream input) + throws IOException { + try { + return parser.parseFrom(input); + } catch (InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } + } + + protected static M parseWithIOException(Parser parser, InputStream input, + ExtensionRegistryLite extensions) throws IOException { + try { + return parser.parseFrom(input, extensions); + } catch (InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } + } + + protected static M parseWithIOException(Parser parser, + CodedInputStream input) throws IOException { + try { + return parser.parseFrom(input); + } catch (InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } + } + + protected static M parseWithIOException(Parser parser, + CodedInputStream input, ExtensionRegistryLite extensions) throws IOException { + try { + return parser.parseFrom(input, extensions); + } catch (InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } + } + + protected static M parseDelimitedWithIOException(Parser parser, + InputStream input) throws IOException { + try { + return parser.parseDelimitedFrom(input); + } catch (InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } + } + + protected static M parseDelimitedWithIOException(Parser parser, + InputStream input, ExtensionRegistryLite extensions) throws IOException { + try { + return parser.parseDelimitedFrom(input, extensions); + } catch (InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } + } + + @Override + public void writeTo(final CodedOutputStream output) throws IOException { + MessageReflection.writeMessageTo(this, getAllFieldsRaw(), output, false); + } + + @Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) { + return size; + } + + memoizedSize = MessageReflection.getSerializedSize( + this, getAllFieldsRaw()); + return memoizedSize; + } + + + + /** + * Used by parsing constructors in generated classes. + */ + protected void makeExtensionsImmutable() { + // Noop for messages without extensions. + } + + /** + * TODO(xiaofeng): remove this after b/29368482 is fixed. We need to move this + * interface to AbstractMessage in order to versioning GeneratedMessage but + * this move breaks binary compatibility for AppEngine. After AppEngine is + * fixed we can exlude this from google3. + */ + protected interface BuilderParent extends AbstractMessage.BuilderParent {} + + /** + * TODO(xiaofeng): remove this together with GeneratedMessage.BuilderParent. + */ + protected abstract Message.Builder newBuilderForType(BuilderParent parent); + + @Override + protected Message.Builder newBuilderForType(final AbstractMessage.BuilderParent parent) { + return newBuilderForType(new BuilderParent() { + @Override + public void markDirty() { + parent.markDirty(); + } + }); + } + + + @SuppressWarnings("unchecked") + public abstract static class Builder > + extends AbstractMessage.Builder { + + private BuilderParent builderParent; + + private BuilderParentImpl meAsParent; + + // Indicates that we've built a message and so we are now obligated + // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener. + private boolean isClean; + + private UnknownFieldSet unknownFields = + UnknownFieldSet.getDefaultInstance(); + + protected Builder() { + this(null); + } + + protected Builder(BuilderParent builderParent) { + this.builderParent = builderParent; + } + + @Override + void dispose() { + builderParent = null; + } + + /** + * Called by the subclass when a message is built. + */ + protected void onBuilt() { + if (builderParent != null) { + markClean(); + } + } + + /** + * Called by the subclass or a builder to notify us that a message was + * built and may be cached and therefore invalidations are needed. + */ + @Override + protected void markClean() { + this.isClean = true; + } + + /** + * Gets whether invalidations are needed + * + * @return whether invalidations are needed + */ + protected boolean isClean() { + return isClean; + } + + @Override + public BuilderType clone() { + BuilderType builder = + (BuilderType) getDefaultInstanceForType().newBuilderForType(); + builder.mergeFrom(buildPartial()); + return builder; + } + + /** + * Called by the initialization and clear code paths to allow subclasses to + * reset any of their builtin fields back to the initial values. + */ + @Override + public BuilderType clear() { + unknownFields = UnknownFieldSet.getDefaultInstance(); + onChanged(); + return (BuilderType) this; + } + + /** + * Get the FieldAccessorTable for this type. We can't have the message + * class pass this in to the constructor because of bootstrapping trouble + * with DescriptorProtos. + */ + protected abstract FieldAccessorTable internalGetFieldAccessorTable(); + + @Override + public Descriptor getDescriptorForType() { + return internalGetFieldAccessorTable().descriptor; + } + + @Override + public Map getAllFields() { + return Collections.unmodifiableMap(getAllFieldsMutable()); + } + + /** Internal helper which returns a mutable map. */ + private Map getAllFieldsMutable() { + final TreeMap result = + new TreeMap(); + final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; + final List fields = descriptor.getFields(); + + for (int i = 0; i < fields.size(); i++) { + FieldDescriptor field = fields.get(i); + final OneofDescriptor oneofDescriptor = field.getContainingOneof(); + + /* + * If the field is part of a Oneof, then at maximum one field in the Oneof is set + * and it is not repeated. There is no need to iterate through the others. + */ + if (oneofDescriptor != null) { + // Skip other fields in the Oneof we know are not set + i += oneofDescriptor.getFieldCount() - 1; + if (!hasOneof(oneofDescriptor)) { + // If no field is set in the Oneof, skip all the fields in the Oneof + continue; + } + // Get the pointer to the only field which is set in the Oneof + field = getOneofFieldDescriptor(oneofDescriptor); + } else { + // If we are not in a Oneof, we need to check if the field is set and if it is repeated + if (field.isRepeated()) { + final List value = (List) getField(field); + if (!value.isEmpty()) { + result.put(field, value); + } + continue; + } + if (!hasField(field)) { + continue; + } + } + // Add the field to the map + result.put(field, getField(field)); + } + return result; + } + + @Override + public Message.Builder newBuilderForField(final FieldDescriptor field) { + return internalGetFieldAccessorTable().getField(field).newBuilder(); + } + + @Override + public Message.Builder getFieldBuilder(final FieldDescriptor field) { + return internalGetFieldAccessorTable().getField(field).getBuilder(this); + } + + @Override + public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) { + return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder( + this, index); + } + + @Override + public boolean hasOneof(final OneofDescriptor oneof) { + return internalGetFieldAccessorTable().getOneof(oneof).has(this); + } + + @Override + public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) { + return internalGetFieldAccessorTable().getOneof(oneof).get(this); + } + + @Override + public boolean hasField(final FieldDescriptor field) { + return internalGetFieldAccessorTable().getField(field).has(this); + } + + @Override + public Object getField(final FieldDescriptor field) { + Object object = internalGetFieldAccessorTable().getField(field).get(this); + if (field.isRepeated()) { + // The underlying list object is still modifiable at this point. + // Make sure not to expose the modifiable list to the caller. + return Collections.unmodifiableList((List) object); + } else { + return object; + } + } + + @Override + public BuilderType setField(final FieldDescriptor field, final Object value) { + internalGetFieldAccessorTable().getField(field).set(this, value); + return (BuilderType) this; + } + + @Override + public BuilderType clearField(final FieldDescriptor field) { + internalGetFieldAccessorTable().getField(field).clear(this); + return (BuilderType) this; + } + + @Override + public BuilderType clearOneof(final OneofDescriptor oneof) { + internalGetFieldAccessorTable().getOneof(oneof).clear(this); + return (BuilderType) this; + } + + @Override + public int getRepeatedFieldCount(final FieldDescriptor field) { + return internalGetFieldAccessorTable().getField(field) + .getRepeatedCount(this); + } + + @Override + public Object getRepeatedField(final FieldDescriptor field, final int index) { + return internalGetFieldAccessorTable().getField(field) + .getRepeated(this, index); + } + + @Override + public BuilderType setRepeatedField( + final FieldDescriptor field, final int index, final Object value) { + internalGetFieldAccessorTable().getField(field) + .setRepeated(this, index, value); + return (BuilderType) this; + } + + @Override + public BuilderType addRepeatedField(final FieldDescriptor field, final Object value) { + internalGetFieldAccessorTable().getField(field).addRepeated(this, value); + return (BuilderType) this; + } + + @Override + public BuilderType setUnknownFields(final UnknownFieldSet unknownFields) { + this.unknownFields = unknownFields; + onChanged(); + return (BuilderType) this; + } + + @Override + public BuilderType mergeUnknownFields( + final UnknownFieldSet unknownFields) { + this.unknownFields = + UnknownFieldSet.newBuilder(this.unknownFields) + .mergeFrom(unknownFields) + .build(); + onChanged(); + return (BuilderType) this; + } + + @Override + public boolean isInitialized() { + for (final FieldDescriptor field : getDescriptorForType().getFields()) { + // Check that all required fields are present. + if (field.isRequired()) { + if (!hasField(field)) { + return false; + } + } + // Check that embedded messages are initialized. + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + if (field.isRepeated()) { + @SuppressWarnings("unchecked") final + List messageList = (List) getField(field); + for (final Message element : messageList) { + if (!element.isInitialized()) { + return false; + } + } + } else { + if (hasField(field) && + !((Message) getField(field)).isInitialized()) { + return false; + } + } + } + } + return true; + } + + @Override + public final UnknownFieldSet getUnknownFields() { + return unknownFields; + } + + /** + * Called by subclasses to parse an unknown field. + * @return {@code true} unless the tag is an end-group tag. + */ + protected boolean parseUnknownField( + final CodedInputStream input, + final UnknownFieldSet.Builder unknownFields, + final ExtensionRegistryLite extensionRegistry, + final int tag) throws IOException { + return unknownFields.mergeFieldFrom(tag, input); + } + + /** + * Implementation of {@link BuilderParent} for giving to our children. This + * small inner class makes it so we don't publicly expose the BuilderParent + * methods. + */ + private class BuilderParentImpl implements BuilderParent { + + @Override + public void markDirty() { + onChanged(); + } + } + + /** + * Gets the {@link BuilderParent} for giving to our children. + * @return The builder parent for our children. + */ + protected BuilderParent getParentForChildren() { + if (meAsParent == null) { + meAsParent = new BuilderParentImpl(); + } + return meAsParent; + } + + /** + * Called when a the builder or one of its nested children has changed + * and any parent should be notified of its invalidation. + */ + protected final void onChanged() { + if (isClean && builderParent != null) { + builderParent.markDirty(); + + // Don't keep dispatching invalidations until build is called again. + isClean = false; + } + } + + /** + * Gets the map field with the given field number. This method should be + * overridden in the generated message class if the message contains map + * fields. + * + * Unlike other field types, reflection support for map fields can't be + * implemented based on generated public API because we need to access a + * map field as a list in reflection API but the generated API only allows + * us to access it as a map. This method returns the underlying map field + * directly and thus enables us to access the map field as a list. + */ + @SuppressWarnings({"unused", "rawtypes"}) + protected MapField internalGetMapField(int fieldNumber) { + // Note that we can't use descriptor names here because this method will + // be called when descriptor is being initialized. + throw new RuntimeException( + "No map fields found in " + getClass().getName()); + } + + /** Like {@link #internalGetMapField} but return a mutable version. */ + @SuppressWarnings({"unused", "rawtypes"}) + protected MapField internalGetMutableMapField(int fieldNumber) { + // Note that we can't use descriptor names here because this method will + // be called when descriptor is being initialized. + throw new RuntimeException( + "No map fields found in " + getClass().getName()); + } + } + + // ================================================================= + // Extensions-related stuff + + public interface ExtendableMessageOrBuilder< + MessageType extends ExtendableMessage> extends MessageOrBuilder { + // Re-define for return type covariance. + @Override + Message getDefaultInstanceForType(); + + /** Check if a singular extension is present. */ + boolean hasExtension( + ExtensionLite extension); + + /** Get the number of elements in a repeated extension. */ + int getExtensionCount( + ExtensionLite> extension); + + /** Get the value of an extension. */ + Type getExtension( + ExtensionLite extension); + + /** Get one element of a repeated extension. */ + Type getExtension( + ExtensionLite> extension, + int index); + + /** Check if a singular extension is present. */ + boolean hasExtension( + Extension extension); + /** Check if a singular extension is present. */ + boolean hasExtension( + GeneratedExtension extension); + /** Get the number of elements in a repeated extension. */ + int getExtensionCount( + Extension> extension); + /** Get the number of elements in a repeated extension. */ + int getExtensionCount( + GeneratedExtension> extension); + /** Get the value of an extension. */ + Type getExtension( + Extension extension); + /** Get the value of an extension. */ + Type getExtension( + GeneratedExtension extension); + /** Get one element of a repeated extension. */ + Type getExtension( + Extension> extension, + int index); + /** Get one element of a repeated extension. */ + Type getExtension( + GeneratedExtension> extension, + int index); + } + + /** + * Generated message classes for message types that contain extension ranges + * subclass this. + * + *

This class implements type-safe accessors for extensions. They + * implement all the same operations that you can do with normal fields -- + * e.g. "has", "get", and "getCount" -- but for extensions. The extensions + * are identified using instances of the class {@link GeneratedExtension}; + * the protocol compiler generates a static instance of this class for every + * extension in its input. Through the magic of generics, all is made + * type-safe. + * + *

For example, imagine you have the {@code .proto} file: + * + *

+   * option java_class = "MyProto";
+   *
+   * message Foo {
+   *   extensions 1000 to max;
+   * }
+   *
+   * extend Foo {
+   *   optional int32 bar;
+   * }
+   * 
+ * + *

Then you might write code like: + * + *

+   * MyProto.Foo foo = getFoo();
+   * int i = foo.getExtension(MyProto.bar);
+   * 
+ * + *

See also {@link ExtendableBuilder}. + */ + public abstract static class ExtendableMessage< + MessageType extends ExtendableMessage> + extends GeneratedMessage + implements ExtendableMessageOrBuilder { + + private static final long serialVersionUID = 1L; + + private final FieldSet extensions; + + protected ExtendableMessage() { + this.extensions = FieldSet.newFieldSet(); + } + + protected ExtendableMessage( + ExtendableBuilder builder) { + super(builder); + this.extensions = builder.buildExtensions(); + } + + private void verifyExtensionContainingType( + final Extension extension) { + if (extension.getDescriptor().getContainingType() != + getDescriptorForType()) { + // This can only happen if someone uses unchecked operations. + throw new IllegalArgumentException( + "Extension is for type \"" + + extension.getDescriptor().getContainingType().getFullName() + + "\" which does not match message type \"" + + getDescriptorForType().getFullName() + "\"."); + } + } + + /** Check if a singular extension is present. */ + @Override + public final boolean hasExtension(final ExtensionLite extensionLite) { + Extension extension = checkNotLite(extensionLite); + + verifyExtensionContainingType(extension); + return extensions.hasField(extension.getDescriptor()); + } + + /** Get the number of elements in a repeated extension. */ + @Override + public final int getExtensionCount( + final ExtensionLite> extensionLite) { + Extension> extension = checkNotLite(extensionLite); + + verifyExtensionContainingType(extension); + final FieldDescriptor descriptor = extension.getDescriptor(); + return extensions.getRepeatedFieldCount(descriptor); + } + + /** Get the value of an extension. */ + @Override + @SuppressWarnings("unchecked") + public final Type getExtension(final ExtensionLite extensionLite) { + Extension extension = checkNotLite(extensionLite); + + verifyExtensionContainingType(extension); + FieldDescriptor descriptor = extension.getDescriptor(); + final Object value = extensions.getField(descriptor); + if (value == null) { + if (descriptor.isRepeated()) { + return (Type) Collections.emptyList(); + } else if (descriptor.getJavaType() == + FieldDescriptor.JavaType.MESSAGE) { + return (Type) extension.getMessageDefaultInstance(); + } else { + return (Type) extension.fromReflectionType( + descriptor.getDefaultValue()); + } + } else { + return (Type) extension.fromReflectionType(value); + } + } + + /** Get one element of a repeated extension. */ + @Override + @SuppressWarnings("unchecked") + public final Type getExtension( + final ExtensionLite> extensionLite, final int index) { + Extension> extension = checkNotLite(extensionLite); + + verifyExtensionContainingType(extension); + FieldDescriptor descriptor = extension.getDescriptor(); + return (Type) extension.singularFromReflectionType( + extensions.getRepeatedField(descriptor, index)); + } + + /** Check if a singular extension is present. */ + @Override + public final boolean hasExtension(final Extension extension) { + return hasExtension((ExtensionLite) extension); + } + /** Check if a singular extension is present. */ + @Override + public final boolean hasExtension( + final GeneratedExtension extension) { + return hasExtension((ExtensionLite) extension); + } + /** Get the number of elements in a repeated extension. */ + @Override + public final int getExtensionCount( + final Extension> extension) { + return getExtensionCount((ExtensionLite>) extension); + } + /** Get the number of elements in a repeated extension. */ + @Override + public final int getExtensionCount( + final GeneratedExtension> extension) { + return getExtensionCount((ExtensionLite>) extension); + } + /** Get the value of an extension. */ + @Override + public final Type getExtension(final Extension extension) { + return getExtension((ExtensionLite) extension); + } + /** Get the value of an extension. */ + @Override + public final Type getExtension( + final GeneratedExtension extension) { + return getExtension((ExtensionLite) extension); + } + /** Get one element of a repeated extension. */ + @Override + public final Type getExtension( + final Extension> extension, final int index) { + return getExtension((ExtensionLite>) extension, index); + } + /** Get one element of a repeated extension. */ + @Override + public final Type getExtension( + final GeneratedExtension> extension, final int index) { + return getExtension((ExtensionLite>) extension, index); + } + + /** Called by subclasses to check if all extensions are initialized. */ + protected boolean extensionsAreInitialized() { + return extensions.isInitialized(); + } + + @Override + public boolean isInitialized() { + return super.isInitialized() && extensionsAreInitialized(); + } + + @Override + protected boolean parseUnknownField( + CodedInputStream input, + UnknownFieldSet.Builder unknownFields, + ExtensionRegistryLite extensionRegistry, + int tag) throws IOException { + return MessageReflection.mergeFieldFrom( + input, unknownFields, extensionRegistry, getDescriptorForType(), + new MessageReflection.ExtensionAdapter(extensions), tag); + } + + + /** + * Used by parsing constructors in generated classes. + */ + @Override + protected void makeExtensionsImmutable() { + extensions.makeImmutable(); + } + + /** + * Used by subclasses to serialize extensions. Extension ranges may be + * interleaved with field numbers, but we must write them in canonical + * (sorted by field number) order. ExtensionWriter helps us write + * individual ranges of extensions at once. + */ + protected class ExtensionWriter { + // Imagine how much simpler this code would be if Java iterators had + // a way to get the next element without advancing the iterator. + + private final Iterator> iter = + extensions.iterator(); + private Map.Entry next; + private final boolean messageSetWireFormat; + + private ExtensionWriter(final boolean messageSetWireFormat) { + if (iter.hasNext()) { + next = iter.next(); + } + this.messageSetWireFormat = messageSetWireFormat; + } + + public void writeUntil(final int end, final CodedOutputStream output) + throws IOException { + while (next != null && next.getKey().getNumber() < end) { + FieldDescriptor descriptor = next.getKey(); + if (messageSetWireFormat && descriptor.getLiteJavaType() == + WireFormat.JavaType.MESSAGE && + !descriptor.isRepeated()) { + if (next instanceof LazyField.LazyEntry) { + output.writeRawMessageSetExtension(descriptor.getNumber(), + ((LazyField.LazyEntry) next).getField().toByteString()); + } else { + output.writeMessageSetExtension(descriptor.getNumber(), + (Message) next.getValue()); + } + } else { + // TODO(xiangl): Taken care of following code, it may cause + // problem when we use LazyField for normal fields/extensions. + // Due to the optional field can be duplicated at the end of + // serialized bytes, which will make the serialized size change + // after lazy field parsed. So when we use LazyField globally, + // we need to change the following write method to write cached + // bytes directly rather than write the parsed message. + FieldSet.writeField(descriptor, next.getValue(), output); + } + if (iter.hasNext()) { + next = iter.next(); + } else { + next = null; + } + } + } + } + + protected ExtensionWriter newExtensionWriter() { + return new ExtensionWriter(false); + } + protected ExtensionWriter newMessageSetExtensionWriter() { + return new ExtensionWriter(true); + } + + /** Called by subclasses to compute the size of extensions. */ + protected int extensionsSerializedSize() { + return extensions.getSerializedSize(); + } + protected int extensionsSerializedSizeAsMessageSet() { + return extensions.getMessageSetSerializedSize(); + } + + // --------------------------------------------------------------- + // Reflection + + protected Map getExtensionFields() { + return extensions.getAllFields(); + } + + @Override + public Map getAllFields() { + final Map result = + super.getAllFieldsMutable(/* getBytesForString = */ false); + result.putAll(getExtensionFields()); + return Collections.unmodifiableMap(result); + } + + @Override + public Map getAllFieldsRaw() { + final Map result = + super.getAllFieldsMutable(/* getBytesForString = */ false); + result.putAll(getExtensionFields()); + return Collections.unmodifiableMap(result); + } + + @Override + public boolean hasField(final FieldDescriptor field) { + if (field.isExtension()) { + verifyContainingType(field); + return extensions.hasField(field); + } else { + return super.hasField(field); + } + } + + @Override + public Object getField(final FieldDescriptor field) { + if (field.isExtension()) { + verifyContainingType(field); + final Object value = extensions.getField(field); + if (value == null) { + if (field.isRepeated()) { + return Collections.emptyList(); + } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + // Lacking an ExtensionRegistry, we have no way to determine the + // extension's real type, so we return a DynamicMessage. + return DynamicMessage.getDefaultInstance(field.getMessageType()); + } else { + return field.getDefaultValue(); + } + } else { + return value; + } + } else { + return super.getField(field); + } + } + + @Override + public int getRepeatedFieldCount(final FieldDescriptor field) { + if (field.isExtension()) { + verifyContainingType(field); + return extensions.getRepeatedFieldCount(field); + } else { + return super.getRepeatedFieldCount(field); + } + } + + @Override + public Object getRepeatedField(final FieldDescriptor field, + final int index) { + if (field.isExtension()) { + verifyContainingType(field); + return extensions.getRepeatedField(field, index); + } else { + return super.getRepeatedField(field, index); + } + } + + private void verifyContainingType(final FieldDescriptor field) { + if (field.getContainingType() != getDescriptorForType()) { + throw new IllegalArgumentException( + "FieldDescriptor does not match message type."); + } + } + } + + /** + * Generated message builders for message types that contain extension ranges + * subclass this. + * + *

This class implements type-safe accessors for extensions. They + * implement all the same operations that you can do with normal fields -- + * e.g. "get", "set", and "add" -- but for extensions. The extensions are + * identified using instances of the class {@link GeneratedExtension}; the + * protocol compiler generates a static instance of this class for every + * extension in its input. Through the magic of generics, all is made + * type-safe. + * + *

For example, imagine you have the {@code .proto} file: + * + *

+   * option java_class = "MyProto";
+   *
+   * message Foo {
+   *   extensions 1000 to max;
+   * }
+   *
+   * extend Foo {
+   *   optional int32 bar;
+   * }
+   * 
+ * + *

Then you might write code like: + * + *

+   * MyProto.Foo foo =
+   *   MyProto.Foo.newBuilder()
+   *     .setExtension(MyProto.bar, 123)
+   *     .build();
+   * 
+ * + *

See also {@link ExtendableMessage}. + */ + @SuppressWarnings("unchecked") + public abstract static class ExtendableBuilder< + MessageType extends ExtendableMessage, + BuilderType extends ExtendableBuilder> + extends Builder + implements ExtendableMessageOrBuilder { + + private FieldSet extensions = FieldSet.emptySet(); + + protected ExtendableBuilder() {} + + protected ExtendableBuilder( + BuilderParent parent) { + super(parent); + } + + // For immutable message conversion. + void internalSetExtensionSet(FieldSet extensions) { + this.extensions = extensions; + } + + @Override + public BuilderType clear() { + extensions = FieldSet.emptySet(); + return super.clear(); + } + + // This is implemented here only to work around an apparent bug in the + // Java compiler and/or build system. See bug #1898463. The mere presence + // of this clone() implementation makes it go away. + @Override + public BuilderType clone() { + return super.clone(); + } + + private void ensureExtensionsIsMutable() { + if (extensions.isImmutable()) { + extensions = extensions.clone(); + } + } + + private void verifyExtensionContainingType( + final Extension extension) { + if (extension.getDescriptor().getContainingType() != + getDescriptorForType()) { + // This can only happen if someone uses unchecked operations. + throw new IllegalArgumentException( + "Extension is for type \"" + + extension.getDescriptor().getContainingType().getFullName() + + "\" which does not match message type \"" + + getDescriptorForType().getFullName() + "\"."); + } + } + + /** Check if a singular extension is present. */ + @Override + public final boolean hasExtension(final ExtensionLite extensionLite) { + Extension extension = checkNotLite(extensionLite); + + verifyExtensionContainingType(extension); + return extensions.hasField(extension.getDescriptor()); + } + + /** Get the number of elements in a repeated extension. */ + @Override + public final int getExtensionCount( + final ExtensionLite> extensionLite) { + Extension> extension = checkNotLite(extensionLite); + + verifyExtensionContainingType(extension); + final FieldDescriptor descriptor = extension.getDescriptor(); + return extensions.getRepeatedFieldCount(descriptor); + } + + /** Get the value of an extension. */ + @Override + public final Type getExtension(final ExtensionLite extensionLite) { + Extension extension = checkNotLite(extensionLite); + + verifyExtensionContainingType(extension); + FieldDescriptor descriptor = extension.getDescriptor(); + final Object value = extensions.getField(descriptor); + if (value == null) { + if (descriptor.isRepeated()) { + return (Type) Collections.emptyList(); + } else if (descriptor.getJavaType() == + FieldDescriptor.JavaType.MESSAGE) { + return (Type) extension.getMessageDefaultInstance(); + } else { + return (Type) extension.fromReflectionType( + descriptor.getDefaultValue()); + } + } else { + return (Type) extension.fromReflectionType(value); + } + } + + /** Get one element of a repeated extension. */ + @Override + public final Type getExtension( + final ExtensionLite> extensionLite, final int index) { + Extension> extension = checkNotLite(extensionLite); + + verifyExtensionContainingType(extension); + FieldDescriptor descriptor = extension.getDescriptor(); + return (Type) extension.singularFromReflectionType( + extensions.getRepeatedField(descriptor, index)); + } + + /** Set the value of an extension. */ + public final BuilderType setExtension( + final ExtensionLite extensionLite, + final Type value) { + Extension extension = checkNotLite(extensionLite); + + verifyExtensionContainingType(extension); + ensureExtensionsIsMutable(); + final FieldDescriptor descriptor = extension.getDescriptor(); + extensions.setField(descriptor, extension.toReflectionType(value)); + onChanged(); + return (BuilderType) this; + } + + /** Set the value of one element of a repeated extension. */ + public final BuilderType setExtension( + final ExtensionLite> extensionLite, + final int index, final Type value) { + Extension> extension = checkNotLite(extensionLite); + + verifyExtensionContainingType(extension); + ensureExtensionsIsMutable(); + final FieldDescriptor descriptor = extension.getDescriptor(); + extensions.setRepeatedField( + descriptor, index, + extension.singularToReflectionType(value)); + onChanged(); + return (BuilderType) this; + } + + /** Append a value to a repeated extension. */ + public final BuilderType addExtension( + final ExtensionLite> extensionLite, + final Type value) { + Extension> extension = checkNotLite(extensionLite); + + verifyExtensionContainingType(extension); + ensureExtensionsIsMutable(); + final FieldDescriptor descriptor = extension.getDescriptor(); + extensions.addRepeatedField( + descriptor, extension.singularToReflectionType(value)); + onChanged(); + return (BuilderType) this; + } + + /** Clear an extension. */ + public final BuilderType clearExtension( + final ExtensionLite extensionLite) { + Extension extension = checkNotLite(extensionLite); + + verifyExtensionContainingType(extension); + ensureExtensionsIsMutable(); + extensions.clearField(extension.getDescriptor()); + onChanged(); + return (BuilderType) this; + } + + /** Check if a singular extension is present. */ + @Override + public final boolean hasExtension(final Extension extension) { + return hasExtension((ExtensionLite) extension); + } + /** Check if a singular extension is present. */ + @Override + public final boolean hasExtension( + final GeneratedExtension extension) { + return hasExtension((ExtensionLite) extension); + } + /** Get the number of elements in a repeated extension. */ + @Override + public final int getExtensionCount( + final Extension> extension) { + return getExtensionCount((ExtensionLite>) extension); + } + /** Get the number of elements in a repeated extension. */ + @Override + public final int getExtensionCount( + final GeneratedExtension> extension) { + return getExtensionCount((ExtensionLite>) extension); + } + /** Get the value of an extension. */ + @Override + public final Type getExtension(final Extension extension) { + return getExtension((ExtensionLite) extension); + } + /** Get the value of an extension. */ + @Override + public final Type getExtension( + final GeneratedExtension extension) { + return getExtension((ExtensionLite) extension); + } + /** Get the value of an extension. */ + @Override + public final Type getExtension( + final Extension> extension, final int index) { + return getExtension((ExtensionLite>) extension, index); + } + /** Get the value of an extension. */ + @Override + public final Type getExtension( + final GeneratedExtension> extension, final int index) { + return getExtension((ExtensionLite>) extension, index); + } + /** Set the value of an extension. */ + public final BuilderType setExtension( + final Extension extension, final Type value) { + return setExtension((ExtensionLite) extension, value); + } + /** Set the value of an extension. */ + public BuilderType setExtension( + final GeneratedExtension extension, final Type value) { + return setExtension((ExtensionLite) extension, value); + } + /** Set the value of one element of a repeated extension. */ + public final BuilderType setExtension( + final Extension> extension, + final int index, final Type value) { + return setExtension((ExtensionLite>) extension, index, value); + } + /** Set the value of one element of a repeated extension. */ + public BuilderType setExtension( + final GeneratedExtension> extension, + final int index, final Type value) { + return setExtension((ExtensionLite>) extension, index, value); + } + /** Append a value to a repeated extension. */ + public final BuilderType addExtension( + final Extension> extension, final Type value) { + return addExtension((ExtensionLite>) extension, value); + } + /** Append a value to a repeated extension. */ + public BuilderType addExtension( + final GeneratedExtension> extension, final Type value) { + return addExtension((ExtensionLite>) extension, value); + } + /** Clear an extension. */ + public final BuilderType clearExtension( + final Extension extension) { + return clearExtension((ExtensionLite) extension); + } + /** Clear an extension. */ + public BuilderType clearExtension( + final GeneratedExtension extension) { + return clearExtension((ExtensionLite) extension); + } + + /** Called by subclasses to check if all extensions are initialized. */ + protected boolean extensionsAreInitialized() { + return extensions.isInitialized(); + } + + /** + * Called by the build code path to create a copy of the extensions for + * building the message. + */ + private FieldSet buildExtensions() { + extensions.makeImmutable(); + return extensions; + } + + @Override + public boolean isInitialized() { + return super.isInitialized() && extensionsAreInitialized(); + } + + /** + * Called by subclasses to parse an unknown field or an extension. + * @return {@code true} unless the tag is an end-group tag. + */ + @Override + protected boolean parseUnknownField( + final CodedInputStream input, + final UnknownFieldSet.Builder unknownFields, + final ExtensionRegistryLite extensionRegistry, + final int tag) throws IOException { + return MessageReflection.mergeFieldFrom( + input, unknownFields, extensionRegistry, getDescriptorForType(), + new MessageReflection.BuilderAdapter(this), tag); + } + + // --------------------------------------------------------------- + // Reflection + + @Override + public Map getAllFields() { + final Map result = super.getAllFieldsMutable(); + result.putAll(extensions.getAllFields()); + return Collections.unmodifiableMap(result); + } + + @Override + public Object getField(final FieldDescriptor field) { + if (field.isExtension()) { + verifyContainingType(field); + final Object value = extensions.getField(field); + if (value == null) { + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + // Lacking an ExtensionRegistry, we have no way to determine the + // extension's real type, so we return a DynamicMessage. + return DynamicMessage.getDefaultInstance(field.getMessageType()); + } else { + return field.getDefaultValue(); + } + } else { + return value; + } + } else { + return super.getField(field); + } + } + + @Override + public int getRepeatedFieldCount(final FieldDescriptor field) { + if (field.isExtension()) { + verifyContainingType(field); + return extensions.getRepeatedFieldCount(field); + } else { + return super.getRepeatedFieldCount(field); + } + } + + @Override + public Object getRepeatedField(final FieldDescriptor field, + final int index) { + if (field.isExtension()) { + verifyContainingType(field); + return extensions.getRepeatedField(field, index); + } else { + return super.getRepeatedField(field, index); + } + } + + @Override + public boolean hasField(final FieldDescriptor field) { + if (field.isExtension()) { + verifyContainingType(field); + return extensions.hasField(field); + } else { + return super.hasField(field); + } + } + + @Override + public BuilderType setField(final FieldDescriptor field, + final Object value) { + if (field.isExtension()) { + verifyContainingType(field); + ensureExtensionsIsMutable(); + extensions.setField(field, value); + onChanged(); + return (BuilderType) this; + } else { + return super.setField(field, value); + } + } + + @Override + public BuilderType clearField(final FieldDescriptor field) { + if (field.isExtension()) { + verifyContainingType(field); + ensureExtensionsIsMutable(); + extensions.clearField(field); + onChanged(); + return (BuilderType) this; + } else { + return super.clearField(field); + } + } + + @Override + public BuilderType setRepeatedField(final FieldDescriptor field, + final int index, final Object value) { + if (field.isExtension()) { + verifyContainingType(field); + ensureExtensionsIsMutable(); + extensions.setRepeatedField(field, index, value); + onChanged(); + return (BuilderType) this; + } else { + return super.setRepeatedField(field, index, value); + } + } + + @Override + public BuilderType addRepeatedField(final FieldDescriptor field, + final Object value) { + if (field.isExtension()) { + verifyContainingType(field); + ensureExtensionsIsMutable(); + extensions.addRepeatedField(field, value); + onChanged(); + return (BuilderType) this; + } else { + return super.addRepeatedField(field, value); + } + } + + protected final void mergeExtensionFields(final ExtendableMessage other) { + ensureExtensionsIsMutable(); + extensions.mergeFrom(other.extensions); + onChanged(); + } + + private void verifyContainingType(final FieldDescriptor field) { + if (field.getContainingType() != getDescriptorForType()) { + throw new IllegalArgumentException( + "FieldDescriptor does not match message type."); + } + } + } + + // ----------------------------------------------------------------- + + /** + * Gets the descriptor for an extension. The implementation depends on whether + * the extension is scoped in the top level of a file or scoped in a Message. + */ + static interface ExtensionDescriptorRetriever { + FieldDescriptor getDescriptor(); + } + + /** For use by generated code only. */ + public static + GeneratedExtension + newMessageScopedGeneratedExtension(final Message scope, + final int descriptorIndex, + final Class singularType, + final Message defaultInstance) { + // For extensions scoped within a Message, we use the Message to resolve + // the outer class's descriptor, from which the extension descriptor is + // obtained. + return new GeneratedExtension( + new CachedDescriptorRetriever() { + @Override + public FieldDescriptor loadDescriptor() { + return scope.getDescriptorForType().getExtensions().get(descriptorIndex); + } + }, + singularType, + defaultInstance, + Extension.ExtensionType.IMMUTABLE); + } + + /** For use by generated code only. */ + public static + GeneratedExtension + newFileScopedGeneratedExtension(final Class singularType, + final Message defaultInstance) { + // For extensions scoped within a file, we rely on the outer class's + // static initializer to call internalInit() on the extension when the + // descriptor is available. + return new GeneratedExtension( + null, // ExtensionDescriptorRetriever is initialized in internalInit(); + singularType, + defaultInstance, + Extension.ExtensionType.IMMUTABLE); + } + + private abstract static class CachedDescriptorRetriever + implements ExtensionDescriptorRetriever { + private volatile FieldDescriptor descriptor; + protected abstract FieldDescriptor loadDescriptor(); + + @Override + public FieldDescriptor getDescriptor() { + if (descriptor == null) { + synchronized (this) { + if (descriptor == null) { + descriptor = loadDescriptor(); + } + } + } + return descriptor; + } + } + + /** + * Used in proto1 generated code only. + * + * After enabling bridge, we can define proto2 extensions (the extended type + * is a proto2 mutable message) in a proto1 .proto file. For these extensions + * we should generate proto2 GeneratedExtensions. + */ + public static + GeneratedExtension + newMessageScopedGeneratedExtension( + final Message scope, final String name, + final Class singularType, final Message defaultInstance) { + // For extensions scoped within a Message, we use the Message to resolve + // the outer class's descriptor, from which the extension descriptor is + // obtained. + return new GeneratedExtension( + new CachedDescriptorRetriever() { + @Override + protected FieldDescriptor loadDescriptor() { + return scope.getDescriptorForType().findFieldByName(name); + } + }, + singularType, + defaultInstance, + Extension.ExtensionType.MUTABLE); + } + + /** + * Used in proto1 generated code only. + * + * After enabling bridge, we can define proto2 extensions (the extended type + * is a proto2 mutable message) in a proto1 .proto file. For these extensions + * we should generate proto2 GeneratedExtensions. + */ + public static + GeneratedExtension + newFileScopedGeneratedExtension( + final Class singularType, final Message defaultInstance, + final String descriptorOuterClass, final String extensionName) { + // For extensions scoped within a file, we load the descriptor outer + // class and rely on it to get the FileDescriptor which then can be + // used to obtain the extension's FieldDescriptor. + return new GeneratedExtension( + new CachedDescriptorRetriever() { + @Override + protected FieldDescriptor loadDescriptor() { + try { + Class clazz = singularType.getClassLoader().loadClass(descriptorOuterClass); + FileDescriptor file = (FileDescriptor) clazz.getField("descriptor").get(null); + return file.findExtensionByName(extensionName); + } catch (Exception e) { + throw new RuntimeException( + "Cannot load descriptors: " + + descriptorOuterClass + + " is not a valid descriptor class name", + e); + } + } + }, + singularType, + defaultInstance, + Extension.ExtensionType.MUTABLE); + } + + /** + * Type used to represent generated extensions. The protocol compiler + * generates a static singleton instance of this class for each extension. + * + *

For example, imagine you have the {@code .proto} file: + * + *

+   * option java_class = "MyProto";
+   *
+   * message Foo {
+   *   extensions 1000 to max;
+   * }
+   *
+   * extend Foo {
+   *   optional int32 bar;
+   * }
+   * 
+ * + *

Then, {@code MyProto.Foo.bar} has type + * {@code GeneratedExtension}. + * + *

In general, users should ignore the details of this type, and simply use + * these static singletons as parameters to the extension accessors defined + * in {@link ExtendableMessage} and {@link ExtendableBuilder}. + */ + public static class GeneratedExtension< + ContainingType extends Message, Type> extends + Extension { + // TODO(kenton): Find ways to avoid using Java reflection within this + // class. Also try to avoid suppressing unchecked warnings. + + // We can't always initialize the descriptor of a GeneratedExtension when + // we first construct it due to initialization order difficulties (namely, + // the descriptor may not have been constructed yet, since it is often + // constructed by the initializer of a separate module). + // + // In the case of nested extensions, we initialize the + // ExtensionDescriptorRetriever with an instance that uses the scoping + // Message's default instance to retrieve the extension's descriptor. + // + // In the case of non-nested extensions, we initialize the + // ExtensionDescriptorRetriever to null and rely on the outer class's static + // initializer to call internalInit() after the descriptor has been parsed. + GeneratedExtension(ExtensionDescriptorRetriever descriptorRetriever, + Class singularType, + Message messageDefaultInstance, + ExtensionType extensionType) { + if (Message.class.isAssignableFrom(singularType) && + !singularType.isInstance(messageDefaultInstance)) { + throw new IllegalArgumentException( + "Bad messageDefaultInstance for " + singularType.getName()); + } + this.descriptorRetriever = descriptorRetriever; + this.singularType = singularType; + this.messageDefaultInstance = messageDefaultInstance; + + if (ProtocolMessageEnum.class.isAssignableFrom(singularType)) { + this.enumValueOf = getMethodOrDie(singularType, "valueOf", + EnumValueDescriptor.class); + this.enumGetValueDescriptor = + getMethodOrDie(singularType, "getValueDescriptor"); + } else { + this.enumValueOf = null; + this.enumGetValueDescriptor = null; + } + this.extensionType = extensionType; + } + + /** For use by generated code only. */ + public void internalInit(final FieldDescriptor descriptor) { + if (descriptorRetriever != null) { + throw new IllegalStateException("Already initialized."); + } + descriptorRetriever = + new ExtensionDescriptorRetriever() { + @Override + public FieldDescriptor getDescriptor() { + return descriptor; + } + }; + } + + private ExtensionDescriptorRetriever descriptorRetriever; + private final Class singularType; + private final Message messageDefaultInstance; + private final Method enumValueOf; + private final Method enumGetValueDescriptor; + private final ExtensionType extensionType; + + @Override + public FieldDescriptor getDescriptor() { + if (descriptorRetriever == null) { + throw new IllegalStateException( + "getDescriptor() called before internalInit()"); + } + return descriptorRetriever.getDescriptor(); + } + + /** + * If the extension is an embedded message or group, returns the default + * instance of the message. + */ + @Override + public Message getMessageDefaultInstance() { + return messageDefaultInstance; + } + + @Override + protected ExtensionType getExtensionType() { + return extensionType; + } + + /** + * Convert from the type used by the reflection accessors to the type used + * by native accessors. E.g., for enums, the reflection accessors use + * EnumValueDescriptors but the native accessors use the generated enum + * type. + */ + @Override + @SuppressWarnings("unchecked") + protected Object fromReflectionType(final Object value) { + FieldDescriptor descriptor = getDescriptor(); + if (descriptor.isRepeated()) { + if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE || + descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { + // Must convert the whole list. + final List result = new ArrayList(); + for (final Object element : (List) value) { + result.add(singularFromReflectionType(element)); + } + return result; + } else { + return value; + } + } else { + return singularFromReflectionType(value); + } + } + + /** + * Like {@link #fromReflectionType(Object)}, but if the type is a repeated + * type, this converts a single element. + */ + @Override + protected Object singularFromReflectionType(final Object value) { + FieldDescriptor descriptor = getDescriptor(); + switch (descriptor.getJavaType()) { + case MESSAGE: + if (singularType.isInstance(value)) { + return value; + } else { + return messageDefaultInstance.newBuilderForType() + .mergeFrom((Message) value).build(); + } + case ENUM: + return invokeOrDie(enumValueOf, null, (EnumValueDescriptor) value); + default: + return value; + } + } + + /** + * Convert from the type used by the native accessors to the type used + * by reflection accessors. E.g., for enums, the reflection accessors use + * EnumValueDescriptors but the native accessors use the generated enum + * type. + */ + @Override + @SuppressWarnings("unchecked") + protected Object toReflectionType(final Object value) { + FieldDescriptor descriptor = getDescriptor(); + if (descriptor.isRepeated()) { + if (descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { + // Must convert the whole list. + final List result = new ArrayList(); + for (final Object element : (List) value) { + result.add(singularToReflectionType(element)); + } + return result; + } else { + return value; + } + } else { + return singularToReflectionType(value); + } + } + + /** + * Like {@link #toReflectionType(Object)}, but if the type is a repeated + * type, this converts a single element. + */ + @Override + protected Object singularToReflectionType(final Object value) { + FieldDescriptor descriptor = getDescriptor(); + switch (descriptor.getJavaType()) { + case ENUM: + return invokeOrDie(enumGetValueDescriptor, value); + default: + return value; + } + } + + @Override + public int getNumber() { + return getDescriptor().getNumber(); + } + + @Override + public WireFormat.FieldType getLiteType() { + return getDescriptor().getLiteType(); + } + + @Override + public boolean isRepeated() { + return getDescriptor().isRepeated(); + } + + @Override + @SuppressWarnings("unchecked") + public Type getDefaultValue() { + if (isRepeated()) { + return (Type) Collections.emptyList(); + } + if (getDescriptor().getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + return (Type) messageDefaultInstance; + } + return (Type) singularFromReflectionType( + getDescriptor().getDefaultValue()); + } + } + + // ================================================================= + + /** Calls Class.getMethod and throws a RuntimeException if it fails. */ + @SuppressWarnings("unchecked") + private static Method getMethodOrDie( + final Class clazz, final String name, final Class... params) { + try { + return clazz.getMethod(name, params); + } catch (NoSuchMethodException e) { + throw new RuntimeException( + "Generated message class \"" + clazz.getName() + + "\" missing method \"" + name + "\".", e); + } + } + + /** Calls invoke and throws a RuntimeException if it fails. */ + private static Object invokeOrDie( + final Method method, final Object object, final Object... params) { + try { + return method.invoke(object, params); + } catch (IllegalAccessException e) { + throw new RuntimeException( + "Couldn't use Java reflection to implement protocol message " + + "reflection.", e); + } catch (InvocationTargetException e) { + final Throwable cause = e.getCause(); + if (cause instanceof RuntimeException) { + throw (RuntimeException) cause; + } else if (cause instanceof Error) { + throw (Error) cause; + } else { + throw new RuntimeException( + "Unexpected exception thrown by generated accessor method.", cause); + } + } + } + + /** + * Gets the map field with the given field number. This method should be + * overridden in the generated message class if the message contains map + * fields. + * + * Unlike other field types, reflection support for map fields can't be + * implemented based on generated public API because we need to access a + * map field as a list in reflection API but the generated API only allows + * us to access it as a map. This method returns the underlying map field + * directly and thus enables us to access the map field as a list. + */ + @SuppressWarnings({"rawtypes", "unused"}) + protected MapField internalGetMapField(int fieldNumber) { + // Note that we can't use descriptor names here because this method will + // be called when descriptor is being initialized. + throw new RuntimeException( + "No map fields found in " + getClass().getName()); + } + + /** + * Users should ignore this class. This class provides the implementation + * with access to the fields of a message object using Java reflection. + */ + public static final class FieldAccessorTable { + + /** + * Construct a FieldAccessorTable for a particular message class. Only + * one FieldAccessorTable should ever be constructed per class. + * + * @param descriptor The type's descriptor. + * @param camelCaseNames The camelcase names of all fields in the message. + * These are used to derive the accessor method names. + * @param messageClass The message type. + * @param builderClass The builder type. + */ + public FieldAccessorTable( + final Descriptor descriptor, + final String[] camelCaseNames, + final Class messageClass, + final Class builderClass) { + this(descriptor, camelCaseNames); + ensureFieldAccessorsInitialized(messageClass, builderClass); + } + + /** + * Construct a FieldAccessorTable for a particular message class without + * initializing FieldAccessors. + */ + public FieldAccessorTable( + final Descriptor descriptor, + final String[] camelCaseNames) { + this.descriptor = descriptor; + this.camelCaseNames = camelCaseNames; + fields = new FieldAccessor[descriptor.getFields().size()]; + oneofs = new OneofAccessor[descriptor.getOneofs().size()]; + initialized = false; + } + + private boolean isMapFieldEnabled(FieldDescriptor field) { + boolean result = true; + return result; + } + + /** + * Ensures the field accessors are initialized. This method is thread-safe. + * + * @param messageClass The message type. + * @param builderClass The builder type. + * @return this + */ + public FieldAccessorTable ensureFieldAccessorsInitialized( + Class messageClass, + Class builderClass) { + if (initialized) { return this; } + synchronized (this) { + if (initialized) { return this; } + int fieldsSize = fields.length; + for (int i = 0; i < fieldsSize; i++) { + FieldDescriptor field = descriptor.getFields().get(i); + String containingOneofCamelCaseName = null; + if (field.getContainingOneof() != null) { + containingOneofCamelCaseName = + camelCaseNames[fieldsSize + field.getContainingOneof().getIndex()]; + } + if (field.isRepeated()) { + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + if (field.isMapField() && isMapFieldEnabled(field)) { + fields[i] = new MapFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass); + } else { + fields[i] = new RepeatedMessageFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass); + } + } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { + fields[i] = new RepeatedEnumFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass); + } else { + fields[i] = new RepeatedFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass); + } + } else { + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + fields[i] = new SingularMessageFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass, + containingOneofCamelCaseName); + } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { + fields[i] = new SingularEnumFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass, + containingOneofCamelCaseName); + } else if (field.getJavaType() == FieldDescriptor.JavaType.STRING) { + fields[i] = new SingularStringFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass, + containingOneofCamelCaseName); + } else { + fields[i] = new SingularFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass, + containingOneofCamelCaseName); + } + } + } + + int oneofsSize = oneofs.length; + for (int i = 0; i < oneofsSize; i++) { + oneofs[i] = new OneofAccessor( + descriptor, camelCaseNames[i + fieldsSize], + messageClass, builderClass); + } + initialized = true; + camelCaseNames = null; + return this; + } + } + + private final Descriptor descriptor; + private final FieldAccessor[] fields; + private String[] camelCaseNames; + private final OneofAccessor[] oneofs; + private volatile boolean initialized; + + /** Get the FieldAccessor for a particular field. */ + private FieldAccessor getField(final FieldDescriptor field) { + if (field.getContainingType() != descriptor) { + throw new IllegalArgumentException( + "FieldDescriptor does not match message type."); + } else if (field.isExtension()) { + // If this type had extensions, it would subclass ExtendableMessage, + // which overrides the reflection interface to handle extensions. + throw new IllegalArgumentException( + "This type does not have extensions."); + } + return fields[field.getIndex()]; + } + + /** Get the OneofAccessor for a particular oneof. */ + private OneofAccessor getOneof(final OneofDescriptor oneof) { + if (oneof.getContainingType() != descriptor) { + throw new IllegalArgumentException( + "OneofDescriptor does not match message type."); + } + return oneofs[oneof.getIndex()]; + } + + /** + * Abstract interface that provides access to a single field. This is + * implemented differently depending on the field type and cardinality. + */ + private interface FieldAccessor { + Object get(GeneratedMessage message); + Object get(GeneratedMessage.Builder builder); + Object getRaw(GeneratedMessage message); + Object getRaw(GeneratedMessage.Builder builder); + void set(Builder builder, Object value); + Object getRepeated(GeneratedMessage message, int index); + Object getRepeated(GeneratedMessage.Builder builder, int index); + Object getRepeatedRaw(GeneratedMessage message, int index); + Object getRepeatedRaw(GeneratedMessage.Builder builder, int index); + void setRepeated(Builder builder, + int index, Object value); + void addRepeated(Builder builder, Object value); + boolean has(GeneratedMessage message); + boolean has(GeneratedMessage.Builder builder); + int getRepeatedCount(GeneratedMessage message); + int getRepeatedCount(GeneratedMessage.Builder builder); + void clear(Builder builder); + Message.Builder newBuilder(); + Message.Builder getBuilder(GeneratedMessage.Builder builder); + Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, + int index); + } + + /** OneofAccessor provides access to a single oneof. */ + private static class OneofAccessor { + OneofAccessor( + final Descriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass) { + this.descriptor = descriptor; + caseMethod = + getMethodOrDie(messageClass, "get" + camelCaseName + "Case"); + caseMethodBuilder = + getMethodOrDie(builderClass, "get" + camelCaseName + "Case"); + clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); + } + + private final Descriptor descriptor; + private final Method caseMethod; + private final Method caseMethodBuilder; + private final Method clearMethod; + + public boolean has(final GeneratedMessage message) { + if (((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() == 0) { + return false; + } + return true; + } + + public boolean has(GeneratedMessage.Builder builder) { + if (((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() == 0) { + return false; + } + return true; + } + + public FieldDescriptor get(final GeneratedMessage message) { + int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); + if (fieldNumber > 0) { + return descriptor.findFieldByNumber(fieldNumber); + } + return null; + } + + public FieldDescriptor get(GeneratedMessage.Builder builder) { + int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); + if (fieldNumber > 0) { + return descriptor.findFieldByNumber(fieldNumber); + } + return null; + } + + public void clear(final Builder builder) { + invokeOrDie(clearMethod, builder); + } + } + + private static boolean supportFieldPresence(FileDescriptor file) { + return file.getSyntax() == FileDescriptor.Syntax.PROTO2; + } + + // --------------------------------------------------------------- + + private static class SingularFieldAccessor implements FieldAccessor { + SingularFieldAccessor( + final FieldDescriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass, + final String containingOneofCamelCaseName) { + field = descriptor; + isOneofField = descriptor.getContainingOneof() != null; + hasHasMethod = supportFieldPresence(descriptor.getFile()) + || (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE); + getMethod = getMethodOrDie(messageClass, "get" + camelCaseName); + getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName); + type = getMethod.getReturnType(); + setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type); + hasMethod = + hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null; + hasMethodBuilder = + hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null; + clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); + caseMethod = isOneofField ? getMethodOrDie( + messageClass, "get" + containingOneofCamelCaseName + "Case") : null; + caseMethodBuilder = isOneofField ? getMethodOrDie( + builderClass, "get" + containingOneofCamelCaseName + "Case") : null; + } + + // Note: We use Java reflection to call public methods rather than + // access private fields directly as this avoids runtime security + // checks. + protected final Class type; + protected final Method getMethod; + protected final Method getMethodBuilder; + protected final Method setMethod; + protected final Method hasMethod; + protected final Method hasMethodBuilder; + protected final Method clearMethod; + protected final Method caseMethod; + protected final Method caseMethodBuilder; + protected final FieldDescriptor field; + protected final boolean isOneofField; + protected final boolean hasHasMethod; + + private int getOneofFieldNumber(final GeneratedMessage message) { + return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); + } + + private int getOneofFieldNumber(final GeneratedMessage.Builder builder) { + return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); + } + + @Override + public Object get(final GeneratedMessage message) { + return invokeOrDie(getMethod, message); + } + @Override + public Object get(GeneratedMessage.Builder builder) { + return invokeOrDie(getMethodBuilder, builder); + } + @Override + public Object getRaw(final GeneratedMessage message) { + return get(message); + } + @Override + public Object getRaw(GeneratedMessage.Builder builder) { + return get(builder); + } + @Override + public void set(final Builder builder, final Object value) { + invokeOrDie(setMethod, builder, value); + } + @Override + public Object getRepeated(final GeneratedMessage message, final int index) { + throw new UnsupportedOperationException( + "getRepeatedField() called on a singular field."); + } + @Override + public Object getRepeatedRaw(final GeneratedMessage message, final int index) { + throw new UnsupportedOperationException( + "getRepeatedFieldRaw() called on a singular field."); + } + @Override + public Object getRepeated(GeneratedMessage.Builder builder, int index) { + throw new UnsupportedOperationException( + "getRepeatedField() called on a singular field."); + } + @Override + public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) { + throw new UnsupportedOperationException( + "getRepeatedFieldRaw() called on a singular field."); + } + @Override + public void setRepeated(final Builder builder, final int index, final Object value) { + throw new UnsupportedOperationException( + "setRepeatedField() called on a singular field."); + } + @Override + public void addRepeated(final Builder builder, final Object value) { + throw new UnsupportedOperationException( + "addRepeatedField() called on a singular field."); + } + @Override + public boolean has(final GeneratedMessage message) { + if (!hasHasMethod) { + if (isOneofField) { + return getOneofFieldNumber(message) == field.getNumber(); + } + return !get(message).equals(field.getDefaultValue()); + } + return (Boolean) invokeOrDie(hasMethod, message); + } +