aboutsummaryrefslogtreecommitdiffhomepage
path: root/java/core
diff options
context:
space:
mode:
authorGravatar Joshua Humphries <jh@squareup.com>2015-10-20 16:24:48 -0400
committerGravatar Joshua Humphries <jh@squareup.com>2016-01-15 21:51:19 -0500
commitf3c75580e4e7b18c372e1f83e4283701c01bcaca (patch)
tree7fc56ae23162f1e90c1dd15cda04f7d4b4f9fe7b /java/core
parent9a5d892e2a2708335a3223d10e268ea932245e15 (diff)
throw IOException instead of InvalidProtocolBufferException when appropriate
Diffstat (limited to 'java/core')
-rw-r--r--java/core/src/main/java/com/google/protobuf/GeneratedMessage.java60
-rw-r--r--java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java12
-rw-r--r--java/core/src/main/java/com/google/protobuf/Parser.java12
3 files changed, 80 insertions, 4 deletions
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
index d84fa75c..ceb97a4e 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -36,15 +36,13 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.Descriptors.OneofDescriptor;
-import com.google.protobuf.GeneratedMessageLite.ExtendableMessage;
-import com.google.protobuf.GeneratedMessageLite.GeneratedExtension;
import java.io.IOException;
+import java.io.InputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
@@ -276,6 +274,60 @@ public abstract class GeneratedMessage extends AbstractMessage
return unknownFields.mergeFieldFrom(tag, input);
}
+ protected static <M extends Message> M parseWithIOException(Parser<M> parser, InputStream input)
+ throws IOException {
+ try {
+ return parser.parseFrom(input);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ protected static <M extends Message> M parseWithIOException(Parser<M> parser, InputStream input,
+ ExtensionRegistryLite extensions) throws IOException {
+ try {
+ return parser.parseFrom(input, extensions);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ protected static <M extends Message> M parseWithIOException(Parser<M> parser,
+ CodedInputStream input) throws IOException {
+ try {
+ return parser.parseFrom(input);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ protected static <M extends Message> M parseWithIOException(Parser<M> parser,
+ CodedInputStream input, ExtensionRegistryLite extensions) throws IOException {
+ try {
+ return parser.parseFrom(input, extensions);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ protected static <M extends Message> M parseDelimitedWithIOException(Parser<M> parser,
+ InputStream input) throws IOException {
+ try {
+ return parser.parseDelimitedFrom(input);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
+ protected static <M extends Message> M parseDelimitedWithIOException(Parser<M> parser,
+ InputStream input, ExtensionRegistryLite extensions) throws IOException {
+ try {
+ return parser.parseDelimitedFrom(input, extensions);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ }
+ }
+
@Override
public void writeTo(final CodedOutputStream output) throws IOException {
MessageReflection.writeMessageTo(this, getAllFieldsRaw(), output, false);
@@ -667,7 +719,7 @@ public abstract class GeneratedMessage extends AbstractMessage
"No map fields found in " + getClass().getName());
}
- /** Like {@link internalGetMapField} but return a mutable version. */
+ /** Like {@link #internalGetMapField} but return a mutable version. */
@SuppressWarnings({"unused", "rawtypes"})
protected MapField internalGetMutableMapField(int fieldNumber) {
// Note that we can't use descriptor names here because this method will
diff --git a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
index 0a761052..85ce7b24 100644
--- a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
+++ b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -46,6 +46,10 @@ public class InvalidProtocolBufferException extends IOException {
super(description);
}
+ public InvalidProtocolBufferException(IOException e) {
+ super(e.getMessage(), e);
+ }
+
/**
* Attaches an unfinished message to the exception to support best-effort
* parsing in {@code Parser} interface.
@@ -66,6 +70,14 @@ public class InvalidProtocolBufferException extends IOException {
return unfinishedMessage;
}
+ /**
+ * Unwraps the underlying {@link IOException} if this exception was caused by an I/O
+ * problem. Otherwise, returns {@code this}.
+ */
+ public IOException unwrapIOException() {
+ return getCause() instanceof IOException ? (IOException) getCause() : this;
+ }
+
static InvalidProtocolBufferException truncatedMessage() {
return new InvalidProtocolBufferException(
"While parsing a protocol message, the input ended unexpectedly " +
diff --git a/java/core/src/main/java/com/google/protobuf/Parser.java b/java/core/src/main/java/com/google/protobuf/Parser.java
index 227c02b7..3fa11c3b 100644
--- a/java/core/src/main/java/com/google/protobuf/Parser.java
+++ b/java/core/src/main/java/com/google/protobuf/Parser.java
@@ -30,6 +30,7 @@
package com.google.protobuf;
+import java.io.IOException;
import java.io.InputStream;
/**
@@ -37,9 +38,20 @@ import java.io.InputStream;
*
* The implementation should be stateless and thread-safe.
*
+ * <p>All methods may throw {@link InvalidProtocolBufferException}. In the event of invalid data,
+ * like an encoding error, the cause of the thrown exception will be {@code null}. However, if an
+ * I/O problem occurs, an exception is thrown with an {@link IOException} cause.
+ *
* @author liujisi@google.com (Pherl Liu)
*/
public interface Parser<MessageType> {
+
+ // NB(jh): Other parts of the protobuf API that parse messages distinguish between an I/O problem
+ // (like failure reading bytes from a socket) and invalid data (encoding error) via the type of
+ // thrown exception. But it would be source-incompatible to make the methods in this interface do
+ // so since they were originally spec'ed to only throw InvalidProtocolBufferException. So callers
+ // must inspect the cause of the exception to distinguish these two cases.
+
/**
* Parses a message of {@code MessageType} from the input.
*