aboutsummaryrefslogtreecommitdiffhomepage
path: root/java/src/main/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/main/java/com')
-rwxr-xr-xjava/src/main/java/com/google/protobuf/AbstractMessage.java646
-rwxr-xr-xjava/src/main/java/com/google/protobuf/AbstractMessageLite.java384
-rwxr-xr-xjava/src/main/java/com/google/protobuf/AbstractParser.java258
-rwxr-xr-xjava/src/main/java/com/google/protobuf/AbstractProtobufList.java180
-rwxr-xr-xjava/src/main/java/com/google/protobuf/BlockingRpcChannel.java51
-rwxr-xr-xjava/src/main/java/com/google/protobuf/BlockingService.java64
6 files changed, 1583 insertions, 0 deletions
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java
new file mode 100755
index 00000000..7639efcf
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -0,0 +1,646 @@
+// 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.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+import com.google.protobuf.Internal.EnumLite;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A partial implementation of the {@link Message} interface which implements
+ * as many methods of that interface as possible in terms of other methods.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class AbstractMessage
+ // TODO(dweis): Update GeneratedMessage to parameterize with MessageType and BuilderType.
+ extends AbstractMessageLite
+ implements Message {
+
+ @Override
+ public boolean isInitialized() {
+ return MessageReflection.isInitialized(this);
+ }
+
+ /**
+ * Interface for the parent of a Builder that allows the builder to
+ * communicate invalidations back to the parent for use when using nested
+ * builders.
+ */
+ protected interface BuilderParent {
+
+ /**
+ * A builder becomes dirty whenever a field is modified -- including fields
+ * in nested builders -- and becomes clean when build() is called. Thus,
+ * when a builder becomes dirty, all its parents become dirty as well, and
+ * when it becomes clean, all its children become clean. The dirtiness
+ * state is used to invalidate certain cached values.
+ * <br>
+ * To this end, a builder calls markDirty() on its parent whenever it
+ * transitions from clean to dirty. The parent must propagate this call to
+ * its own parent, unless it was already dirty, in which case the
+ * grandparent must necessarily already be dirty as well. The parent can
+ * only transition back to "clean" after calling build() on all children.
+ */
+ void markDirty();
+ }
+
+ /** Create a nested builder. */
+ protected Message.Builder newBuilderForType(BuilderParent parent) {
+ throw new UnsupportedOperationException("Nested builder is not supported for this type.");
+ }
+
+
+ @Override
+ public List<String> findInitializationErrors() {
+ return MessageReflection.findMissingFields(this);
+ }
+
+ @Override
+ public String getInitializationErrorString() {
+ return MessageReflection.delimitWithCommas(findInitializationErrors());
+ }
+
+ /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+ @Override
+ public boolean hasOneof(OneofDescriptor oneof) {
+ throw new UnsupportedOperationException("hasOneof() is not implemented.");
+ }
+
+ /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+ @Override
+ public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
+ throw new UnsupportedOperationException(
+ "getOneofFieldDescriptor() is not implemented.");
+ }
+
+ @Override
+ public final String toString() {
+ return TextFormat.printToString(this);
+ }
+
+ @Override
+ public void writeTo(final CodedOutputStream output) throws IOException {
+ MessageReflection.writeMessageTo(this, getAllFields(), output, false);
+ }
+
+ protected int memoizedSize = -1;
+
+ @Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) {
+ return size;
+ }
+
+ memoizedSize = MessageReflection.getSerializedSize(this, getAllFields());
+ return memoizedSize;
+ }
+
+ @Override
+ public boolean equals(final Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof Message)) {
+ return false;
+ }
+ final Message otherMessage = (Message) other;
+ if (getDescriptorForType() != otherMessage.getDescriptorForType()) {
+ return false;
+ }
+ return compareFields(getAllFields(), otherMessage.getAllFields()) &&
+ getUnknownFields().equals(otherMessage.getUnknownFields());
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = memoizedHashCode;
+ if (hash == 0) {
+ hash = 41;
+ hash = (19 * hash) + getDescriptorForType().hashCode();
+ hash = hashFields(hash, getAllFields());
+ hash = (29 * hash) + getUnknownFields().hashCode();
+ memoizedHashCode = hash;
+ }
+ return hash;
+ }
+
+ private static ByteString toByteString(Object value) {
+ if (value instanceof byte[]) {
+ return ByteString.copyFrom((byte[]) value);
+ } else {
+ return (ByteString) value;
+ }
+ }
+
+ /**
+ * Compares two bytes fields. The parameters must be either a byte array or a
+ * ByteString object. They can be of different type though.
+ */
+ private static boolean compareBytes(Object a, Object b) {
+ if (a instanceof byte[] && b instanceof byte[]) {
+ return Arrays.equals((byte[])a, (byte[])b);
+ }
+ return toByteString(a).equals(toByteString(b));
+ }
+
+ /**
+ * Converts a list of MapEntry messages into a Map used for equals() and
+ * hashCode().
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private static Map convertMapEntryListToMap(List list) {
+ if (list.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ Map result = new HashMap();
+ Iterator iterator = list.iterator();
+ Message entry = (Message) iterator.next();
+ Descriptors.Descriptor descriptor = entry.getDescriptorForType();
+ Descriptors.FieldDescriptor key = descriptor.findFieldByName("key");
+ Descriptors.FieldDescriptor value = descriptor.findFieldByName("value");
+ Object fieldValue = entry.getField(value);
+ if (fieldValue instanceof EnumValueDescriptor) {
+ fieldValue = ((EnumValueDescriptor) fieldValue).getNumber();
+ }
+ result.put(entry.getField(key), fieldValue);
+ while (iterator.hasNext()) {
+ entry = (Message) iterator.next();
+ fieldValue = entry.getField(value);
+ if (fieldValue instanceof EnumValueDescriptor) {
+ fieldValue = ((EnumValueDescriptor) fieldValue).getNumber();
+ }
+ result.put(entry.getField(key), fieldValue);
+ }
+ return result;
+ }
+
+ /**
+ * Compares two map fields. The parameters must be a list of MapEntry
+ * messages.
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private static boolean compareMapField(Object a, Object b) {
+ Map ma = convertMapEntryListToMap((List) a);
+ Map mb = convertMapEntryListToMap((List) b);
+ return MapFieldLite.equals(ma, mb);
+ }
+
+ /**
+ * Compares two set of fields.
+ * This method is used to implement {@link AbstractMessage#equals(Object)}
+ * and {@link AbstractMutableMessage#equals(Object)}. It takes special care
+ * of bytes fields because immutable messages and mutable messages use
+ * different Java type to reprensent a bytes field and this method should be
+ * able to compare immutable messages, mutable messages and also an immutable
+ * message to a mutable message.
+ */
+ static boolean compareFields(Map<FieldDescriptor, Object> a,
+ Map<FieldDescriptor, Object> b) {
+ if (a.size() != b.size()) {
+ return false;
+ }
+ for (FieldDescriptor descriptor : a.keySet()) {
+ if (!b.containsKey(descriptor)) {
+ return false;
+ }
+ Object value1 = a.get(descriptor);
+ Object value2 = b.get(descriptor);
+ if (descriptor.getType() == FieldDescriptor.Type.BYTES) {
+ if (descriptor.isRepeated()) {
+ List list1 = (List) value1;
+ List list2 = (List) value2;
+ if (list1.size() != list2.size()) {
+ return false;
+ }
+ for (int i = 0; i < list1.size(); i++) {
+ if (!compareBytes(list1.get(i), list2.get(i))) {
+ return false;
+ }
+ }
+ } else {
+ // Compares a singular bytes field.
+ if (!compareBytes(value1, value2)) {
+ return false;
+ }
+ }
+ } else if (descriptor.isMapField()) {
+ if (!compareMapField(value1, value2)) {
+ return false;
+ }
+ } else {
+ // Compare non-bytes fields.
+ if (!value1.equals(value2)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Calculates the hash code of a map field. {@code value} must be a list of
+ * MapEntry messages.
+ */
+ @SuppressWarnings("unchecked")
+ private static int hashMapField(Object value) {
+ return MapFieldLite.calculateHashCodeForMap(convertMapEntryListToMap((List) value));
+ }
+
+ /** Get a hash code for given fields and values, using the given seed. */
+ @SuppressWarnings("unchecked")
+ protected static int hashFields(int hash, Map<FieldDescriptor, Object> map) {
+ for (Map.Entry<FieldDescriptor, Object> entry : map.entrySet()) {
+ FieldDescriptor field = entry.getKey();
+ Object value = entry.getValue();
+ hash = (37 * hash) + field.getNumber();
+ if (field.isMapField()) {
+ hash = (53 * hash) + hashMapField(value);
+ } else if (field.getType() != FieldDescriptor.Type.ENUM){
+ hash = (53 * hash) + value.hashCode();
+ } else if (field.isRepeated()) {
+ List<? extends EnumLite> list = (List<? extends EnumLite>) value;
+ hash = (53 * hash) + Internal.hashEnumList(list);
+ } else {
+ hash = (53 * hash) + Internal.hashEnum((EnumLite) value);
+ }
+ }
+ return hash;
+ }
+
+ /**
+ * Package private helper method for AbstractParser to create
+ * UninitializedMessageException with missing field information.
+ */
+ @Override
+ UninitializedMessageException newUninitializedMessageException() {
+ return Builder.newUninitializedMessageException(this);
+ }
+
+ // =================================================================
+
+ /**
+ * A partial implementation of the {@link Message.Builder} interface which
+ * implements as many methods of that interface as possible in terms of
+ * other methods.
+ */
+ @SuppressWarnings("unchecked")
+ public static abstract class Builder<BuilderType extends Builder<BuilderType>>
+ extends AbstractMessageLite.Builder
+ implements Message.Builder {
+ // The compiler produces an error if this is not declared explicitly.
+ @Override
+ public abstract BuilderType clone();
+
+ /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+ @Override
+ public boolean hasOneof(OneofDescriptor oneof) {
+ throw new UnsupportedOperationException("hasOneof() is not implemented.");
+ }
+
+ /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+ @Override
+ public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
+ throw new UnsupportedOperationException(
+ "getOneofFieldDescriptor() is not implemented.");
+ }
+
+ /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+ @Override
+ public BuilderType clearOneof(OneofDescriptor oneof) {
+ throw new UnsupportedOperationException("clearOneof() is not implemented.");
+ }
+
+ @Override
+ public BuilderType clear() {
+ for (final Map.Entry<FieldDescriptor, Object> entry :
+ getAllFields().entrySet()) {
+ clearField(entry.getKey());
+ }
+ return (BuilderType) this;
+ }
+
+ @Override
+ public List<String> findInitializationErrors() {
+ return MessageReflection.findMissingFields(this);
+ }
+
+ @Override
+ public String getInitializationErrorString() {
+ return MessageReflection.delimitWithCommas(findInitializationErrors());
+ }
+
+ @Override
+ protected BuilderType internalMergeFrom(AbstractMessageLite other) {
+ return mergeFrom((Message) other);
+ }
+
+ @Override
+ public BuilderType mergeFrom(final Message other) {
+ if (other.getDescriptorForType() != getDescriptorForType()) {
+ throw new IllegalArgumentException(
+ "mergeFrom(Message) can only merge messages of the same type.");
+ }
+
+ // Note: We don't attempt to verify that other's fields have valid
+ // types. Doing so would be a losing battle. We'd have to verify
+ // all sub-messages as well, and we'd have to make copies of all of
+ // them to insure that they don't change after verification (since
+ // the Message interface itself cannot enforce immutability of
+ // implementations).
+ // TODO(kenton): Provide a function somewhere called makeDeepCopy()
+ // which allows people to make secure deep copies of messages.
+
+ for (final Map.Entry<FieldDescriptor, Object> entry :
+ other.getAllFields().entrySet()) {
+ final FieldDescriptor field = entry.getKey();
+ if (field.isRepeated()) {
+ for (final Object element : (List)entry.getValue()) {
+ addRepeatedField(field, element);
+ }
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ final Message existingValue = (Message)getField(field);
+ if (existingValue == existingValue.getDefaultInstanceForType()) {
+ setField(field, entry.getValue());
+ } else {
+ setField(field,
+ existingValue.newBuilderForType()
+ .mergeFrom(existingValue)
+ .mergeFrom((Message)entry.getValue())
+ .build());
+ }
+ } else {
+ setField(field, entry.getValue());
+ }
+ }
+
+ mergeUnknownFields(other.getUnknownFields());
+
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType mergeFrom(final CodedInputStream input)
+ throws IOException {
+ return mergeFrom(input, ExtensionRegistry.getEmptyRegistry());
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final CodedInputStream input,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ final UnknownFieldSet.Builder unknownFields =
+ UnknownFieldSet.newBuilder(getUnknownFields());
+ while (true) {
+ final int tag = input.readTag();
+ if (tag == 0) {
+ break;
+ }
+
+ MessageReflection.BuilderAdapter builderAdapter =
+ new MessageReflection.BuilderAdapter(this);
+ if (!MessageReflection.mergeFieldFrom(input, unknownFields,
+ extensionRegistry,
+ getDescriptorForType(),
+ builderAdapter,
+ tag)) {
+ // end group tag
+ break;
+ }
+ }
+ setUnknownFields(unknownFields.build());
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
+ setUnknownFields(
+ UnknownFieldSet.newBuilder(getUnknownFields())
+ .mergeFrom(unknownFields)
+ .build());
+ return (BuilderType) this;
+ }
+
+ @Override
+ public Message.Builder getFieldBuilder(final FieldDescriptor field) {
+ throw new UnsupportedOperationException(
+ "getFieldBuilder() called on an unsupported message type.");
+ }
+
+ @Override
+ public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldBuilder() called on an unsupported message type.");
+ }
+
+ @Override
+ public String toString() {
+ return TextFormat.printToString(this);
+ }
+
+ /**
+ * Construct an UninitializedMessageException reporting missing fields in
+ * the given message.
+ */
+ protected static UninitializedMessageException
+ newUninitializedMessageException(Message message) {
+ return new UninitializedMessageException(
+ MessageReflection.findMissingFields(message));
+ }
+
+ /**
+ * Used to support nested builders and called to mark this builder as clean.
+ * Clean builders will propagate the {@link BuilderParent#markDirty()} event
+ * to their parent builders, while dirty builders will not, as their parents
+ * should be dirty already.
+ *
+ * NOTE: Implementations that don't support nested builders don't need to
+ * override this method.
+ */
+ void markClean() {
+ throw new IllegalStateException("Should be overridden by subclasses.");
+ }
+
+ /**
+ * Used to support nested builders and called when this nested builder is
+ * no longer used by its parent builder and should release the reference
+ * to its parent builder.
+ *
+ * NOTE: Implementations that don't support nested builders don't need to
+ * override this method.
+ */
+ void dispose() {
+ throw new IllegalStateException("Should be overridden by subclasses.");
+ }
+
+ // ===============================================================
+ // The following definitions seem to be required in order to make javac
+ // not produce weird errors like:
+ //
+ // java/com/google/protobuf/DynamicMessage.java:203: types
+ // com.google.protobuf.AbstractMessage.Builder<
+ // com.google.protobuf.DynamicMessage.Builder> and
+ // com.google.protobuf.AbstractMessage.Builder<
+ // com.google.protobuf.DynamicMessage.Builder> are incompatible; both
+ // define mergeFrom(com.google.protobuf.ByteString), but with unrelated
+ // return types.
+ //
+ // Strangely, these lines are only needed if javac is invoked separately
+ // on AbstractMessage.java and AbstractMessageLite.java. If javac is
+ // invoked on both simultaneously, it works. (Or maybe the important
+ // point is whether or not DynamicMessage.java is compiled together with
+ // AbstractMessageLite.java -- not sure.) I suspect this is a compiler
+ // bug.
+
+ @Override
+ public BuilderType mergeFrom(final ByteString data)
+ throws InvalidProtocolBufferException {
+ return (BuilderType) super.mergeFrom(data);
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final ByteString data,
+ final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return (BuilderType) super.mergeFrom(data, extensionRegistry);
+ }
+
+ @Override
+ public BuilderType mergeFrom(final byte[] data)
+ throws InvalidProtocolBufferException {
+ return (BuilderType) super.mergeFrom(data);
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final byte[] data, final int off, final int len)
+ throws InvalidProtocolBufferException {
+ return (BuilderType) super.mergeFrom(data, off, len);
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final byte[] data,
+ final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return (BuilderType) super.mergeFrom(data, extensionRegistry);
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final byte[] data, final int off, final int len,
+ final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return (BuilderType) super.mergeFrom(data, off, len, extensionRegistry);
+ }
+
+ @Override
+ public BuilderType mergeFrom(final InputStream input)
+ throws IOException {
+ return (BuilderType) super.mergeFrom(input);
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final InputStream input,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ return (BuilderType) super.mergeFrom(input, extensionRegistry);
+ }
+
+ @Override
+ public boolean mergeDelimitedFrom(final InputStream input)
+ throws IOException {
+ return super.mergeDelimitedFrom(input);
+ }
+
+ @Override
+ public boolean mergeDelimitedFrom(
+ final InputStream input,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ return super.mergeDelimitedFrom(input, extensionRegistry);
+ }
+ }
+
+ /**
+ * @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1
+ * generated code.
+ */
+ @Deprecated
+ protected static int hashLong(long n) {
+ return (int) (n ^ (n >>> 32));
+ }
+ //
+ /**
+ * @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1
+ * generated code.
+ */
+ @Deprecated
+ protected static int hashBoolean(boolean b) {
+ return b ? 1231 : 1237;
+ }
+ //
+ /**
+ * @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1
+ * generated code.
+ */
+ @Deprecated
+ protected static int hashEnum(EnumLite e) {
+ return e.getNumber();
+ }
+ //
+ /**
+ * @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1
+ * generated code.
+ */
+ @Deprecated
+ protected static int hashEnumList(List<? extends EnumLite> list) {
+ int hash = 1;
+ for (EnumLite e : list) {
+ hash = 31 * hash + hashEnum(e);
+ }
+ return hash;
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
new file mode 100755
index 00000000..046030f3
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
@@ -0,0 +1,384 @@
+// 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 java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+
+/**
+ * A partial implementation of the {@link MessageLite} interface which
+ * implements as many methods of that interface as possible in terms of other
+ * methods.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class AbstractMessageLite<
+ MessageType extends AbstractMessageLite<MessageType, BuilderType>,
+ BuilderType extends AbstractMessageLite.Builder<MessageType, BuilderType>>
+ implements MessageLite {
+ protected int memoizedHashCode = 0;
+
+ @Override
+ public ByteString toByteString() {
+ try {
+ final ByteString.CodedBuilder out =
+ ByteString.newCodedBuilder(getSerializedSize());
+ writeTo(out.getCodedOutput());
+ return out.build();
+ } catch (IOException e) {
+ throw new RuntimeException(getSerializingExceptionMessage("ByteString"), e);
+ }
+ }
+
+ @Override
+ public byte[] toByteArray() {
+ try {
+ final byte[] result = new byte[getSerializedSize()];
+ final CodedOutputStream output = CodedOutputStream.newInstance(result);
+ writeTo(output);
+ output.checkNoSpaceLeft();
+ return result;
+ } catch (IOException e) {
+ throw new RuntimeException(getSerializingExceptionMessage("byte array"), e);
+ }
+ }
+
+ @Override
+ public void writeTo(final OutputStream output) throws IOException {
+ final int bufferSize =
+ CodedOutputStream.computePreferredBufferSize(getSerializedSize());
+ final CodedOutputStream codedOutput =
+ CodedOutputStream.newInstance(output, bufferSize);
+ writeTo(codedOutput);
+ codedOutput.flush();
+ }
+
+ @Override
+ public void writeDelimitedTo(final OutputStream output) throws IOException {
+ final int serialized = getSerializedSize();
+ final int bufferSize = CodedOutputStream.computePreferredBufferSize(
+ CodedOutputStream.computeRawVarint32Size(serialized) + serialized);
+ final CodedOutputStream codedOutput =
+ CodedOutputStream.newInstance(output, bufferSize);
+ codedOutput.writeRawVarint32(serialized);
+ writeTo(codedOutput);
+ codedOutput.flush();
+ }
+
+
+ /**
+ * Package private helper method for AbstractParser to create
+ * UninitializedMessageException.
+ */
+ UninitializedMessageException newUninitializedMessageException() {
+ return new UninitializedMessageException(this);
+ }
+
+ private String getSerializingExceptionMessage(String target) {
+ return "Serializing " + getClass().getName() + " to a " + target
+ + " threw an IOException (should never happen).";
+ }
+
+ protected static void checkByteStringIsUtf8(ByteString byteString)
+ throws IllegalArgumentException {
+ if (!byteString.isValidUtf8()) {
+ throw new IllegalArgumentException("Byte string is not UTF-8.");
+ }
+ }
+
+ protected static <T> void addAll(final Iterable<T> values,
+ final Collection<? super T> list) {
+ Builder.addAll(values, list);
+ }
+
+ /**
+ * A partial implementation of the {@link Message.Builder} interface which
+ * implements as many methods of that interface as possible in terms of
+ * other methods.
+ */
+ @SuppressWarnings("unchecked")
+ public abstract static class Builder<
+ MessageType extends AbstractMessageLite<MessageType, BuilderType>,
+ BuilderType extends Builder<MessageType, BuilderType>>
+ implements MessageLite.Builder {
+ // The compiler produces an error if this is not declared explicitly.
+ @Override
+ public abstract BuilderType clone();
+
+ @Override
+ public BuilderType mergeFrom(final CodedInputStream input) throws IOException {
+ return mergeFrom(input, ExtensionRegistryLite.getEmptyRegistry());
+ }
+
+ // Re-defined here for return type covariance.
+ @Override
+ public abstract BuilderType mergeFrom(
+ final CodedInputStream input, final ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ @Override
+ public BuilderType mergeFrom(final ByteString data) throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input = data.newCodedInput();
+ mergeFrom(input);
+ input.checkLastTagWas(0);
+ return (BuilderType) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(getReadingExceptionMessage("ByteString"), e);
+ }
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final ByteString data, final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input = data.newCodedInput();
+ mergeFrom(input, extensionRegistry);
+ input.checkLastTagWas(0);
+ return (BuilderType) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(getReadingExceptionMessage("ByteString"), e);
+ }
+ }
+
+ @Override
+ public BuilderType mergeFrom(final byte[] data) throws InvalidProtocolBufferException {
+ return mergeFrom(data, 0, data.length);
+ }
+
+ @Override
+ public BuilderType mergeFrom(final byte[] data, final int off, final int len)
+ throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input =
+ CodedInputStream.newInstance(data, off, len);
+ mergeFrom(input);
+ input.checkLastTagWas(0);
+ return (BuilderType) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(getReadingExceptionMessage("byte array"), e);
+ }
+ }
+
+ @Override
+ public BuilderType mergeFrom(final byte[] data, final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return mergeFrom(data, 0, data.length, extensionRegistry);
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final byte[] data,
+ final int off,
+ final int len,
+ final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input =
+ CodedInputStream.newInstance(data, off, len);
+ mergeFrom(input, extensionRegistry);
+ input.checkLastTagWas(0);
+ return (BuilderType) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(getReadingExceptionMessage("byte array"), e);
+ }
+ }
+
+ @Override
+ public BuilderType mergeFrom(final InputStream input) throws IOException {
+ final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+ mergeFrom(codedInput);
+ codedInput.checkLastTagWas(0);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
+ final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+ mergeFrom(codedInput, extensionRegistry);
+ codedInput.checkLastTagWas(0);
+ return (BuilderType) this;
+ }
+
+ /**
+ * An InputStream implementations which reads from some other InputStream
+ * but is limited to a particular number of bytes. Used by
+ * mergeDelimitedFrom(). This is intentionally package-private so that
+ * UnknownFieldSet can share it.
+ */
+ static final class LimitedInputStream extends FilterInputStream {
+ private int limit;
+
+ LimitedInputStream(InputStream in, int limit) {
+ super(in);
+ this.limit = limit;
+ }
+
+ @Override
+ public int available() throws IOException {
+ return Math.min(super.available(), limit);
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (limit <= 0) {
+ return -1;
+ }
+ final int result = super.read();
+ if (result >= 0) {
+ --limit;
+ }
+ return result;
+ }
+
+ @Override
+ public int read(final byte[] b, final int off, int len)
+ throws IOException {
+ if (limit <= 0) {
+ return -1;
+ }
+ len = Math.min(len, limit);
+ final int result = super.read(b, off, len);
+ if (result >= 0) {
+ limit -= result;
+ }
+ return result;
+ }
+
+ @Override
+ public long skip(final long n) throws IOException {
+ final long result = super.skip(Math.min(n, limit));
+ if (result >= 0) {
+ limit -= result;
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public boolean mergeDelimitedFrom(
+ final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
+ final int firstByte = input.read();
+ if (firstByte == -1) {
+ return false;
+ }
+ final int size = CodedInputStream.readRawVarint32(firstByte, input);
+ final InputStream limitedInput = new LimitedInputStream(input, size);
+ mergeFrom(limitedInput, extensionRegistry);
+ return true;
+ }
+
+ @Override
+ public boolean mergeDelimitedFrom(final InputStream input) throws IOException {
+ return mergeDelimitedFrom(input,
+ ExtensionRegistryLite.getEmptyRegistry());
+ }
+
+ @Override
+ @SuppressWarnings("unchecked") // isInstance takes care of this
+ public BuilderType mergeFrom(final MessageLite other) {
+ if (!getDefaultInstanceForType().getClass().isInstance(other)) {
+ throw new IllegalArgumentException(
+ "mergeFrom(MessageLite) can only merge messages of the same type.");
+ }
+
+ return internalMergeFrom((MessageType) other);
+ }
+
+ protected abstract BuilderType internalMergeFrom(MessageType message);
+
+ private String getReadingExceptionMessage(String target) {
+ return "Reading " + getClass().getName() + " from a " + target
+ + " threw an IOException (should never happen).";
+ }
+
+ /**
+ * Construct an UninitializedMessageException reporting missing fields in
+ * the given message.
+ */
+ protected static UninitializedMessageException
+ newUninitializedMessageException(MessageLite message) {
+ return new UninitializedMessageException(message);
+ }
+
+ /**
+ * Adds the {@code values} to the {@code list}. This is a helper method
+ * used by generated code. Users should ignore it.
+ *
+ * @throws NullPointerException if {@code values} or any of the elements of
+ * {@code values} is null. When that happens, some elements of
+ * {@code values} may have already been added to the result {@code list}.
+ */
+ protected static <T> void addAll(final Iterable<T> values,
+ final Collection<? super T> list) {
+ if (values == null) {
+ throw new NullPointerException();
+ }
+ if (values instanceof LazyStringList) {
+ // For StringOrByteStringLists, check the underlying elements to avoid
+ // forcing conversions of ByteStrings to Strings.
+ checkForNullValues(((LazyStringList) values).getUnderlyingElements());
+ list.addAll((Collection<T>) values);
+ } else if (values instanceof Collection) {
+ checkForNullValues(values);
+ list.addAll((Collection<T>) values);
+ } else {
+ for (final T value : values) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ list.add(value);
+ }
+ }
+ }
+
+ private static void checkForNullValues(final Iterable<?> values) {
+ for (final Object value : values) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ }
+ }
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/AbstractParser.java b/java/src/main/java/com/google/protobuf/AbstractParser.java
new file mode 100755
index 00000000..66b0ee3b
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/AbstractParser.java
@@ -0,0 +1,258 @@
+// 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.AbstractMessageLite.Builder.LimitedInputStream;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A partial implementation of the {@link Parser} interface which implements
+ * as many methods of that interface as possible in terms of other methods.
+ *
+ * Note: This class implements all the convenience methods in the
+ * {@link Parser} interface. See {@link Parser} for related javadocs.
+ * Subclasses need to implement
+ * {@link Parser#parsePartialFrom(CodedInputStream, ExtensionRegistryLite)}
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+public abstract class AbstractParser<MessageType extends MessageLite>
+ implements Parser<MessageType> {
+ /**
+ * Creates an UninitializedMessageException for MessageType.
+ */
+ private UninitializedMessageException
+ newUninitializedMessageException(MessageType message) {
+ if (message instanceof AbstractMessageLite) {
+ return ((AbstractMessageLite) message).newUninitializedMessageException();
+ }
+ return new UninitializedMessageException(message);
+ }
+
+ /**
+ * Helper method to check if message is initialized.
+ *
+ * @throws InvalidProtocolBufferException if it is not initialized.
+ * @return The message to check.
+ */
+ private MessageType checkMessageInitialized(MessageType message)
+ throws InvalidProtocolBufferException {
+ if (message != null && !message.isInitialized()) {
+ throw newUninitializedMessageException(message)
+ .asInvalidProtocolBufferException()
+ .setUnfinishedMessage(message);
+ }
+ return message;
+ }
+
+ private static final ExtensionRegistryLite EMPTY_REGISTRY
+ = ExtensionRegistryLite.getEmptyRegistry();
+
+ @Override
+ public MessageType parsePartialFrom(CodedInputStream input)
+ throws InvalidProtocolBufferException {
+ return parsePartialFrom(input, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parseFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialFrom(input, extensionRegistry));
+ }
+
+ @Override
+ public MessageType parseFrom(CodedInputStream input) throws InvalidProtocolBufferException {
+ return parseFrom(input, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parsePartialFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ MessageType message;
+ try {
+ CodedInputStream input = data.newCodedInput();
+ message = parsePartialFrom(input, extensionRegistry);
+ try {
+ input.checkLastTagWas(0);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(message);
+ }
+ return message;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ }
+ }
+
+ @Override
+ public MessageType parsePartialFrom(ByteString data) throws InvalidProtocolBufferException {
+ return parsePartialFrom(data, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parseFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(parsePartialFrom(data, extensionRegistry));
+ }
+
+ @Override
+ public MessageType parseFrom(ByteString data) throws InvalidProtocolBufferException {
+ return parseFrom(data, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parsePartialFrom(
+ byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ try {
+ CodedInputStream input = CodedInputStream.newInstance(data, off, len);
+ MessageType message = parsePartialFrom(input, extensionRegistry);
+ try {
+ input.checkLastTagWas(0);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(message);
+ }
+ return message;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ }
+ }
+
+ @Override
+ public MessageType parsePartialFrom(byte[] data, int off, int len)
+ throws InvalidProtocolBufferException {
+ return parsePartialFrom(data, off, len, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parsePartialFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return parsePartialFrom(data, 0, data.length, extensionRegistry);
+ }
+
+ @Override
+ public MessageType parsePartialFrom(byte[] data) throws InvalidProtocolBufferException {
+ return parsePartialFrom(data, 0, data.length, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parseFrom(
+ byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialFrom(data, off, len, extensionRegistry));
+ }
+
+ @Override
+ public MessageType parseFrom(byte[] data, int off, int len)
+ throws InvalidProtocolBufferException {
+ return parseFrom(data, off, len, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parseFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return parseFrom(data, 0, data.length, extensionRegistry);
+ }
+
+ @Override
+ public MessageType parseFrom(byte[] data) throws InvalidProtocolBufferException {
+ return parseFrom(data, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parsePartialFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ CodedInputStream codedInput = CodedInputStream.newInstance(input);
+ MessageType message = parsePartialFrom(codedInput, extensionRegistry);
+ try {
+ codedInput.checkLastTagWas(0);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(message);
+ }
+ return message;
+ }
+
+ @Override
+ public MessageType parsePartialFrom(InputStream input) throws InvalidProtocolBufferException {
+ return parsePartialFrom(input, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parseFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialFrom(input, extensionRegistry));
+ }
+
+ @Override
+ public MessageType parseFrom(InputStream input) throws InvalidProtocolBufferException {
+ return parseFrom(input, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parsePartialDelimitedFrom(
+ InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ int size;
+ try {
+ int firstByte = input.read();
+ if (firstByte == -1) {
+ return null;
+ }
+ size = CodedInputStream.readRawVarint32(firstByte, input);
+ } catch (IOException e) {
+ throw new InvalidProtocolBufferException(e.getMessage());
+ }
+ InputStream limitedInput = new LimitedInputStream(input, size);
+ return parsePartialFrom(limitedInput, extensionRegistry);
+ }
+
+ @Override
+ public MessageType parsePartialDelimitedFrom(InputStream input)
+ throws InvalidProtocolBufferException {
+ return parsePartialDelimitedFrom(input, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parseDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialDelimitedFrom(input, extensionRegistry));
+ }
+
+ @Override
+ public MessageType parseDelimitedFrom(InputStream input) throws InvalidProtocolBufferException {
+ return parseDelimitedFrom(input, EMPTY_REGISTRY);
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/AbstractProtobufList.java b/java/src/main/java/com/google/protobuf/AbstractProtobufList.java
new file mode 100755
index 00000000..b17db6e0
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/AbstractProtobufList.java
@@ -0,0 +1,180 @@
+// 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.Internal.ProtobufList;
+
+import java.util.AbstractList;
+import java.util.Collection;
+import java.util.List;
+import java.util.RandomAccess;
+
+/**
+ * An abstract implementation of {@link ProtobufList} which manages mutability semantics. All mutate
+ * methods must check if the list is mutable before proceeding. Subclasses must invoke
+ * {@link #ensureIsMutable()} manually when overriding those methods.
+ * <p>
+ * This implementation assumes all subclasses are array based, supporting random access.
+ */
+abstract class AbstractProtobufList<E> extends AbstractList<E> implements ProtobufList<E> {
+
+ protected static final int DEFAULT_CAPACITY = 10;
+
+ /**
+ * Whether or not this list is modifiable.
+ */
+ private boolean isMutable;
+
+ /**
+ * Constructs a mutable list by default.
+ */
+ AbstractProtobufList() {
+ isMutable = true;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof List)) {
+ return false;
+ }
+ // Handle lists that do not support RandomAccess as efficiently as possible by using an iterator
+ // based approach in our super class. Otherwise our index based approach will avoid those
+ // allocations.
+ if (!(o instanceof RandomAccess)) {
+ return super.equals(o);
+ }
+
+ List<?> other = (List<?>) o;
+ final int size = size();
+ if (size != other.size()) {
+ return false;
+ }
+ for (int i = 0; i < size; i++) {
+ if (!get(i).equals(other.get(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ final int size = size();
+ int hashCode = 1;
+ for (int i = 0; i < size; i++) {
+ hashCode = (31 * hashCode) + get(i).hashCode();
+ }
+ return hashCode;
+ }
+
+ @Override
+ public boolean add(E e) {
+ ensureIsMutable();
+ return super.add(e);
+ }
+
+ @Override
+ public void add(int index, E element) {
+ ensureIsMutable();
+ super.add(index, element);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends E> c) {
+ ensureIsMutable();
+ return super.addAll(c);
+ }
+
+ @Override
+ public boolean addAll(int index, Collection<? extends E> c) {
+ ensureIsMutable();
+ return super.addAll(index, c);
+ }
+
+ @Override
+ public void clear() {
+ ensureIsMutable();
+ super.clear();
+ }
+
+ @Override
+ public boolean isModifiable() {
+ return isMutable;
+ }
+
+ @Override
+ public final void makeImmutable() {
+ isMutable = false;
+ }
+
+ @Override
+ public E remove(int index) {
+ ensureIsMutable();
+ return super.remove(index);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ ensureIsMutable();
+ return super.remove(o);
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ ensureIsMutable();
+ return super.removeAll(c);
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ ensureIsMutable();
+ return super.retainAll(c);
+ }
+
+ @Override
+ public E set(int index, E element) {
+ ensureIsMutable();
+ return super.set(index, element);
+ }
+
+ /**
+ * Throws an {@link UnsupportedOperationException} if the list is immutable. Subclasses are
+ * responsible for invoking this method on mutate operations.
+ */
+ protected void ensureIsMutable() {
+ if (!isMutable) {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/BlockingRpcChannel.java b/java/src/main/java/com/google/protobuf/BlockingRpcChannel.java
new file mode 100755
index 00000000..d535efb9
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/BlockingRpcChannel.java
@@ -0,0 +1,51 @@
+// 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;
+
+/**
+ * <p>Abstract interface for a blocking RPC channel. {@code BlockingRpcChannel}
+ * is the blocking equivalent to {@link RpcChannel}.
+ *
+ * @author kenton@google.com Kenton Varda
+ * @author cpovirk@google.com Chris Povirk
+ */
+public interface BlockingRpcChannel {
+ /**
+ * Call the given method of the remote service and blocks until it returns.
+ * {@code callBlockingMethod()} is the blocking equivalent to
+ * {@link RpcChannel#callMethod}.
+ */
+ Message callBlockingMethod(
+ Descriptors.MethodDescriptor method,
+ RpcController controller,
+ Message request,
+ Message responsePrototype) throws ServiceException;
+}
diff --git a/java/src/main/java/com/google/protobuf/BlockingService.java b/java/src/main/java/com/google/protobuf/BlockingService.java
new file mode 100755
index 00000000..d01f0b8f
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/BlockingService.java
@@ -0,0 +1,64 @@
+// 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;
+
+/**
+ * Blocking equivalent to {@link Service}.
+ *
+ * @author kenton@google.com Kenton Varda
+ * @author cpovirk@google.com Chris Povirk
+ */
+public interface BlockingService {
+ /**
+ * Equivalent to {@link Service#getDescriptorForType}.
+ */
+ Descriptors.ServiceDescriptor getDescriptorForType();
+
+ /**
+ * Equivalent to {@link Service#callMethod}, except that
+ * {@code callBlockingMethod()} returns the result of the RPC or throws a
+ * {@link ServiceException} if there is a failure, rather than passing the
+ * information to a callback.
+ */
+ Message callBlockingMethod(Descriptors.MethodDescriptor method,
+ RpcController controller,
+ Message request) throws ServiceException;
+
+ /**
+ * Equivalent to {@link Service#getRequestPrototype}.
+ */
+ Message getRequestPrototype(Descriptors.MethodDescriptor method);
+
+ /**
+ * Equivalent to {@link Service#getResponsePrototype}.
+ */
+ Message getResponsePrototype(Descriptors.MethodDescriptor method);
+}