diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/BaseServiceException.java b/gcloud-java-core/src/main/java/com/google/gcloud/BaseServiceException.java index 579340f1256e..365243904436 100644 --- a/gcloud-java-core/src/main/java/com/google/gcloud/BaseServiceException.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/BaseServiceException.java @@ -97,13 +97,17 @@ public BaseServiceException(IOException exception, boolean idempotent) { String debugInfo = null; if (exception instanceof GoogleJsonResponseException) { GoogleJsonError jsonError = ((GoogleJsonResponseException) exception).getDetails(); - Error error = error(jsonError); - code = error.code; - reason = error.reason; - if (reason != null) { - GoogleJsonError.ErrorInfo errorInfo = jsonError.getErrors().get(0); - location = errorInfo.getLocation(); - debugInfo = (String) errorInfo.get("debugInfo"); + if (jsonError != null) { + Error error = error(jsonError); + code = error.code; + reason = error.reason; + if (reason != null) { + GoogleJsonError.ErrorInfo errorInfo = jsonError.getErrors().get(0); + location = errorInfo.getLocation(); + debugInfo = (String) errorInfo.get("debugInfo"); + } + } else { + code = ((GoogleJsonResponseException) exception).getStatusCode(); } } this.code = code; @@ -207,7 +211,10 @@ protected static Error error(GoogleJsonError error) { protected static String message(IOException exception) { if (exception instanceof GoogleJsonResponseException) { - return ((GoogleJsonResponseException) exception).getDetails().getMessage(); + GoogleJsonError details = ((GoogleJsonResponseException) exception).getDetails(); + if (details != null) { + return details.getMessage(); + } } return exception.getMessage(); } diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java b/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java index 4d9214ef5929..cac47b4bd248 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java @@ -31,6 +31,7 @@ import static com.google.gcloud.spi.StorageRpc.Option.PREFIX; import static com.google.gcloud.spi.StorageRpc.Option.VERSIONS; import static java.net.HttpURLConnection.HTTP_NOT_FOUND; +import static javax.servlet.http.HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE; import com.google.api.client.googleapis.batch.json.JsonBatchCallback; import com.google.api.client.googleapis.json.GoogleJsonError; @@ -453,7 +454,11 @@ public Tuple read(StorageObject from, Map options, lo String etag = req.getLastResponseHeaders().getETag(); return Tuple.of(etag, output.toByteArray()); } catch (IOException ex) { - throw translate(ex); + StorageException serviceException = translate(ex); + if (serviceException.code() == SC_REQUESTED_RANGE_NOT_SATISFIABLE) { + return Tuple.of(null, new byte[0]); + } + throw serviceException; } } diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobReadChannel.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobReadChannel.java index 2b9643434ecc..52b8c39321da 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobReadChannel.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobReadChannel.java @@ -127,7 +127,7 @@ public Tuple call() { return storageRpc.read(storageObject, requestOptions, position, toRead); } }, serviceOptions.retryParams(), StorageImpl.EXCEPTION_HANDLER); - if (lastEtag != null && !Objects.equals(result.x(), lastEtag)) { + if (result.y().length > 0 && lastEtag != null && !Objects.equals(result.x(), lastEtag)) { StringBuilder messageBuilder = new StringBuilder(); messageBuilder.append("Blob ").append(blob).append(" was updated while reading"); throw new StorageException(0, messageBuilder.toString()); diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/it/ITStorageTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/it/ITStorageTest.java index a411cdd60bfb..b62a54aff818 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/it/ITStorageTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/it/ITStorageTest.java @@ -54,6 +54,7 @@ import org.junit.Test; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; @@ -834,14 +835,18 @@ public void testReadAndWriteChannelsWithDifferentFileSize() throws IOException { byte[] bytes = new byte[blobSize]; rnd.nextBytes(bytes); try (WriteChannel writer = storage.writer(blob)) { - writer.write(ByteBuffer.wrap(BLOB_BYTE_CONTENT)); + writer.write(ByteBuffer.wrap(bytes)); } - ByteBuffer readBytes; + ByteArrayOutputStream output = new ByteArrayOutputStream(); try (ReadChannel reader = storage.reader(blob.blobId())) { - readBytes = ByteBuffer.allocate(BLOB_BYTE_CONTENT.length); - reader.read(readBytes); + ByteBuffer buffer = ByteBuffer.allocate(64 * 1024); + while (reader.read(buffer) > 0) { + buffer.flip(); + output.write(buffer.array(), 0, buffer.limit()); + buffer.clear(); + } } - assertArrayEquals(BLOB_BYTE_CONTENT, readBytes.array()); + assertArrayEquals(bytes, output.toByteArray()); assertTrue(storage.delete(BUCKET, blobName)); } }