|
@@ -36,6 +36,7 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor;
|
|
import com.google.protobuf.Descriptors.FieldDescriptor;
|
|
import com.google.protobuf.Descriptors.FieldDescriptor;
|
|
import com.google.protobuf.Descriptors.FileDescriptor;
|
|
import com.google.protobuf.Descriptors.FileDescriptor;
|
|
import com.google.protobuf.Descriptors.OneofDescriptor;
|
|
import com.google.protobuf.Descriptors.OneofDescriptor;
|
|
|
|
+import com.google.protobuf.GeneratedMessage.GeneratedExtension;
|
|
|
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.InputStream;
|
|
@@ -1609,356 +1610,6 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
|
|
FieldDescriptor getDescriptor();
|
|
FieldDescriptor getDescriptor();
|
|
}
|
|
}
|
|
|
|
|
|
- /** For use by generated code only. */
|
|
|
|
- public static <ContainingType extends Message, Type>
|
|
|
|
- GeneratedExtension<ContainingType, Type>
|
|
|
|
- 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<ContainingType, Type>(
|
|
|
|
- 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 <ContainingType extends Message, Type>
|
|
|
|
- GeneratedExtension<ContainingType, Type>
|
|
|
|
- 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<ContainingType, Type>(
|
|
|
|
- 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 <ContainingType extends Message, Type>
|
|
|
|
- GeneratedExtension<ContainingType, Type>
|
|
|
|
- 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<ContainingType, Type>(
|
|
|
|
- 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 <ContainingType extends Message, Type>
|
|
|
|
- GeneratedExtension<ContainingType, Type>
|
|
|
|
- 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<ContainingType, Type>(
|
|
|
|
- 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.
|
|
|
|
- *
|
|
|
|
- * <p>For example, imagine you have the {@code .proto} file:
|
|
|
|
- *
|
|
|
|
- * <pre>
|
|
|
|
- * option java_class = "MyProto";
|
|
|
|
- *
|
|
|
|
- * message Foo {
|
|
|
|
- * extensions 1000 to max;
|
|
|
|
- * }
|
|
|
|
- *
|
|
|
|
- * extend Foo {
|
|
|
|
- * optional int32 bar;
|
|
|
|
- * }
|
|
|
|
- * </pre>
|
|
|
|
- *
|
|
|
|
- * <p>Then, {@code MyProto.Foo.bar} has type
|
|
|
|
- * {@code GeneratedExtension<MyProto.Foo, Integer>}.
|
|
|
|
- *
|
|
|
|
- * <p>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<ContainingType, Type> {
|
|
|
|
- // 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. */
|
|
/** Calls Class.getMethod and throws a RuntimeException if it fails. */
|