// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // http://code.google.com/p/protobuf/ // // 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 java.io.IOException; import java.io.ObjectStreamException; import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; /** * Lite version of {@link GeneratedMessage}. * * @author kenton@google.com Kenton Varda */ public abstract class GeneratedMessageLite extends AbstractMessageLite implements Serializable { private static final long serialVersionUID = 1L; protected GeneratedMessageLite() { } protected GeneratedMessageLite(Builder builder) { } @SuppressWarnings("unchecked") public abstract static class Builder<MessageType extends GeneratedMessageLite, BuilderType extends Builder> extends AbstractMessageLite.Builder<BuilderType> { protected Builder() {} //@Override (Java 1.6 override semantics, but we must support 1.5) public BuilderType clear() { return (BuilderType) this; } // 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() { throw new UnsupportedOperationException( "This is supposed to be overridden by subclasses."); } /** All subclasses implement this. */ public abstract BuilderType mergeFrom(MessageType message); // Defined here for return type covariance. public abstract MessageType getDefaultInstanceForType(); /** * 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 ExtensionRegistryLite extensionRegistry, final int tag) throws IOException { return input.skipField(tag); } } // ================================================================= // Extensions-related stuff /** * Lite equivalent of {@link com.google.protobuf.GeneratedMessage.ExtendableMessageOrBuilder}. */ public interface ExtendableMessageOrBuilder< MessageType extends ExtendableMessage> extends MessageLiteOrBuilder { /** Check if a singular extension is present. */ <Type> boolean hasExtension( GeneratedExtension<MessageType, Type> extension); /** Get the number of elements in a repeated extension. */ <Type> int getExtensionCount( GeneratedExtension<MessageType, List<Type>> extension); /** Get the value of an extension. */ <Type> Type getExtension(GeneratedExtension<MessageType, Type> extension); /** Get one element of a repeated extension. */ <Type> Type getExtension( GeneratedExtension<MessageType, List<Type>> extension, int index); } /** * Lite equivalent of {@link GeneratedMessage.ExtendableMessage}. */ public abstract static class ExtendableMessage< MessageType extends ExtendableMessage<MessageType>> extends GeneratedMessageLite implements ExtendableMessageOrBuilder<MessageType> { private final FieldSet<ExtensionDescriptor> extensions; protected ExtendableMessage() { this.extensions = FieldSet.newFieldSet(); } protected ExtendableMessage(ExtendableBuilder<MessageType, ?> builder) { this.extensions = builder.buildExtensions(); } 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 GeneratedExtension<MessageType, Type> extension) { verifyExtensionContainingType(extension); return extensions.hasField(extension.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 GeneratedExtension<MessageType, List<Type>> extension) { verifyExtensionContainingType(extension); return extensions.getRepeatedFieldCount(extension.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 GeneratedExtension<MessageType, Type> extension) { verifyExtensionContainingType(extension); final Object value = extensions.getField(extension.descriptor); if (value == null) { return extension.defaultValue; } else { return (Type) 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 GeneratedExtension<MessageType, List<Type>> extension, final int index) { verifyExtensionContainingType(extension); return (Type) extensions.getRepeatedField(extension.descriptor, index); } /** Called by subclasses to check if all extensions are initialized. */ protected boolean extensionsAreInitialized() { return extensions.isInitialized(); } /** * 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 extends ExtendableBuilder<MessageType, BuilderType>> extends Builder<MessageType, BuilderType> implements ExtendableMessageOrBuilder<MessageType> { protected ExtendableBuilder() {} private FieldSet<ExtensionDescriptor> extensions = FieldSet.emptySet(); private boolean extensionsIsMutable; @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. */ private 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 GeneratedExtension<MessageType, Type> extension) { verifyExtensionContainingType(extension); return extensions.hasField(extension.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 GeneratedExtension<MessageType, List<Type>> extension) { verifyExtensionContainingType(extension); return extensions.getRepeatedFieldCount(extension.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 GeneratedExtension<MessageType, Type> extension) { verifyExtensionContainingType(extension); final Object value = extensions.getField(extension.descriptor); if (value == null) { return extension.defaultValue; } else { return (Type) 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 GeneratedExtension<MessageType, List<Type>> extension, final int index) { verifyExtensionContainingType(extension); return (Type) extensions.getRepeatedField(extension.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() { throw new UnsupportedOperationException( "This is supposed to be overridden by subclasses."); } /** Set the value of an extension. */ public final <Type> BuilderType setExtension( final GeneratedExtension<MessageType, Type> extension, final Type value) { verifyExtensionContainingType(extension); ensureExtensionsIsMutable(); extensions.setField(extension.descriptor, value); return (BuilderType) this; } /** Set the value of one element of a repeated extension. */ public final <Type> BuilderType setExtension( final GeneratedExtension<MessageType, List<Type>> extension, final int index, final Type value) { verifyExtensionContainingType(extension); ensureExtensionsIsMutable(); extensions.setRepeatedField(extension.descriptor, index, value); return (BuilderType) this; } /** Append a value to a repeated extension. */ public final <Type> BuilderType addExtension( final GeneratedExtension<MessageType, List<Type>> extension, final Type value) { verifyExtensionContainingType(extension); ensureExtensionsIsMutable(); extensions.addRepeatedField(extension.descriptor, value); return (BuilderType) this; } /** Clear an extension. */ public final <Type> BuilderType clearExtension( final GeneratedExtension<MessageType, ?> extension) { verifyExtensionContainingType(extension); ensureExtensionsIsMutable(); extensions.clearField(extension.descriptor); return (BuilderType) this; } /** Called by subclasses to check if all extensions are initialized. */ protected boolean extensionsAreInitialized() { return extensions.isInitialized(); } /** * 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 ExtensionRegistryLite extensionRegistry, final int tag) throws IOException { final int wireType = WireFormat.getTagWireType(tag); final int fieldNumber = WireFormat.getTagFieldNumber(tag); final GeneratedExtension<MessageType, ?> extension = extensionRegistry.findLiteExtensionByNumber( getDefaultInstanceForType(), 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 input.skipField(tag); } if (packed) { final int length = input.readRawVarint32(); final int limit = input.pushLimit(length); if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) { while (input.getBytesUntilLimit() > 0) { final int rawValue = input.readEnum(); final 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; } ensureExtensionsIsMutable(); extensions.addRepeatedField(extension.descriptor, value); } } else { while (input.getBytesUntilLimit() > 0) { final Object value = FieldSet.readPrimitiveField(input, extension.descriptor.getLiteType()); ensureExtensionsIsMutable(); extensions.addRepeatedField(extension.descriptor, value); } } input.popLimit(limit); } else { final 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.messageDefaultInstance.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: final int rawValue = input.readEnum(); value = extension.descriptor.getEnumType() .findValueByNumber(rawValue); // If the number isn't recognized as a valid value for this enum, // drop it. if (value == null) { return true; } break; default: value = FieldSet.readPrimitiveField(input, extension.descriptor.getLiteType()); break; } if (extension.descriptor.isRepeated()) { ensureExtensionsIsMutable(); extensions.addRepeatedField(extension.descriptor, value); } else { ensureExtensionsIsMutable(); extensions.setField(extension.descriptor, value); } } return true; } protected final void mergeExtensionFields(final MessageType other) { ensureExtensionsIsMutable(); extensions.mergeFrom(((ExtendableMessage) other).extensions); } } // ----------------------------------------------------------------- /** 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) { return new GeneratedExtension<ContainingType, Type>( containingTypeDefaultInstance, defaultValue, messageDefaultInstance, new ExtensionDescriptor(enumTypeMap, number, type, false /* isRepeated */, false /* isPacked */)); } /** 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) { @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)); } private static final class ExtensionDescriptor implements FieldSet.FieldDescriptorLite< ExtensionDescriptor> { private 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; } private final Internal.EnumLiteMap<?> enumTypeMap; private final int number; private final WireFormat.FieldType type; private final boolean isRepeated; private 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; } } /** * 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 final class GeneratedExtension< ContainingType extends MessageLite, Type> { private GeneratedExtension( final ContainingType containingTypeDefaultInstance, final Type defaultValue, final MessageLite messageDefaultInstance, final ExtensionDescriptor descriptor) { // 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; } private final ContainingType containingTypeDefaultInstance; private final Type defaultValue; private final MessageLite messageDefaultInstance; private final ExtensionDescriptor descriptor; /** * 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, this is the default instance of * that type. */ public MessageLite getMessageDefaultInstance() { return messageDefaultInstance; } } /** * 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 String messageClassName; private 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); Method newBuilder = messageClass.getMethod("newBuilder"); MessageLite.Builder builder = (MessageLite.Builder) newBuilder.invoke(null); builder.mergeFrom(asBytes); return builder.buildPartial(); } catch (ClassNotFoundException e) { throw new RuntimeException("Unable to find proto buffer class", e); } catch (NoSuchMethodException e) { throw new RuntimeException("Unable to find newBuilder method", e); } catch (IllegalAccessException e) { throw new RuntimeException("Unable to call newBuilder method", e); } catch (InvocationTargetException e) { throw new RuntimeException("Error calling newBuilder", e.getCause()); } 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();</code> * @return a SerializedForm of this message */ protected Object writeReplace() throws ObjectStreamException { return new SerializedForm(this); } }