Fix java compatibilty tests.

Change-Id: I3ff47358e66965cab34736eed2a477ae29f02f61
pull/2234/head
Feng Xiao 8 years ago committed by Bo Yang
parent 9d4657a9e2
commit 04d72c2997
  1. 351
      java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java

@ -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. */

Loading…
Cancel
Save