| // 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 com.google.protobuf; |
| |
| import com.google.protobuf.WireFormat.FieldType; |
| |
| import java.io.IOException; |
| 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.concurrent.ConcurrentHashMap; |
| |
| /** |
| * Lite version of {@link GeneratedMessage}. |
| * |
| * @author kenton@google.com Kenton Varda |
| */ |
| public abstract class GeneratedMessageLite< |
| MessageType extends GeneratedMessageLite<MessageType, BuilderType>, |
| BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>> |
| extends AbstractMessageLite |
| implements Serializable { |
| |
| /** |
| * Holds all the {@link PrototypeHolder}s for loaded classes. |
| */ |
| // TODO(dweis): Consider different concurrency values. |
| // TODO(dweis): This will prevent garbage collection of the class loader. |
| // Ideally we'd use something like ClassValue but that's Java 7 only. |
| private static final Map<Class<?>, PrototypeHolder<?, ?>> PROTOTYPE_MAP = |
| new ConcurrentHashMap<Class<?>, PrototypeHolder<?, ?>>(); |
| |
| // For use by generated code only. |
| protected static < |
| MessageType extends GeneratedMessageLite<MessageType, BuilderType>, |
| BuilderType extends GeneratedMessageLite.Builder< |
| MessageType, BuilderType>> void onLoad(Class<MessageType> clazz, |
| PrototypeHolder<MessageType, BuilderType> protoTypeHolder) { |
| PROTOTYPE_MAP.put(clazz, protoTypeHolder); |
| } |
| |
| private static final long serialVersionUID = 1L; |
| |
| /** For use by generated code only. */ |
| protected UnknownFieldSetLite unknownFields; |
| |
| @SuppressWarnings("unchecked") // Guaranteed by runtime. |
| public final Parser<MessageType> getParserForType() { |
| return (Parser<MessageType>) PROTOTYPE_MAP |
| .get(getClass()).getParserForType(); |
| } |
| |
| @SuppressWarnings("unchecked") // Guaranteed by runtime. |
| public final MessageType getDefaultInstanceForType() { |
| return (MessageType) PROTOTYPE_MAP |
| .get(getClass()).getDefaultInstanceForType(); |
| } |
| |
| @SuppressWarnings("unchecked") // Guaranteed by runtime. |
| public final BuilderType newBuilderForType() { |
| return (BuilderType) PROTOTYPE_MAP |
| .get(getClass()).newBuilderForType(); |
| } |
| |
| /** |
| * Called by subclasses to parse an unknown field. For use by generated code |
| * only. |
| * @return {@code true} unless the tag is an end-group tag. |
| */ |
| protected static boolean parseUnknownField( |
| CodedInputStream input, |
| UnknownFieldSetLite.Builder unknownFields, |
| ExtensionRegistryLite extensionRegistry, |
| int tag) throws IOException { |
| return unknownFields.mergeFieldFrom(tag, input); |
| } |
| |
| // The default behavior. If a message has required fields in its subtree, the |
| // generated code will override. |
| public boolean isInitialized() { |
| return true; |
| } |
| |
| @SuppressWarnings("unchecked") |
| public abstract static class Builder< |
| MessageType extends GeneratedMessageLite<MessageType, BuilderType>, |
| BuilderType extends Builder<MessageType, BuilderType>> |
| extends AbstractMessageLite.Builder<BuilderType> { |
| |
| private final MessageType defaultInstance; |
| |
| /** For use by generated code only. */ |
| protected UnknownFieldSetLite unknownFields = |
| UnknownFieldSetLite.getDefaultInstance(); |
| |
| protected Builder(MessageType defaultInstance) { |
| this.defaultInstance = defaultInstance; |
| } |
| |
| // The default behavior. If a message has required fields in its subtree, |
| // the generated code will override. |
| public boolean isInitialized() { |
| return true; |
| } |
| |
| //@Override (Java 1.6 override semantics, but we must support 1.5) |
| public BuilderType clear() { |
| unknownFields = UnknownFieldSetLite.getDefaultInstance(); |
| return (BuilderType) this; |
| } |
| |
| //@Override (Java 1.6 override semantics, but we must support 1.5) |
| public BuilderType clone() { |
| BuilderType builder = |
| (BuilderType) getDefaultInstanceForType().newBuilderForType(); |
| builder.mergeFrom(buildPartial()); |
| return builder; |
| } |
| |
| /** All subclasses implement this. */ |
| public abstract MessageType buildPartial(); |
| |
| //@Override (Java 1.6 override semantics, but we must support 1.5) |
| public final MessageType build() { |
| MessageType result = buildPartial(); |
| if (!result.isInitialized()) { |
| throw newUninitializedMessageException(result); |
| } |
| return result; |
| } |
| |
| /** All subclasses implement this. */ |
| public abstract BuilderType mergeFrom(MessageType message); |
| |
| public MessageType getDefaultInstanceForType() { |
| return defaultInstance; |
| } |
| |
| /** |
| * Called by subclasses to parse an unknown field. |
| * @return {@code true} unless the tag is an end-group tag. |
| */ |
| protected boolean parseUnknownField( |
| CodedInputStream input, |
| UnknownFieldSetLite.Builder unknownFields, |
| ExtensionRegistryLite extensionRegistry, |
| int tag) throws IOException { |
| return unknownFields.mergeFieldFrom(tag, input); |
| } |
| |
| /** |
| * Merge some unknown fields into the {@link UnknownFieldSetLite} for this |
| * message. |
| * |
| * <p>For use by generated code only. |
| */ |
| protected final BuilderType mergeUnknownFields( |
| final UnknownFieldSetLite unknownFields) { |
| this.unknownFields = UnknownFieldSetLite.concat(this.unknownFields, unknownFields); |
| return (BuilderType) this; |
| } |
| |
| public BuilderType mergeFrom( |
| com.google.protobuf.CodedInputStream input, |
| com.google.protobuf.ExtensionRegistryLite extensionRegistry) |
| throws java.io.IOException { |
| MessageType parsedMessage = null; |
| try { |
| parsedMessage = |
| (MessageType) getDefaultInstanceForType().getParserForType().parsePartialFrom( |
| input, extensionRegistry); |
| } catch (com.google.protobuf.InvalidProtocolBufferException e) { |
| parsedMessage = (MessageType) e.getUnfinishedMessage(); |
| throw e; |
| } finally { |
| if (parsedMessage != null) { |
| mergeFrom(parsedMessage); |
| } |
| } |
| return (BuilderType) this; |
| } |
| } |
| |
| |
| // ================================================================= |
| // Extensions-related stuff |
| |
| /** |
| * Lite equivalent of {@link com.google.protobuf.GeneratedMessage.ExtendableMessageOrBuilder}. |
| */ |
| public interface ExtendableMessageOrBuilder< |
| MessageType extends ExtendableMessage<MessageType, BuilderType>, |
| BuilderType extends ExtendableBuilder<MessageType, BuilderType>> |
| extends MessageLiteOrBuilder { |
| |
| /** Check if a singular extension is present. */ |
| <Type> boolean hasExtension( |
| ExtensionLite<MessageType, Type> extension); |
| |
| /** Get the number of elements in a repeated extension. */ |
| <Type> int getExtensionCount( |
| ExtensionLite<MessageType, List<Type>> extension); |
| |
| /** Get the value of an extension. */ |
| <Type> Type getExtension(ExtensionLite<MessageType, Type> extension); |
| |
| /** Get one element of a repeated extension. */ |
| <Type> Type getExtension( |
| ExtensionLite<MessageType, List<Type>> extension, |
| int index); |
| } |
| |
| /** |
| * Lite equivalent of {@link GeneratedMessage.ExtendableMessage}. |
| */ |
| public abstract static class ExtendableMessage< |
| MessageType extends ExtendableMessage<MessageType, BuilderType>, |
| BuilderType extends ExtendableBuilder<MessageType, BuilderType>> |
| extends GeneratedMessageLite<MessageType, BuilderType> |
| implements ExtendableMessageOrBuilder<MessageType, BuilderType> { |
| |
| /** |
| * Represents the set of extensions on this message. For use by generated |
| * code only. |
| */ |
| protected FieldSet<ExtensionDescriptor> extensions = FieldSet.newFieldSet(); |
| |
| // -1 => not memoized, 0 => false, 1 => true. |
| private byte memoizedIsInitialized = -1; |
| |
| // The default behavior. If a message has required fields in its subtree, |
| // the generated code will override. |
| public boolean isInitialized() { |
| if (memoizedIsInitialized == -1) { |
| memoizedIsInitialized = (byte) (extensions.isInitialized() ? 1 : 0); |
| } |
| |
| return memoizedIsInitialized == 1; |
| } |
| |
| private void verifyExtensionContainingType( |
| final GeneratedExtension<MessageType, ?> extension) { |
| if (extension.getContainingTypeDefaultInstance() != |
| getDefaultInstanceForType()) { |
| // This can only happen if someone uses unchecked operations. |
| throw new IllegalArgumentException( |
| "This extension is for a different message type. Please make " + |
| "sure that you are not suppressing any generics type warnings."); |
| } |
| } |
| |
| /** Check if a singular extension is present. */ |
| //@Override (Java 1.6 override semantics, but we must support 1.5) |
| public final <Type> boolean hasExtension( |
| final ExtensionLite<MessageType, Type> extension) { |
| GeneratedExtension<MessageType, Type> extensionLite = |
| checkIsLite(extension); |
| |
| verifyExtensionContainingType(extensionLite); |
| return extensions.hasField(extensionLite.descriptor); |
| } |
| |
| /** Get the number of elements in a repeated extension. */ |
| //@Override (Java 1.6 override semantics, but we must support 1.5) |
| public final <Type> int getExtensionCount( |
| final ExtensionLite<MessageType, List<Type>> extension) { |
| GeneratedExtension<MessageType, List<Type>> extensionLite = |
| checkIsLite(extension); |
| |
| verifyExtensionContainingType(extensionLite); |
| return extensions.getRepeatedFieldCount(extensionLite.descriptor); |
| } |
| |
| /** Get the value of an extension. */ |
| //@Override (Java 1.6 override semantics, but we must support 1.5) |
| @SuppressWarnings("unchecked") |
| public final <Type> Type getExtension( |
| final ExtensionLite<MessageType, Type> extension) { |
| GeneratedExtension<MessageType, Type> extensionLite = |
| checkIsLite(extension); |
| |
| verifyExtensionContainingType(extensionLite); |
| final Object value = extensions.getField(extensionLite.descriptor); |
| if (value == null) { |
| return extensionLite.defaultValue; |
| } else { |
| return (Type) extensionLite.fromFieldSetType(value); |
| } |
| } |
| |
| /** Get one element of a repeated extension. */ |
| //@Override (Java 1.6 override semantics, but we must support 1.5) |
| @SuppressWarnings("unchecked") |
| public final <Type> Type getExtension( |
| final ExtensionLite<MessageType, List<Type>> extension, |
| final int index) { |
| GeneratedExtension<MessageType, List<Type>> extensionLite = |
| checkIsLite(extension); |
| |
| verifyExtensionContainingType(extensionLite); |
| return (Type) extensionLite.singularFromFieldSetType( |
| extensions.getRepeatedField(extensionLite.descriptor, index)); |
| } |
| |
| /** Called by subclasses to check if all extensions are initialized. */ |
| protected boolean extensionsAreInitialized() { |
| return extensions.isInitialized(); |
| } |
| |
| |
| /** |
| * Used by parsing constructors in generated classes. |
| */ |
| protected static void makeExtensionsImmutable( |
| FieldSet<ExtensionDescriptor> extensions) { |
| 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<Map.Entry<ExtensionDescriptor, Object>> iter = |
| extensions.iterator(); |
| private Map.Entry<ExtensionDescriptor, Object> next; |
| private final boolean messageSetWireFormat; |
| |
| private ExtensionWriter(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) { |
| ExtensionDescriptor extension = next.getKey(); |
| if (messageSetWireFormat && extension.getLiteJavaType() == |
| WireFormat.JavaType.MESSAGE && |
| !extension.isRepeated()) { |
| output.writeMessageSetExtension(extension.getNumber(), |
| (MessageLite) next.getValue()); |
| } else { |
| FieldSet.writeField(extension, 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(); |
| } |
| } |
| |
| /** |
| * Lite equivalent of {@link GeneratedMessage.ExtendableBuilder}. |
| */ |
| @SuppressWarnings("unchecked") |
| public abstract static class ExtendableBuilder< |
| MessageType extends ExtendableMessage<MessageType, BuilderType>, |
| BuilderType extends ExtendableBuilder<MessageType, BuilderType>> |
| extends Builder<MessageType, BuilderType> |
| implements ExtendableMessageOrBuilder<MessageType, BuilderType> { |
| protected ExtendableBuilder(MessageType defaultInstance) { |
| super(defaultInstance); |
| } |
| |
| private FieldSet<ExtensionDescriptor> extensions = FieldSet.emptySet(); |
| private boolean extensionsIsMutable; |
| |
| // The default behavior. If a message has required fields in its subtree, |
| // the generated code will override. |
| public boolean isInitialized() { |
| return extensions.isInitialized(); |
| } |
| |
| // For immutable message conversion. |
| void internalSetExtensionSet(FieldSet<ExtensionDescriptor> extensions) { |
| this.extensions = extensions; |
| } |
| |
| @Override |
| public BuilderType clear() { |
| extensions.clear(); |
| extensionsIsMutable = false; |
| return super.clear(); |
| } |
| |
| private void ensureExtensionsIsMutable() { |
| if (!extensionsIsMutable) { |
| extensions = extensions.clone(); |
| extensionsIsMutable = true; |
| } |
| } |
| |
| /** |
| * Called by the build code path to create a copy of the extensions for |
| * building the message. |
| * <p> |
| * For use by generated code only. |
| */ |
| protected final FieldSet<ExtensionDescriptor> buildExtensions() { |
| extensions.makeImmutable(); |
| extensionsIsMutable = false; |
| return extensions; |
| } |
| |
| private void verifyExtensionContainingType( |
| final GeneratedExtension<MessageType, ?> extension) { |
| if (extension.getContainingTypeDefaultInstance() != |
| getDefaultInstanceForType()) { |
| // This can only happen if someone uses unchecked operations. |
| throw new IllegalArgumentException( |
| "This extension is for a different message type. Please make " + |
| "sure that you are not suppressing any generics type warnings."); |
| } |
| } |
| |
| /** Check if a singular extension is present. */ |
| //@Override (Java 1.6 override semantics, but we must support 1.5) |
| public final <Type> boolean hasExtension( |
| final ExtensionLite<MessageType, Type> extension) { |
| GeneratedExtension<MessageType, Type> extensionLite = |
| checkIsLite(extension); |
| |
| verifyExtensionContainingType(extensionLite); |
| return extensions.hasField(extensionLite.descriptor); |
| } |
| |
| /** Get the number of elements in a repeated extension. */ |
| //@Override (Java 1.6 override semantics, but we must support 1.5) |
| public final <Type> int getExtensionCount( |
| final ExtensionLite<MessageType, List<Type>> extension) { |
| GeneratedExtension<MessageType, List<Type>> extensionLite = |
| checkIsLite(extension); |
| |
| verifyExtensionContainingType(extensionLite); |
| return extensions.getRepeatedFieldCount(extensionLite.descriptor); |
| } |
| |
| /** Get the value of an extension. */ |
| //@Override (Java 1.6 override semantics, but we must support 1.5) |
| @SuppressWarnings("unchecked") |
| public final <Type> Type getExtension( |
| final ExtensionLite<MessageType, Type> extension) { |
| GeneratedExtension<MessageType, Type> extensionLite = |
| checkIsLite(extension); |
| |
| verifyExtensionContainingType(extensionLite); |
| final Object value = extensions.getField(extensionLite.descriptor); |
| if (value == null) { |
| return extensionLite.defaultValue; |
| } else { |
| return (Type) extensionLite.fromFieldSetType(value); |
| } |
| } |
| |
| /** Get one element of a repeated extension. */ |
| @SuppressWarnings("unchecked") |
| //@Override (Java 1.6 override semantics, but we must support 1.5) |
| public final <Type> Type getExtension( |
| final ExtensionLite<MessageType, List<Type>> extension, |
| final int index) { |
| GeneratedExtension<MessageType, List<Type>> extensionLite = |
| checkIsLite(extension); |
| |
| verifyExtensionContainingType(extensionLite); |
| return (Type) extensionLite.singularFromFieldSetType( |
| extensions.getRepeatedField(extensionLite.descriptor, index)); |
| } |
| |
| // 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 dummy clone() implementation makes it go away. |
| @Override |
| public BuilderType clone() { |
| return super.clone(); |
| } |
| |
| /** Set the value of an extension. */ |
| public final <Type> BuilderType setExtension( |
| final ExtensionLite<MessageType, Type> extension, |
| final Type value) { |
| GeneratedExtension<MessageType, Type> extensionLite = |
| checkIsLite(extension); |
| |
| verifyExtensionContainingType(extensionLite); |
| ensureExtensionsIsMutable(); |
| extensions.setField(extensionLite.descriptor, |
| extensionLite.toFieldSetType(value)); |
| return (BuilderType) this; |
| } |
| |
| /** Set the value of one element of a repeated extension. */ |
| public final <Type> BuilderType setExtension( |
| final ExtensionLite<MessageType, List<Type>> extension, |
| final int index, final Type value) { |
| GeneratedExtension<MessageType, List<Type>> extensionLite = |
| checkIsLite(extension); |
| |
| verifyExtensionContainingType(extensionLite); |
| ensureExtensionsIsMutable(); |
| extensions.setRepeatedField(extensionLite.descriptor, index, |
| extensionLite.singularToFieldSetType(value)); |
| return (BuilderType) this; |
| } |
| |
| /** Append a value to a repeated extension. */ |
| public final <Type> BuilderType addExtension( |
| final ExtensionLite<MessageType, List<Type>> extension, |
| final Type value) { |
| GeneratedExtension<MessageType, List<Type>> extensionLite = |
| checkIsLite(extension); |
| |
| verifyExtensionContainingType(extensionLite); |
| ensureExtensionsIsMutable(); |
| extensions.addRepeatedField(extensionLite.descriptor, |
| extensionLite.singularToFieldSetType(value)); |
| return (BuilderType) this; |
| } |
| |
| /** Clear an extension. */ |
| public final <Type> BuilderType clearExtension( |
| final ExtensionLite<MessageType, ?> extension) { |
| GeneratedExtension<MessageType, ?> extensionLite = checkIsLite(extension); |
| |
| verifyExtensionContainingType(extensionLite); |
| ensureExtensionsIsMutable(); |
| extensions.clearField(extensionLite.descriptor); |
| return (BuilderType) this; |
| } |
| |
| /** Called by subclasses to check if all extensions are initialized. */ |
| protected boolean extensionsAreInitialized() { |
| return extensions.isInitialized(); |
| } |
| |
| protected final void mergeExtensionFields(final MessageType other) { |
| ensureExtensionsIsMutable(); |
| extensions.mergeFrom(((ExtendableMessage) other).extensions); |
| } |
| } |
| |
| //----------------------------------------------------------------- |
| |
| /** |
| * Parse an unknown field or an extension. For use by generated code only. |
| * @return {@code true} unless the tag is an end-group tag. |
| */ |
| protected static <MessageType extends MessageLite> |
| boolean parseUnknownField( |
| FieldSet<ExtensionDescriptor> extensions, |
| MessageType defaultInstance, |
| CodedInputStream input, |
| UnknownFieldSetLite.Builder unknownFields, |
| ExtensionRegistryLite extensionRegistry, |
| int tag) throws IOException { |
| int wireType = WireFormat.getTagWireType(tag); |
| int fieldNumber = WireFormat.getTagFieldNumber(tag); |
| |
| GeneratedExtension<MessageType, ?> extension = |
| extensionRegistry.findLiteExtensionByNumber( |
| defaultInstance, fieldNumber); |
| |
| boolean unknown = false; |
| boolean packed = false; |
| if (extension == null) { |
| unknown = true; // Unknown field. |
| } else if (wireType == FieldSet.getWireFormatForFieldType( |
| extension.descriptor.getLiteType(), |
| false /* isPacked */)) { |
| packed = false; // Normal, unpacked value. |
| } else if (extension.descriptor.isRepeated && |
| extension.descriptor.type.isPackable() && |
| wireType == FieldSet.getWireFormatForFieldType( |
| extension.descriptor.getLiteType(), |
| true /* isPacked */)) { |
| packed = true; // Packed value. |
| } else { |
| unknown = true; // Wrong wire type. |
| } |
| |
| if (unknown) { // Unknown field or wrong wire type. Skip. |
| return unknownFields.mergeFieldFrom(tag, input); |
| } |
| |
| if (packed) { |
| int length = input.readRawVarint32(); |
| int limit = input.pushLimit(length); |
| if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) { |
| while (input.getBytesUntilLimit() > 0) { |
| int rawValue = input.readEnum(); |
| Object value = |
| extension.descriptor.getEnumType().findValueByNumber(rawValue); |
| if (value == null) { |
| // If the number isn't recognized as a valid value for this |
| // enum, drop it (don't even add it to unknownFields). |
| return true; |
| } |
| extensions.addRepeatedField(extension.descriptor, |
| extension.singularToFieldSetType(value)); |
| } |
| } else { |
| while (input.getBytesUntilLimit() > 0) { |
| Object value = |
| FieldSet.readPrimitiveField(input, |
| extension.descriptor.getLiteType(), |
| /*checkUtf8=*/ false); |
| extensions.addRepeatedField(extension.descriptor, value); |
| } |
| } |
| input.popLimit(limit); |
| } else { |
| Object value; |
| switch (extension.descriptor.getLiteJavaType()) { |
| case MESSAGE: { |
| MessageLite.Builder subBuilder = null; |
| if (!extension.descriptor.isRepeated()) { |
| MessageLite existingValue = |
| (MessageLite) extensions.getField(extension.descriptor); |
| if (existingValue != null) { |
| subBuilder = existingValue.toBuilder(); |
| } |
| } |
| if (subBuilder == null) { |
| subBuilder = extension.getMessageDefaultInstance() |
| .newBuilderForType(); |
| } |
| if (extension.descriptor.getLiteType() == |
| WireFormat.FieldType.GROUP) { |
| input.readGroup(extension.getNumber(), |
| subBuilder, extensionRegistry); |
| } else { |
| input.readMessage(subBuilder, extensionRegistry); |
| } |
| value = subBuilder.build(); |
| break; |
| } |
| case ENUM: |
| int rawValue = input.readEnum(); |
| value = extension.descriptor.getEnumType() |
| .findValueByNumber(rawValue); |
| // If the number isn't recognized as a valid value for this enum, |
| // write it to unknown fields object. |
| if (value == null) { |
| unknownFields.mergeVarintField(fieldNumber, rawValue); |
| return true; |
| } |
| break; |
| default: |
| value = FieldSet.readPrimitiveField(input, |
| extension.descriptor.getLiteType(), |
| /*checkUtf8=*/ false); |
| break; |
| } |
| |
| if (extension.descriptor.isRepeated()) { |
| extensions.addRepeatedField(extension.descriptor, |
| extension.singularToFieldSetType(value)); |
| } else { |
| extensions.setField(extension.descriptor, |
| extension.singularToFieldSetType(value)); |
| } |
| } |
| |
| return true; |
| } |
| |
| // ----------------------------------------------------------------- |
| |
| /** For use by generated code only. */ |
| public static <ContainingType extends MessageLite, Type> |
| GeneratedExtension<ContainingType, Type> |
| newSingularGeneratedExtension( |
| final ContainingType containingTypeDefaultInstance, |
| final Type defaultValue, |
| final MessageLite messageDefaultInstance, |
| final Internal.EnumLiteMap<?> enumTypeMap, |
| final int number, |
| final WireFormat.FieldType type, |
| final Class singularType) { |
| return new GeneratedExtension<ContainingType, Type>( |
| containingTypeDefaultInstance, |
| defaultValue, |
| messageDefaultInstance, |
| new ExtensionDescriptor(enumTypeMap, number, type, |
| false /* isRepeated */, |
| false /* isPacked */), |
| singularType); |
| } |
| |
| /** For use by generated code only. */ |
| public static <ContainingType extends MessageLite, Type> |
| GeneratedExtension<ContainingType, Type> |
| newRepeatedGeneratedExtension( |
| final ContainingType containingTypeDefaultInstance, |
| final MessageLite messageDefaultInstance, |
| final Internal.EnumLiteMap<?> enumTypeMap, |
| final int number, |
| final WireFormat.FieldType type, |
| final boolean isPacked, |
| final Class singularType) { |
| @SuppressWarnings("unchecked") // Subclasses ensure Type is a List |
| Type emptyList = (Type) Collections.emptyList(); |
| return new GeneratedExtension<ContainingType, Type>( |
| containingTypeDefaultInstance, |
| emptyList, |
| messageDefaultInstance, |
| new ExtensionDescriptor( |
| enumTypeMap, number, type, true /* isRepeated */, isPacked), |
| singularType); |
| } |
| |
| static final class ExtensionDescriptor |
| implements FieldSet.FieldDescriptorLite< |
| ExtensionDescriptor> { |
| ExtensionDescriptor( |
| final Internal.EnumLiteMap<?> enumTypeMap, |
| final int number, |
| final WireFormat.FieldType type, |
| final boolean isRepeated, |
| final boolean isPacked) { |
| this.enumTypeMap = enumTypeMap; |
| this.number = number; |
| this.type = type; |
| this.isRepeated = isRepeated; |
| this.isPacked = isPacked; |
| } |
| |
| final Internal.EnumLiteMap<?> enumTypeMap; |
| final int number; |
| final WireFormat.FieldType type; |
| final boolean isRepeated; |
| final boolean isPacked; |
| |
| public int getNumber() { |
| return number; |
| } |
| |
| public WireFormat.FieldType getLiteType() { |
| return type; |
| } |
| |
| public WireFormat.JavaType getLiteJavaType() { |
| return type.getJavaType(); |
| } |
| |
| public boolean isRepeated() { |
| return isRepeated; |
| } |
| |
| public boolean isPacked() { |
| return isPacked; |
| } |
| |
| public Internal.EnumLiteMap<?> getEnumType() { |
| return enumTypeMap; |
| } |
| |
| @SuppressWarnings("unchecked") |
| public MessageLite.Builder internalMergeFrom( |
| MessageLite.Builder to, MessageLite from) { |
| return ((Builder) to).mergeFrom((GeneratedMessageLite) from); |
| } |
| |
| |
| public int compareTo(ExtensionDescriptor other) { |
| return number - other.number; |
| } |
| } |
| |
| // ================================================================= |
| |
| /** Calls Class.getMethod and throws a RuntimeException if it fails. */ |
| @SuppressWarnings("unchecked") |
| static Method getMethodOrDie(Class clazz, String name, 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. */ |
| static Object invokeOrDie(Method method, Object object, 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); |
| } |
| } |
| } |
| |
| /** |
| * Lite equivalent to {@link GeneratedMessage.GeneratedExtension}. |
| * |
| * Users should ignore the contents of this class and only use objects of |
| * this type as parameters to extension accessors and ExtensionRegistry.add(). |
| */ |
| public static class GeneratedExtension< |
| ContainingType extends MessageLite, Type> |
| extends ExtensionLite<ContainingType, Type> { |
| |
| /** |
| * Create a new isntance with the given parameters. |
| * |
| * The last parameter {@code singularType} is only needed for enum types. |
| * We store integer values for enum types in a {@link ExtendableMessage} |
| * and use Java reflection to convert an integer value back into a concrete |
| * enum object. |
| */ |
| GeneratedExtension( |
| final ContainingType containingTypeDefaultInstance, |
| final Type defaultValue, |
| final MessageLite messageDefaultInstance, |
| final ExtensionDescriptor descriptor, |
| Class singularType) { |
| // Defensive checks to verify the correct initialization order of |
| // GeneratedExtensions and their related GeneratedMessages. |
| if (containingTypeDefaultInstance == null) { |
| throw new IllegalArgumentException( |
| "Null containingTypeDefaultInstance"); |
| } |
| if (descriptor.getLiteType() == WireFormat.FieldType.MESSAGE && |
| messageDefaultInstance == null) { |
| throw new IllegalArgumentException( |
| "Null messageDefaultInstance"); |
| } |
| this.containingTypeDefaultInstance = containingTypeDefaultInstance; |
| this.defaultValue = defaultValue; |
| this.messageDefaultInstance = messageDefaultInstance; |
| this.descriptor = descriptor; |
| |
| // Use Java reflection to invoke the static method {@code valueOf} of |
| // enum types in order to convert integers to concrete enum objects. |
| this.singularType = singularType; |
| if (Internal.EnumLite.class.isAssignableFrom(singularType)) { |
| this.enumValueOf = getMethodOrDie( |
| singularType, "valueOf", int.class); |
| } else { |
| this.enumValueOf = null; |
| } |
| } |
| |
| final ContainingType containingTypeDefaultInstance; |
| final Type defaultValue; |
| final MessageLite messageDefaultInstance; |
| final ExtensionDescriptor descriptor; |
| final Class singularType; |
| final Method enumValueOf; |
| |
| /** |
| * Default instance of the type being extended, used to identify that type. |
| */ |
| public ContainingType getContainingTypeDefaultInstance() { |
| return containingTypeDefaultInstance; |
| } |
| |
| /** Get the field number. */ |
| public int getNumber() { |
| return descriptor.getNumber(); |
| } |
| |
| |
| /** |
| * If the extension is an embedded message or group, returns the default |
| * instance of the message. |
| */ |
| public MessageLite getMessageDefaultInstance() { |
| return messageDefaultInstance; |
| } |
| |
| @SuppressWarnings("unchecked") |
| Object fromFieldSetType(final Object value) { |
| if (descriptor.isRepeated()) { |
| if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) { |
| final List result = new ArrayList(); |
| for (final Object element : (List) value) { |
| result.add(singularFromFieldSetType(element)); |
| } |
| return result; |
| } else { |
| return value; |
| } |
| } else { |
| return singularFromFieldSetType(value); |
| } |
| } |
| |
| Object singularFromFieldSetType(final Object value) { |
| if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) { |
| return invokeOrDie(enumValueOf, null, (Integer) value); |
| } else { |
| return value; |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| Object toFieldSetType(final Object value) { |
| if (descriptor.isRepeated()) { |
| if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) { |
| final List result = new ArrayList(); |
| for (final Object element : (List) value) { |
| result.add(singularToFieldSetType(element)); |
| } |
| return result; |
| } else { |
| return value; |
| } |
| } else { |
| return singularToFieldSetType(value); |
| } |
| } |
| |
| Object singularToFieldSetType(final Object value) { |
| if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) { |
| return ((Internal.EnumLite) value).getNumber(); |
| } else { |
| return value; |
| } |
| } |
| |
| public FieldType getLiteType() { |
| return descriptor.getLiteType(); |
| } |
| |
| public boolean isRepeated() { |
| return descriptor.isRepeated; |
| } |
| |
| public Type getDefaultValue() { |
| return defaultValue; |
| } |
| } |
| |
| /** |
| * A serialized (serializable) form of the generated message. Stores the |
| * message as a class name and a byte array. |
| */ |
| static final class SerializedForm implements Serializable { |
| private static final long serialVersionUID = 0L; |
| |
| private final String messageClassName; |
| private final byte[] asBytes; |
| |
| /** |
| * Creates the serialized form by calling {@link com.google.protobuf.MessageLite#toByteArray}. |
| * @param regularForm the message to serialize |
| */ |
| SerializedForm(MessageLite regularForm) { |
| messageClassName = regularForm.getClass().getName(); |
| asBytes = regularForm.toByteArray(); |
| } |
| |
| /** |
| * When read from an ObjectInputStream, this method converts this object |
| * back to the regular form. Part of Java's serialization magic. |
| * @return a GeneratedMessage of the type that was serialized |
| */ |
| @SuppressWarnings("unchecked") |
| protected Object readResolve() throws ObjectStreamException { |
| try { |
| Class messageClass = Class.forName(messageClassName); |
| Parser<?> parser = |
| (Parser<?>) messageClass.getField("PARSER").get(null); |
| return parser.parsePartialFrom(asBytes); |
| } catch (ClassNotFoundException e) { |
| throw new RuntimeException("Unable to find proto buffer class", e); |
| } catch (NoSuchFieldException e) { |
| throw new RuntimeException("Unable to find PARSER", e); |
| } catch (SecurityException e) { |
| throw new RuntimeException("Unable to call PARSER", e); |
| } catch (IllegalAccessException e) { |
| throw new RuntimeException("Unable to call parseFrom method", e); |
| } catch (InvalidProtocolBufferException e) { |
| throw new RuntimeException("Unable to understand proto buffer", e); |
| } |
| } |
| } |
| |
| /** |
| * Replaces this object in the output stream with a serialized form. |
| * Part of Java's serialization magic. Generated sub-classes must override |
| * this method by calling {@code return super.writeReplace();} |
| * @return a SerializedForm of this message |
| */ |
| protected Object writeReplace() throws ObjectStreamException { |
| return new SerializedForm(this); |
| } |
| |
| /** |
| * Checks that the {@link Extension} is Lite and returns it as a |
| * {@link GeneratedExtension}. |
| */ |
| private static < |
| MessageType extends ExtendableMessage<MessageType, BuilderType>, |
| BuilderType extends ExtendableBuilder<MessageType, BuilderType>, |
| T> |
| GeneratedExtension<MessageType, T> checkIsLite( |
| ExtensionLite<MessageType, T> extension) { |
| if (!extension.isLite()) { |
| throw new IllegalArgumentException("Expected a lite extension."); |
| } |
| |
| return (GeneratedExtension<MessageType, T>) extension; |
| } |
| |
| /** |
| * Represents the state needed to implement *ForType methods. Generated code |
| * must provide a static singleton instance by adding it with |
| * {@link GeneratedMessageLite#onLoad(Class, PrototypeHolder)} on class load. |
| * <ul> |
| * <li>{@link #getDefaultInstanceForType()} |
| * <li>{@link #getParserForType()} |
| * <li>{@link #newBuilderForType()} |
| * </ul> |
| * This allows us to trade three generated methods for a static Map. |
| */ |
| protected static class PrototypeHolder< |
| MessageType extends GeneratedMessageLite<MessageType, BuilderType>, |
| BuilderType extends GeneratedMessageLite.Builder< |
| MessageType, BuilderType>> { |
| |
| private final MessageType defaultInstance; |
| private final Parser<MessageType> parser; |
| |
| public PrototypeHolder( |
| MessageType defaultInstance, Parser<MessageType> parser) { |
| this.defaultInstance = defaultInstance; |
| this.parser = parser; |
| } |
| |
| public MessageType getDefaultInstanceForType() { |
| return defaultInstance; |
| } |
| |
| public Parser<MessageType> getParserForType() { |
| return parser; |
| } |
| |
| @SuppressWarnings("unchecked") // Guaranteed by runtime. |
| public BuilderType newBuilderForType() { |
| return (BuilderType) defaultInstance.toBuilder(); |
| } |
| } |
| } |