|
|
|
@ -36,6 +36,7 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor; |
|
|
|
|
import com.google.protobuf.Descriptors.FieldDescriptor; |
|
|
|
|
import com.google.protobuf.Descriptors.FileDescriptor; |
|
|
|
|
import com.google.protobuf.Descriptors.OneofDescriptor; |
|
|
|
|
import com.google.protobuf.GeneratedMessage.GeneratedExtension; |
|
|
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.io.InputStream; |
|
|
|
@ -1609,356 +1610,6 @@ public abstract class GeneratedMessageV3 extends AbstractMessage |
|
|
|
|
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. */ |
|
|
|
|