From ea36a9e62f6179c557f7f788c37189f9aa3c107d Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Tue, 3 Nov 2015 18:06:36 +0100 Subject: [PATCH 01/48] Rename ListResult and move to core module --- .../main/java/com/google/gcloud/BasePage.java | 16 +++---- .../src/main/java/com/google/gcloud/Page.java | 10 ++--- .../java/com/google/gcloud/BasePageTest.java | 17 ++++---- .../{BlobListResult.java => BlobPage.java} | 17 ++++---- .../com/google/gcloud/storage/Bucket.java | 5 ++- .../com/google/gcloud/storage/Storage.java | 5 ++- .../google/gcloud/storage/StorageImpl.java | 20 +++++---- ...bListResultTest.java => BlobPageTest.java} | 30 +++++++------ .../com/google/gcloud/storage/BucketTest.java | 14 +++--- .../gcloud/storage/RemoteGcsHelperTest.java | 13 +++--- .../gcloud/storage/SerializationTest.java | 5 ++- .../gcloud/storage/StorageImplTest.java | 43 +++++++++---------- 12 files changed, 103 insertions(+), 92 deletions(-) rename gcloud-java-storage/src/main/java/com/google/gcloud/storage/BaseListResult.java => gcloud-java-core/src/main/java/com/google/gcloud/BasePage.java (79%) rename gcloud-java-storage/src/main/java/com/google/gcloud/storage/ListResult.java => gcloud-java-core/src/main/java/com/google/gcloud/Page.java (75%) rename gcloud-java-storage/src/test/java/com/google/gcloud/storage/BaseListResultTest.java => gcloud-java-core/src/test/java/com/google/gcloud/BasePageTest.java (69%) rename gcloud-java-storage/src/main/java/com/google/gcloud/storage/{BlobListResult.java => BlobPage.java} (79%) rename gcloud-java-storage/src/test/java/com/google/gcloud/storage/{BlobListResultTest.java => BlobPageTest.java} (77%) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BaseListResult.java b/gcloud-java-core/src/main/java/com/google/gcloud/BasePage.java similarity index 79% rename from gcloud-java-storage/src/main/java/com/google/gcloud/storage/BaseListResult.java rename to gcloud-java-core/src/main/java/com/google/gcloud/BasePage.java index fdcd84705555..ce62b334a785 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BaseListResult.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/BasePage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.google.gcloud.storage; +package com.google.gcloud; import java.io.Serializable; import java.util.Collections; @@ -22,9 +22,9 @@ import java.util.Objects; /** - * Base implementation for Google Cloud storage list result. + * Base implementation for Google Cloud paginated results. */ -public class BaseListResult implements ListResult, Serializable { +public class BasePage implements Page, Serializable { private static final long serialVersionUID = -6937287874908527950L; @@ -33,10 +33,10 @@ public class BaseListResult implements ListResult, Se private final NextPageFetcher pageFetcher; public interface NextPageFetcher extends Serializable { - ListResult nextPage(); + Page nextPage(); } - public BaseListResult(NextPageFetcher pageFetcher, String cursor, Iterable results) { + public BasePage(NextPageFetcher pageFetcher, String cursor, Iterable results) { this.pageFetcher = pageFetcher; this.cursor = cursor; this.results = results; @@ -48,7 +48,7 @@ public String nextPageCursor() { } @Override - public ListResult nextPage() { + public Page nextPage() { if (cursor == null || pageFetcher == null) { return null; } @@ -67,10 +67,10 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (!(obj instanceof BaseListResult)) { + if (!(obj instanceof BasePage)) { return false; } - BaseListResult other = (BaseListResult) obj; + BasePage other = (BasePage) obj; return Objects.equals(cursor, other.cursor) && Objects.equals(results, other.results); } diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/ListResult.java b/gcloud-java-core/src/main/java/com/google/gcloud/Page.java similarity index 75% rename from gcloud-java-storage/src/main/java/com/google/gcloud/storage/ListResult.java rename to gcloud-java-core/src/main/java/com/google/gcloud/Page.java index 62b1f442310c..21d465bb79f9 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/ListResult.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/Page.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.google.gcloud.storage; +package com.google.gcloud; /** - * Interface for Google Cloud storage list result. + * Interface for Google Cloud paginated results. */ -public interface ListResult extends Iterable { +public interface Page extends Iterable { /** * Returns the cursor for the nextPage or {@code null} if no more results. @@ -27,8 +27,8 @@ public interface ListResult extends Iterable { String nextPageCursor(); /** - * Returns the results of the nextPage or {@code null} if no more result. + * Returns the next page of results or {@code null} if no more result. */ - ListResult nextPage(); + Page nextPage(); } diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BaseListResultTest.java b/gcloud-java-core/src/test/java/com/google/gcloud/BasePageTest.java similarity index 69% rename from gcloud-java-storage/src/test/java/com/google/gcloud/storage/BaseListResultTest.java rename to gcloud-java-core/src/test/java/com/google/gcloud/BasePageTest.java index 4c22edbc35c8..888d7ace7ab0 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BaseListResultTest.java +++ b/gcloud-java-core/src/test/java/com/google/gcloud/BasePageTest.java @@ -14,31 +14,32 @@ * limitations under the License. */ -package com.google.gcloud.storage; +package com.google.gcloud; import static org.junit.Assert.assertEquals; import com.google.common.collect.ImmutableList; +import com.google.gcloud.BasePage; import org.junit.Test; import java.util.Collections; -public class BaseListResultTest { +public class BasePageTest { @Test - public void testListResult() throws Exception { + public void testPage() throws Exception { ImmutableList values = ImmutableList.of("1", "2"); - final BaseListResult nextResult = - new BaseListResult<>(null, "c", Collections.emptyList()); - BaseListResult.NextPageFetcher fetcher = new BaseListResult.NextPageFetcher() { + final BasePage nextResult = + new BasePage<>(null, "c", Collections.emptyList()); + BasePage.NextPageFetcher fetcher = new BasePage.NextPageFetcher() { @Override - public BaseListResult nextPage() { + public BasePage nextPage() { return nextResult; } }; - BaseListResult result = new BaseListResult<>(fetcher, "c", values); + BasePage result = new BasePage<>(fetcher, "c", values); assertEquals(nextResult, result.nextPage()); assertEquals("c", result.nextPageCursor()); assertEquals(values, ImmutableList.copyOf(result.iterator())); diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobListResult.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobPage.java similarity index 79% rename from gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobListResult.java rename to gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobPage.java index 9e6ec9dc5655..1090fdc99bcc 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobListResult.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobPage.java @@ -20,6 +20,7 @@ import com.google.common.base.Function; import com.google.common.collect.Iterators; +import com.google.gcloud.Page; import java.util.Iterator; import java.util.Objects; @@ -27,12 +28,12 @@ /** * Implementation of a paginated list of Google Cloud storage {@code Blob}. */ -public class BlobListResult implements ListResult { +public class BlobPage implements Page { - private final ListResult infoList; + private final Page infoList; private final Storage storage; - public BlobListResult(Storage storage, ListResult infoList) { + public BlobPage(Storage storage, Page infoList) { this.storage = checkNotNull(storage); this.infoList = checkNotNull(infoList); } @@ -43,12 +44,12 @@ public String nextPageCursor() { } @Override - public ListResult nextPage() { - ListResult nextPageInfoList = infoList.nextPage(); + public Page nextPage() { + Page nextPageInfoList = infoList.nextPage(); if (nextPageInfoList == null) { return null; } - return new BlobListResult(storage, nextPageInfoList); + return new BlobPage(storage, nextPageInfoList); } @Override @@ -68,10 +69,10 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (!(obj instanceof BlobListResult)) { + if (!(obj instanceof BlobPage)) { return false; } - BlobListResult other = (BlobListResult) obj; + BlobPage other = (BlobPage) obj; return Objects.equals(infoList, other.infoList); } } diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java index 8d696dc2ab6b..95e5b36133cf 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.MoreObjects; +import com.google.gcloud.Page; import com.google.gcloud.storage.Storage.BlobSourceOption; import com.google.gcloud.storage.Storage.BlobTargetOption; import com.google.gcloud.storage.Storage.BlobWriteOption; @@ -134,8 +135,8 @@ public boolean delete(BucketSourceOption... options) { * @param options options for listing blobs * @throws StorageException upon failure */ - public ListResult list(Storage.BlobListOption... options) { - return new BlobListResult(storage, storage.list(info.name(), options)); + public Page list(Storage.BlobListOption... options) { + return new BlobPage(storage, storage.list(info.name(), options)); } /** diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java index 9bc971a09dba..2fd4df0cc6ba 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java @@ -24,6 +24,7 @@ import com.google.common.collect.Lists; import com.google.gcloud.AuthCredentials.ServiceAccountAuthCredentials; import com.google.gcloud.Service; +import com.google.gcloud.Page; import com.google.gcloud.spi.StorageRpc; import com.google.gcloud.spi.StorageRpc.Tuple; @@ -827,14 +828,14 @@ private static void checkContentType(BlobInfo blobInfo) throws IllegalArgumentEx * * @throws StorageException upon failure */ - ListResult list(BucketListOption... options); + Page list(BucketListOption... options); /** * List the bucket's blobs. * * @throws StorageException upon failure */ - ListResult list(String bucket, BlobListOption... options); + Page list(String bucket, BlobListOption... options); /** * Update bucket information. diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java index ab85dc8b4609..422dfc0e4f4a 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java @@ -44,10 +44,12 @@ import com.google.common.io.BaseEncoding; import com.google.common.primitives.Ints; import com.google.gcloud.AuthCredentials.ServiceAccountAuthCredentials; +import com.google.gcloud.BasePage; import com.google.gcloud.BaseService; import com.google.gcloud.ExceptionHandler; import com.google.gcloud.ExceptionHandler.Interceptor; import com.google.gcloud.RetryHelper.RetryHelperException; +import com.google.gcloud.Page; import com.google.gcloud.spi.StorageRpc; import com.google.gcloud.spi.StorageRpc.RewriteResponse; import com.google.gcloud.spi.StorageRpc.Tuple; @@ -224,7 +226,7 @@ public BlobInfo get(BlobId blob) { } private abstract static class BasePageFetcher - implements BaseListResult.NextPageFetcher { + implements BasePage.NextPageFetcher { private static final long serialVersionUID = 8236329004030295223L; protected final Map requestOptions; @@ -256,7 +258,7 @@ private static class BucketPageFetcher extends BasePageFetcher { } @Override - public ListResult nextPage() { + public Page nextPage() { return listBuckets(serviceOptions, requestOptions); } } @@ -273,17 +275,17 @@ private static class BlobPageFetcher extends BasePageFetcher { } @Override - public ListResult nextPage() { + public Page nextPage() { return listBlobs(bucket, serviceOptions, requestOptions); } } @Override - public ListResult list(BucketListOption... options) { + public Page list(BucketListOption... options) { return listBuckets(options(), optionMap(options)); } - private static ListResult listBuckets(final StorageOptions serviceOptions, + private static Page listBuckets(final StorageOptions serviceOptions, final Map optionsMap) { try { Tuple> result = runWithRetries( @@ -302,7 +304,7 @@ public BucketInfo apply(com.google.api.services.storage.model.Bucket bucketPb) { return BucketInfo.fromPb(bucketPb); } }); - return new BaseListResult<>(new BucketPageFetcher(serviceOptions, cursor, optionsMap), cursor, + return new BasePage<>(new BucketPageFetcher(serviceOptions, cursor, optionsMap), cursor, buckets); } catch (RetryHelperException e) { throw StorageException.translateAndThrow(e); @@ -310,11 +312,11 @@ public BucketInfo apply(com.google.api.services.storage.model.Bucket bucketPb) { } @Override - public ListResult list(final String bucket, BlobListOption... options) { + public Page list(final String bucket, BlobListOption... options) { return listBlobs(bucket, options(), optionMap(options)); } - private static ListResult listBlobs(final String bucket, + private static Page listBlobs(final String bucket, final StorageOptions serviceOptions, final Map optionsMap) { try { Tuple> result = runWithRetries( @@ -333,7 +335,7 @@ public BlobInfo apply(StorageObject storageObject) { return BlobInfo.fromPb(storageObject); } }); - return new BaseListResult<>(new BlobPageFetcher(bucket, serviceOptions, cursor, optionsMap), + return new BasePage<>(new BlobPageFetcher(bucket, serviceOptions, cursor, optionsMap), cursor, blobs); } catch (RetryHelperException e) { diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobListResultTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobPageTest.java similarity index 77% rename from gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobListResultTest.java rename to gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobPageTest.java index 615213ab1516..68ddaf9c550f 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobListResultTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobPageTest.java @@ -24,13 +24,15 @@ import static org.junit.Assert.assertFalse; import com.google.common.collect.ImmutableList; +import com.google.gcloud.BasePage; +import com.google.gcloud.Page; import org.junit.Before; import org.junit.Test; import java.util.Iterator; -public class BlobListResultTest { +public class BlobPageTest { private static final Iterable FIRST_PAGE_RESULTS = ImmutableList.of( BlobInfo.builder("b1", "n1").build(), @@ -40,29 +42,29 @@ public class BlobListResultTest { BlobInfo.builder("b1", "n1").build(), BlobInfo.builder("b2", "n2").build()); - private BaseListResult firstPage; - private BaseListResult secondPage; + private BasePage firstPage; + private BasePage secondPage; private Storage storage; - private BlobListResult blobListResult; + private BlobPage blobPage; @Before public void setUp() throws Exception { - firstPage = createStrictMock(BaseListResult.class); - secondPage = createStrictMock(BaseListResult.class); + firstPage = createStrictMock(BasePage.class); + secondPage = createStrictMock(BasePage.class); storage = createStrictMock(Storage.class); - blobListResult = new BlobListResult(storage, firstPage); + blobPage = new BlobPage(storage, firstPage); } @Test - public void testListResult() throws Exception { + public void testPage() throws Exception { expect(firstPage.iterator()).andReturn(FIRST_PAGE_RESULTS.iterator()); replay(firstPage); Iterator firstPageIterator = FIRST_PAGE_RESULTS.iterator(); - Iterator blobListIterator = blobListResult.iterator(); - while (blobListIterator.hasNext() && firstPageIterator.hasNext()) { - assertEquals(firstPageIterator.next(), blobListIterator.next().info()); + Iterator pageIterator = blobPage.iterator(); + while (pageIterator.hasNext() && firstPageIterator.hasNext()) { + assertEquals(firstPageIterator.next(), pageIterator.next().info()); } - assertFalse(blobListIterator.hasNext()); + assertFalse(pageIterator.hasNext()); assertFalse(firstPageIterator.hasNext()); verify(firstPage); } @@ -71,7 +73,7 @@ public void testListResult() throws Exception { public void testCursor() throws Exception { expect(firstPage.nextPageCursor()).andReturn("c"); replay(firstPage); - assertEquals("c", blobListResult.nextPageCursor()); + assertEquals("c", blobPage.nextPageCursor()); verify(firstPage); } @@ -81,7 +83,7 @@ public void testNextPage() throws Exception { expect(secondPage.iterator()).andReturn(SECOND_PAGE_RESULTS.iterator()); replay(firstPage); replay(secondPage); - ListResult nextPageResult = blobListResult.nextPage(); + Page nextPageResult = blobPage.nextPage(); Iterator secondPageIterator = SECOND_PAGE_RESULTS.iterator(); Iterator blobListIterator = nextPageResult.iterator(); while (blobListIterator.hasNext() && secondPageIterator.hasNext()) { diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java index 370850a5b6d4..89e59084c67d 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java @@ -27,6 +27,8 @@ import static org.junit.Assert.assertTrue; import com.google.common.collect.ImmutableList; +import com.google.gcloud.BasePage; +import com.google.gcloud.Page; import com.google.gcloud.storage.BatchResponse.Result; import org.easymock.Capture; @@ -114,18 +116,18 @@ public void testDelete() throws Exception { @Test public void testList() throws Exception { - BaseListResult blobInfoResult = new BaseListResult<>(null, "c", BLOB_INFO_RESULTS); - expect(storage.list(BUCKET_INFO.name())).andReturn(blobInfoResult); + BasePage blobInfoPage = new BasePage<>(null, "c", BLOB_INFO_RESULTS); + expect(storage.list(BUCKET_INFO.name())).andReturn(blobInfoPage); replay(storage); - ListResult blobResult = bucket.list(); - Iterator blobInfoIterator = blobInfoResult.iterator(); - Iterator blobIterator = blobResult.iterator(); + Page blobPage = bucket.list(); + Iterator blobInfoIterator = blobInfoPage.iterator(); + Iterator blobIterator = blobPage.iterator(); while (blobInfoIterator.hasNext() && blobIterator.hasNext()) { assertEquals(blobInfoIterator.next(), blobIterator.next().info()); } assertFalse(blobInfoIterator.hasNext()); assertFalse(blobIterator.hasNext()); - assertEquals(blobInfoResult.nextPageCursor(), blobResult.nextPageCursor()); + assertEquals(blobInfoPage.nextPageCursor(), blobPage.nextPageCursor()); } @Test diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java index 329767e85d4a..91a646b1e11b 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertTrue; import com.google.common.collect.ImmutableList; +import com.google.gcloud.Page; import com.google.gcloud.storage.testing.RemoteGcsHelper; import org.easymock.EasyMock; @@ -74,15 +75,15 @@ public class RemoteGcsHelperTest { BlobInfo.builder(BUCKET_NAME, "n2").build()); private static final StorageException RETRYABLE_EXCEPTION = new StorageException(409, "", true); private static final StorageException FATAL_EXCEPTION = new StorageException(500, "", false); - private static final ListResult BLOB_LIST_RESULT = new ListResult() { + private static final Page BLOB_PAGE = new Page() { @Override public String nextPageCursor() { - return "listResult"; + return "nextPageCursor"; } @Override - public ListResult nextPage() { + public Page nextPage() { return null; } @@ -106,7 +107,7 @@ public static void beforeClass() { @Test public void testForceDelete() throws InterruptedException, ExecutionException { Storage storageMock = EasyMock.createMock(Storage.class); - EasyMock.expect(storageMock.list(BUCKET_NAME)).andReturn(BLOB_LIST_RESULT); + EasyMock.expect(storageMock.list(BUCKET_NAME)).andReturn(BLOB_PAGE); for (BlobInfo info : BLOB_LIST) { EasyMock.expect(storageMock.delete(BUCKET_NAME, info.name())).andReturn(true); } @@ -119,7 +120,7 @@ public void testForceDelete() throws InterruptedException, ExecutionException { @Test public void testForceDeleteTimeout() throws InterruptedException, ExecutionException { Storage storageMock = EasyMock.createMock(Storage.class); - EasyMock.expect(storageMock.list(BUCKET_NAME)).andReturn(BLOB_LIST_RESULT).anyTimes(); + EasyMock.expect(storageMock.list(BUCKET_NAME)).andReturn(BLOB_PAGE).anyTimes(); for (BlobInfo info : BLOB_LIST) { EasyMock.expect(storageMock.delete(BUCKET_NAME, info.name())).andReturn(true).anyTimes(); } @@ -132,7 +133,7 @@ public void testForceDeleteTimeout() throws InterruptedException, ExecutionExcep @Test public void testForceDeleteFail() throws InterruptedException, ExecutionException { Storage storageMock = EasyMock.createMock(Storage.class); - EasyMock.expect(storageMock.list(BUCKET_NAME)).andReturn(BLOB_LIST_RESULT); + EasyMock.expect(storageMock.list(BUCKET_NAME)).andReturn(BLOB_PAGE); for (BlobInfo info : BLOB_LIST) { EasyMock.expect(storageMock.delete(BUCKET_NAME, info.name())).andReturn(true); } diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java index 4c22170bba80..0239a2bf0326 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableMap; import com.google.gcloud.AuthCredentials; +import com.google.gcloud.BasePage; import com.google.gcloud.RestorableState; import com.google.gcloud.RetryParams; import com.google.gcloud.spi.StorageRpc; @@ -54,7 +55,7 @@ public class SerializationTest { Collections.singletonList(BatchResponse.Result.of(true)), Collections.>emptyList(), Collections.>emptyList()); - private static final BaseListResult LIST_RESULT = new BaseListResult<>( + private static final BasePage PAGE_RESULT = new BasePage<>( null, "c", Collections.singletonList(BlobInfo.builder("b", "n").build())); private static final Storage.BlobListOption BLOB_LIST_OPTIONS = Storage.BlobListOption.maxResults(100); @@ -93,7 +94,7 @@ public void testServiceOptions() throws Exception { public void testModelAndRequests() throws Exception { Serializable[] objects = {ACL_DOMAIN, ACL_GROUP, ACL_PROJECT_, ACL_USER, ACL_RAW, BLOB_INFO, BUCKET_INFO, - ORIGIN, CORS, BATCH_REQUEST, BATCH_RESPONSE, LIST_RESULT, BLOB_LIST_OPTIONS, + ORIGIN, CORS, BATCH_REQUEST, BATCH_RESPONSE, PAGE_RESULT, BLOB_LIST_OPTIONS, BLOB_SOURCE_OPTIONS, BLOB_TARGET_OPTIONS, BUCKET_LIST_OPTIONS, BUCKET_SOURCE_OPTIONS, BUCKET_TARGET_OPTIONS}; for (Serializable obj : objects) { diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java index bdac54bcef2d..a1284ae5c67f 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java @@ -35,6 +35,7 @@ import com.google.gcloud.AuthCredentials.ServiceAccountAuthCredentials; import com.google.gcloud.RetryParams; import com.google.gcloud.ServiceOptions; +import com.google.gcloud.Page; import com.google.gcloud.spi.StorageRpc; import com.google.gcloud.spi.StorageRpc.Tuple; import com.google.gcloud.spi.StorageRpcFactory; @@ -400,9 +401,9 @@ public void testListBuckets() { EasyMock.expect(storageRpcMock.list(EMPTY_RPC_OPTIONS)).andReturn(result); EasyMock.replay(storageRpcMock); storage = options.service(); - ListResult listResult = storage.list(); - assertEquals(cursor, listResult.nextPageCursor()); - assertArrayEquals(bucketList.toArray(), Iterables.toArray(listResult, BucketInfo.class)); + Page page = storage.list(); + assertEquals(cursor, page.nextPageCursor()); + assertArrayEquals(bucketList.toArray(), Iterables.toArray(page, BucketInfo.class)); } @Test @@ -411,10 +412,10 @@ public void testListBucketsEmpty() { Tuple.>of(null, null)); EasyMock.replay(storageRpcMock); storage = options.service(); - ListResult listResult = storage.list(); - assertNull(listResult.nextPageCursor()); + Page page = storage.list(); + assertNull(page.nextPageCursor()); assertArrayEquals(ImmutableList.of().toArray(), - Iterables.toArray(listResult, BucketInfo.class)); + Iterables.toArray(page, BucketInfo.class)); } @Test @@ -426,9 +427,9 @@ public void testListBucketsWithOptions() { EasyMock.expect(storageRpcMock.list(BUCKET_LIST_OPTIONS)).andReturn(result); EasyMock.replay(storageRpcMock); storage = options.service(); - ListResult listResult = storage.list(BUCKET_LIST_MAX_RESULT, BUCKET_LIST_PREFIX); - assertEquals(cursor, listResult.nextPageCursor()); - assertArrayEquals(bucketList.toArray(), Iterables.toArray(listResult, BucketInfo.class)); + Page page = storage.list(BUCKET_LIST_MAX_RESULT, BUCKET_LIST_PREFIX); + assertEquals(cursor, page.nextPageCursor()); + assertArrayEquals(bucketList.toArray(), Iterables.toArray(page, BucketInfo.class)); } @Test @@ -440,22 +441,21 @@ public void testListBlobs() { EasyMock.expect(storageRpcMock.list(BUCKET_NAME1, EMPTY_RPC_OPTIONS)).andReturn(result); EasyMock.replay(storageRpcMock); storage = options.service(); - ListResult listResult = storage.list(BUCKET_NAME1); - assertEquals(cursor, listResult.nextPageCursor()); - assertArrayEquals(blobList.toArray(), Iterables.toArray(listResult, BlobInfo.class)); + Page page = storage.list(BUCKET_NAME1); + assertEquals(cursor, page.nextPageCursor()); + assertArrayEquals(blobList.toArray(), Iterables.toArray(page, BlobInfo.class)); } @Test public void testListBlobsEmpty() { EasyMock.expect(storageRpcMock.list(BUCKET_NAME1, EMPTY_RPC_OPTIONS)) - .andReturn( - Tuple.>of(null, - null)); + .andReturn(Tuple.>of( + null, null)); EasyMock.replay(storageRpcMock); storage = options.service(); - ListResult listResult = storage.list(BUCKET_NAME1); - assertNull(listResult.nextPageCursor()); - assertArrayEquals(ImmutableList.of().toArray(), Iterables.toArray(listResult, BlobInfo.class)); + Page page = storage.list(BUCKET_NAME1); + assertNull(page.nextPageCursor()); + assertArrayEquals(ImmutableList.of().toArray(), Iterables.toArray(page, BlobInfo.class)); } @Test @@ -467,10 +467,9 @@ public void testListBlobsWithOptions() { EasyMock.expect(storageRpcMock.list(BUCKET_NAME1, BLOB_LIST_OPTIONS)).andReturn(result); EasyMock.replay(storageRpcMock); storage = options.service(); - ListResult listResult = - storage.list(BUCKET_NAME1, BLOB_LIST_MAX_RESULT, BLOB_LIST_PREFIX); - assertEquals(cursor, listResult.nextPageCursor()); - assertArrayEquals(blobList.toArray(), Iterables.toArray(listResult, BlobInfo.class)); + Page page = storage.list(BUCKET_NAME1, BLOB_LIST_MAX_RESULT, BLOB_LIST_PREFIX); + assertEquals(cursor, page.nextPageCursor()); + assertArrayEquals(blobList.toArray(), Iterables.toArray(page, BlobInfo.class)); } @Test From 6753c541b99e947d0af13b6e4d88ce65cd65a4c7 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 4 Nov 2015 12:04:01 +0100 Subject: [PATCH 02/48] Remove implements Serializable from BasePage and implements Iterable from Page - Add values() method to page, to return results - Add javadoc to BasePage to highlight that Iterable must be serializable - Delete BlobPage and BlobPageTest classes - Add BlobPageFetcher and LazyBlobIterable to Bucket class - Implement Bucket.list using BasePage, BlobPageFetcher and LazyBlobIterable - Update StorageExaple to iterate through pages --- .../main/java/com/google/gcloud/BasePage.java | 21 ++-- .../src/main/java/com/google/gcloud/Page.java | 19 +++- .../java/com/google/gcloud/BasePageTest.java | 4 +- .../gcloud/examples/StorageExample.java | 17 +++- .../com/google/gcloud/storage/BlobPage.java | 78 --------------- .../com/google/gcloud/storage/Bucket.java | 79 ++++++++++++++- .../storage/testing/RemoteGcsHelper.java | 2 +- .../google/gcloud/storage/BlobPageTest.java | 97 ------------------- .../com/google/gcloud/storage/BucketTest.java | 10 +- .../google/gcloud/storage/ITStorageTest.java | 4 +- .../gcloud/storage/RemoteGcsHelperTest.java | 5 +- .../gcloud/storage/StorageImplTest.java | 13 +-- 12 files changed, 140 insertions(+), 209 deletions(-) delete mode 100644 gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobPage.java delete mode 100644 gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobPageTest.java diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/BasePage.java b/gcloud-java-core/src/main/java/com/google/gcloud/BasePage.java index ce62b334a785..f041b5cf5d59 100644 --- a/gcloud-java-core/src/main/java/com/google/gcloud/BasePage.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/BasePage.java @@ -18,30 +18,38 @@ import java.io.Serializable; import java.util.Collections; -import java.util.Iterator; import java.util.Objects; /** * Base implementation for Google Cloud paginated results. */ -public class BasePage implements Page, Serializable { +public class BasePage implements Page, Serializable { - private static final long serialVersionUID = -6937287874908527950L; + private static final long serialVersionUID = 3914827379823557934L; private final String cursor; private final Iterable results; private final NextPageFetcher pageFetcher; - public interface NextPageFetcher extends Serializable { + public interface NextPageFetcher extends Serializable { Page nextPage(); } + /** + * Creates a {@code BasePage} object. In order for the object to be serializable the {@code + * results} parameter must be serializable. + */ public BasePage(NextPageFetcher pageFetcher, String cursor, Iterable results) { this.pageFetcher = pageFetcher; this.cursor = cursor; this.results = results; } + @Override + public Iterable values() { + return results == null ? Collections.EMPTY_LIST : results; + } + @Override public String nextPageCursor() { return cursor; @@ -55,11 +63,6 @@ public Page nextPage() { return pageFetcher.nextPage(); } - @Override - public Iterator iterator() { - return results == null ? Collections.emptyIterator() : results.iterator(); - } - @Override public int hashCode() { return Objects.hash(cursor, results); diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/Page.java b/gcloud-java-core/src/main/java/com/google/gcloud/Page.java index 21d465bb79f9..1b7754562716 100644 --- a/gcloud-java-core/src/main/java/com/google/gcloud/Page.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/Page.java @@ -18,8 +18,25 @@ /** * Interface for Google Cloud paginated results. + * + *

+ * A typical {@code Page} usage: + *

 {@code
+ * Page page = ...; // get a Page instance
+ * while (page != null) {
+ *   for (T value : page.values()) {
+ *     // do something with value
+ *   }
+ *   page = page.nextPage();
+ * }
+ * }
*/ -public interface Page extends Iterable { +public interface Page { + + /** + * Returns the values contained in this page. + */ + Iterable values(); /** * Returns the cursor for the nextPage or {@code null} if no more results. diff --git a/gcloud-java-core/src/test/java/com/google/gcloud/BasePageTest.java b/gcloud-java-core/src/test/java/com/google/gcloud/BasePageTest.java index 888d7ace7ab0..06e7c6167559 100644 --- a/gcloud-java-core/src/test/java/com/google/gcloud/BasePageTest.java +++ b/gcloud-java-core/src/test/java/com/google/gcloud/BasePageTest.java @@ -19,7 +19,6 @@ import static org.junit.Assert.assertEquals; import com.google.common.collect.ImmutableList; -import com.google.gcloud.BasePage; import org.junit.Test; @@ -42,7 +41,6 @@ public BasePage nextPage() { BasePage result = new BasePage<>(fetcher, "c", values); assertEquals(nextResult, result.nextPage()); assertEquals("c", result.nextPageCursor()); - assertEquals(values, ImmutableList.copyOf(result.iterator())); - + assertEquals(values, ImmutableList.copyOf(result.values().iterator())); } } diff --git a/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java index fb207023203f..7cf7fe2454fc 100644 --- a/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java +++ b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java @@ -18,6 +18,7 @@ import com.google.gcloud.AuthCredentials; import com.google.gcloud.AuthCredentials.ServiceAccountAuthCredentials; +import com.google.gcloud.Page; import com.google.gcloud.RetryParams; import com.google.gcloud.spi.StorageRpc.Tuple; import com.google.gcloud.storage.Blob; @@ -213,8 +214,12 @@ String parse(String... args) { public void run(Storage storage, String bucketName) { if (bucketName == null) { // list buckets - for (BucketInfo b : storage.list()) { - System.out.println(b); + Page bucketPage = storage.list(); + while (bucketPage != null) { + for (BucketInfo b : bucketPage.values()) { + System.out.println(b); + } + bucketPage = bucketPage.nextPage(); } } else { // list a bucket's blobs @@ -223,8 +228,12 @@ public void run(Storage storage, String bucketName) { System.out.println("No such bucket"); return; } - for (Blob b : bucket.list()) { - System.out.println(b.info()); + Page blobPage = bucket.list(); + while (blobPage != null) { + for (Blob b : blobPage.values()) { + System.out.println(b.info()); + } + blobPage = blobPage.nextPage(); } } } diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobPage.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobPage.java deleted file mode 100644 index 1090fdc99bcc..000000000000 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobPage.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.gcloud.storage; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.base.Function; -import com.google.common.collect.Iterators; -import com.google.gcloud.Page; - -import java.util.Iterator; -import java.util.Objects; - -/** - * Implementation of a paginated list of Google Cloud storage {@code Blob}. - */ -public class BlobPage implements Page { - - private final Page infoList; - private final Storage storage; - - public BlobPage(Storage storage, Page infoList) { - this.storage = checkNotNull(storage); - this.infoList = checkNotNull(infoList); - } - - @Override - public String nextPageCursor() { - return infoList.nextPageCursor(); - } - - @Override - public Page nextPage() { - Page nextPageInfoList = infoList.nextPage(); - if (nextPageInfoList == null) { - return null; - } - return new BlobPage(storage, nextPageInfoList); - } - - @Override - public Iterator iterator() { - return Iterators.transform(infoList.iterator(), new Function() { - @Override - public Blob apply(BlobInfo info) { - return new Blob(storage, info); - } - }); - } - - @Override - public int hashCode() { - return Objects.hash(infoList); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof BlobPage)) { - return false; - } - BlobPage other = (BlobPage) obj; - return Objects.equals(infoList, other.infoList); - } -} diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java index 95e5b36133cf..2b366dd7c8b0 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java @@ -19,17 +19,24 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.base.Function; import com.google.common.base.MoreObjects; +import com.google.common.collect.Iterators; +import com.google.gcloud.BasePage; import com.google.gcloud.Page; import com.google.gcloud.storage.Storage.BlobSourceOption; import com.google.gcloud.storage.Storage.BlobTargetOption; import com.google.gcloud.storage.Storage.BlobWriteOption; import com.google.gcloud.storage.Storage.BucketSourceOption; import com.google.gcloud.storage.Storage.BucketTargetOption; -import java.io.InputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Objects; @@ -47,6 +54,71 @@ public final class Bucket { private final Storage storage; private final BucketInfo info; + private static class BlobPageFetcher implements BasePage.NextPageFetcher { + + private static final long serialVersionUID = 3221100177471323801L; + + private final StorageOptions options; + private final Page infoPage; + + BlobPageFetcher(StorageOptions options, Page infoPage) { + this.options = options; + this.infoPage = infoPage; + } + + @Override + public Page nextPage() { + Page nextInfoPage = infoPage.nextPage(); + return new BasePage(new BlobPageFetcher(options, nextInfoPage), + nextInfoPage.nextPageCursor(), new LazyBlobIterable(options, nextInfoPage.values())); + } + } + + private static class LazyBlobIterable implements Iterable, Serializable { + + private static final long serialVersionUID = -3092290247725378832L; + + private final StorageOptions options; + private Iterable infoIterable; + private transient Storage storage; + + public LazyBlobIterable(StorageOptions options, Iterable infoIterable) { + this.options = options; + this.infoIterable = infoIterable; + this.storage = options.service(); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + this.storage = options.service(); + } + + @Override + public Iterator iterator() { + return Iterators.transform(infoIterable.iterator(), new Function() { + @Override + public Blob apply(BlobInfo blobInfo) { + return new Blob(storage, blobInfo); + } + }); + } + + @Override + public int hashCode() { + return Objects.hash(options, infoIterable); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof LazyBlobIterable)) { + return false; + } + LazyBlobIterable other = (LazyBlobIterable) obj; + return Objects.equals(options, other.options) + && Objects.equals(infoIterable, other.infoIterable); + } + } + /** * Constructs a {@code Bucket} object for the provided {@code BucketInfo}. The storage service is * used to issue requests. @@ -136,7 +208,10 @@ public boolean delete(BucketSourceOption... options) { * @throws StorageException upon failure */ public Page list(Storage.BlobListOption... options) { - return new BlobPage(storage, storage.list(info.name(), options)); + Page infoPage = storage.list(info.name(), options); + StorageOptions storageOptions = storage.options(); + return new BasePage(new BlobPageFetcher(storageOptions, infoPage), + infoPage.nextPageCursor(), new LazyBlobIterable(storageOptions, infoPage.values())); } /** diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/testing/RemoteGcsHelper.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/testing/RemoteGcsHelper.java index 6ad655db8670..b15768cffa98 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/testing/RemoteGcsHelper.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/testing/RemoteGcsHelper.java @@ -195,7 +195,7 @@ public DeleteBucketTask(Storage storage, String bucket) { @Override public Boolean call() throws Exception { while (true) { - for (BlobInfo info : storage.list(bucket)) { + for (BlobInfo info : storage.list(bucket).values()) { storage.delete(bucket, info.name()); } try { diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobPageTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobPageTest.java deleted file mode 100644 index 68ddaf9c550f..000000000000 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobPageTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.gcloud.storage; - -import static org.easymock.EasyMock.createStrictMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -import com.google.common.collect.ImmutableList; -import com.google.gcloud.BasePage; -import com.google.gcloud.Page; - -import org.junit.Before; -import org.junit.Test; - -import java.util.Iterator; - -public class BlobPageTest { - - private static final Iterable FIRST_PAGE_RESULTS = ImmutableList.of( - BlobInfo.builder("b1", "n1").build(), - BlobInfo.builder("b2", "n2").build()); - - private static final Iterable SECOND_PAGE_RESULTS = ImmutableList.of( - BlobInfo.builder("b1", "n1").build(), - BlobInfo.builder("b2", "n2").build()); - - private BasePage firstPage; - private BasePage secondPage; - private Storage storage; - private BlobPage blobPage; - - @Before - public void setUp() throws Exception { - firstPage = createStrictMock(BasePage.class); - secondPage = createStrictMock(BasePage.class); - storage = createStrictMock(Storage.class); - blobPage = new BlobPage(storage, firstPage); - } - - @Test - public void testPage() throws Exception { - expect(firstPage.iterator()).andReturn(FIRST_PAGE_RESULTS.iterator()); - replay(firstPage); - Iterator firstPageIterator = FIRST_PAGE_RESULTS.iterator(); - Iterator pageIterator = blobPage.iterator(); - while (pageIterator.hasNext() && firstPageIterator.hasNext()) { - assertEquals(firstPageIterator.next(), pageIterator.next().info()); - } - assertFalse(pageIterator.hasNext()); - assertFalse(firstPageIterator.hasNext()); - verify(firstPage); - } - - @Test - public void testCursor() throws Exception { - expect(firstPage.nextPageCursor()).andReturn("c"); - replay(firstPage); - assertEquals("c", blobPage.nextPageCursor()); - verify(firstPage); - } - - @Test - public void testNextPage() throws Exception { - expect(firstPage.nextPage()).andReturn(secondPage); - expect(secondPage.iterator()).andReturn(SECOND_PAGE_RESULTS.iterator()); - replay(firstPage); - replay(secondPage); - Page nextPageResult = blobPage.nextPage(); - Iterator secondPageIterator = SECOND_PAGE_RESULTS.iterator(); - Iterator blobListIterator = nextPageResult.iterator(); - while (blobListIterator.hasNext() && secondPageIterator.hasNext()) { - assertEquals(secondPageIterator.next(), blobListIterator.next().info()); - } - assertFalse(blobListIterator.hasNext()); - assertFalse(secondPageIterator.hasNext()); - verify(firstPage); - verify(secondPage); - } -} diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java index 89e59084c67d..b6fbb09bbb4f 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java @@ -116,18 +116,22 @@ public void testDelete() throws Exception { @Test public void testList() throws Exception { + StorageOptions storageOptions = createStrictMock(StorageOptions.class); BasePage blobInfoPage = new BasePage<>(null, "c", BLOB_INFO_RESULTS); expect(storage.list(BUCKET_INFO.name())).andReturn(blobInfoPage); - replay(storage); + expect(storage.options()).andReturn(storageOptions); + expect(storageOptions.service()).andReturn(storage); + replay(storage, storageOptions); Page blobPage = bucket.list(); - Iterator blobInfoIterator = blobInfoPage.iterator(); - Iterator blobIterator = blobPage.iterator(); + Iterator blobInfoIterator = blobInfoPage.values().iterator(); + Iterator blobIterator = blobPage.values().iterator(); while (blobInfoIterator.hasNext() && blobIterator.hasNext()) { assertEquals(blobInfoIterator.next(), blobIterator.next().info()); } assertFalse(blobInfoIterator.hasNext()); assertFalse(blobIterator.hasNext()); assertEquals(blobInfoPage.nextPageCursor(), blobPage.nextPageCursor()); + verify(storageOptions); } @Test diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java index 3aad7b712e48..d15e07dfeff7 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java @@ -81,10 +81,10 @@ public static void afterClass() @Test(timeout = 5000) public void testListBuckets() throws InterruptedException { Iterator bucketIterator = - storage.list(Storage.BucketListOption.prefix(BUCKET)).iterator(); + storage.list(Storage.BucketListOption.prefix(BUCKET)).values().iterator(); while (!bucketIterator.hasNext()) { Thread.sleep(500); - bucketIterator = storage.list(Storage.BucketListOption.prefix(BUCKET)).iterator(); + bucketIterator = storage.list(Storage.BucketListOption.prefix(BUCKET)).values().iterator(); } while (bucketIterator.hasNext()) { assertTrue(bucketIterator.next().name().startsWith(BUCKET)); diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java index 91a646b1e11b..ff6fd68fd1eb 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java @@ -33,7 +33,6 @@ import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.Iterator; import java.util.List; import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -88,8 +87,8 @@ public Page nextPage() { } @Override - public Iterator iterator() { - return BLOB_LIST.iterator(); + public Iterable values() { + return BLOB_LIST; } }; private static String keyPath = "/does/not/exist/key." + UUID.randomUUID().toString() + ".json"; diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java index a1284ae5c67f..6c77b4fcfc99 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java @@ -403,7 +403,7 @@ public void testListBuckets() { storage = options.service(); Page page = storage.list(); assertEquals(cursor, page.nextPageCursor()); - assertArrayEquals(bucketList.toArray(), Iterables.toArray(page, BucketInfo.class)); + assertArrayEquals(bucketList.toArray(), Iterables.toArray(page.values(), BucketInfo.class)); } @Test @@ -415,7 +415,7 @@ public void testListBucketsEmpty() { Page page = storage.list(); assertNull(page.nextPageCursor()); assertArrayEquals(ImmutableList.of().toArray(), - Iterables.toArray(page, BucketInfo.class)); + Iterables.toArray(page.values(), BucketInfo.class)); } @Test @@ -429,7 +429,7 @@ public void testListBucketsWithOptions() { storage = options.service(); Page page = storage.list(BUCKET_LIST_MAX_RESULT, BUCKET_LIST_PREFIX); assertEquals(cursor, page.nextPageCursor()); - assertArrayEquals(bucketList.toArray(), Iterables.toArray(page, BucketInfo.class)); + assertArrayEquals(bucketList.toArray(), Iterables.toArray(page.values(), BucketInfo.class)); } @Test @@ -443,7 +443,7 @@ public void testListBlobs() { storage = options.service(); Page page = storage.list(BUCKET_NAME1); assertEquals(cursor, page.nextPageCursor()); - assertArrayEquals(blobList.toArray(), Iterables.toArray(page, BlobInfo.class)); + assertArrayEquals(blobList.toArray(), Iterables.toArray(page.values(), BlobInfo.class)); } @Test @@ -455,7 +455,8 @@ public void testListBlobsEmpty() { storage = options.service(); Page page = storage.list(BUCKET_NAME1); assertNull(page.nextPageCursor()); - assertArrayEquals(ImmutableList.of().toArray(), Iterables.toArray(page, BlobInfo.class)); + assertArrayEquals(ImmutableList.of().toArray(), + Iterables.toArray(page.values(), BlobInfo.class)); } @Test @@ -469,7 +470,7 @@ public void testListBlobsWithOptions() { storage = options.service(); Page page = storage.list(BUCKET_NAME1, BLOB_LIST_MAX_RESULT, BLOB_LIST_PREFIX); assertEquals(cursor, page.nextPageCursor()); - assertArrayEquals(blobList.toArray(), Iterables.toArray(page, BlobInfo.class)); + assertArrayEquals(blobList.toArray(), Iterables.toArray(page.values(), BlobInfo.class)); } @Test From 104bf41e1c6ff76f36816d2e9b8b75cfe5db8f5c Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 4 Nov 2015 19:36:50 +0100 Subject: [PATCH 03/48] Rename BasePage to PageImpl --- .../google/gcloud/{BasePage.java => PageImpl.java} | 10 +++++----- .../gcloud/{BasePageTest.java => PageImplTest.java} | 12 ++++++------ .../main/java/com/google/gcloud/storage/Bucket.java | 8 ++++---- .../java/com/google/gcloud/storage/StorageImpl.java | 8 ++++---- .../java/com/google/gcloud/storage/BucketTest.java | 4 ++-- .../com/google/gcloud/storage/SerializationTest.java | 4 ++-- 6 files changed, 23 insertions(+), 23 deletions(-) rename gcloud-java-core/src/main/java/com/google/gcloud/{BasePage.java => PageImpl.java} (87%) rename gcloud-java-core/src/test/java/com/google/gcloud/{BasePageTest.java => PageImplTest.java} (79%) diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/BasePage.java b/gcloud-java-core/src/main/java/com/google/gcloud/PageImpl.java similarity index 87% rename from gcloud-java-core/src/main/java/com/google/gcloud/BasePage.java rename to gcloud-java-core/src/main/java/com/google/gcloud/PageImpl.java index f041b5cf5d59..3925079c8d4b 100644 --- a/gcloud-java-core/src/main/java/com/google/gcloud/BasePage.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/PageImpl.java @@ -23,7 +23,7 @@ /** * Base implementation for Google Cloud paginated results. */ -public class BasePage implements Page, Serializable { +public class PageImpl implements Page, Serializable { private static final long serialVersionUID = 3914827379823557934L; @@ -36,10 +36,10 @@ public interface NextPageFetcher extends Serializable { } /** - * Creates a {@code BasePage} object. In order for the object to be serializable the {@code + * Creates a {@code PageImpl} object. In order for the object to be serializable the {@code * results} parameter must be serializable. */ - public BasePage(NextPageFetcher pageFetcher, String cursor, Iterable results) { + public PageImpl(NextPageFetcher pageFetcher, String cursor, Iterable results) { this.pageFetcher = pageFetcher; this.cursor = cursor; this.results = results; @@ -70,10 +70,10 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (!(obj instanceof BasePage)) { + if (!(obj instanceof PageImpl)) { return false; } - BasePage other = (BasePage) obj; + PageImpl other = (PageImpl) obj; return Objects.equals(cursor, other.cursor) && Objects.equals(results, other.results); } diff --git a/gcloud-java-core/src/test/java/com/google/gcloud/BasePageTest.java b/gcloud-java-core/src/test/java/com/google/gcloud/PageImplTest.java similarity index 79% rename from gcloud-java-core/src/test/java/com/google/gcloud/BasePageTest.java rename to gcloud-java-core/src/test/java/com/google/gcloud/PageImplTest.java index 06e7c6167559..78aa3feaa281 100644 --- a/gcloud-java-core/src/test/java/com/google/gcloud/BasePageTest.java +++ b/gcloud-java-core/src/test/java/com/google/gcloud/PageImplTest.java @@ -24,21 +24,21 @@ import java.util.Collections; -public class BasePageTest { +public class PageImplTest { @Test public void testPage() throws Exception { ImmutableList values = ImmutableList.of("1", "2"); - final BasePage nextResult = - new BasePage<>(null, "c", Collections.emptyList()); - BasePage.NextPageFetcher fetcher = new BasePage.NextPageFetcher() { + final PageImpl nextResult = + new PageImpl<>(null, "c", Collections.emptyList()); + PageImpl.NextPageFetcher fetcher = new PageImpl.NextPageFetcher() { @Override - public BasePage nextPage() { + public PageImpl nextPage() { return nextResult; } }; - BasePage result = new BasePage<>(fetcher, "c", values); + PageImpl result = new PageImpl<>(fetcher, "c", values); assertEquals(nextResult, result.nextPage()); assertEquals("c", result.nextPageCursor()); assertEquals(values, ImmutableList.copyOf(result.values().iterator())); diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java index 2b366dd7c8b0..fe149a84ccc8 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java @@ -22,7 +22,7 @@ import com.google.common.base.Function; import com.google.common.base.MoreObjects; import com.google.common.collect.Iterators; -import com.google.gcloud.BasePage; +import com.google.gcloud.PageImpl; import com.google.gcloud.Page; import com.google.gcloud.storage.Storage.BlobSourceOption; import com.google.gcloud.storage.Storage.BlobTargetOption; @@ -54,7 +54,7 @@ public final class Bucket { private final Storage storage; private final BucketInfo info; - private static class BlobPageFetcher implements BasePage.NextPageFetcher { + private static class BlobPageFetcher implements PageImpl.NextPageFetcher { private static final long serialVersionUID = 3221100177471323801L; @@ -69,7 +69,7 @@ private static class BlobPageFetcher implements BasePage.NextPageFetcher { @Override public Page nextPage() { Page nextInfoPage = infoPage.nextPage(); - return new BasePage(new BlobPageFetcher(options, nextInfoPage), + return new PageImpl(new BlobPageFetcher(options, nextInfoPage), nextInfoPage.nextPageCursor(), new LazyBlobIterable(options, nextInfoPage.values())); } } @@ -210,7 +210,7 @@ public boolean delete(BucketSourceOption... options) { public Page list(Storage.BlobListOption... options) { Page infoPage = storage.list(info.name(), options); StorageOptions storageOptions = storage.options(); - return new BasePage(new BlobPageFetcher(storageOptions, infoPage), + return new PageImpl(new BlobPageFetcher(storageOptions, infoPage), infoPage.nextPageCursor(), new LazyBlobIterable(storageOptions, infoPage.values())); } diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java index 422dfc0e4f4a..d1e85368fecb 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java @@ -44,7 +44,7 @@ import com.google.common.io.BaseEncoding; import com.google.common.primitives.Ints; import com.google.gcloud.AuthCredentials.ServiceAccountAuthCredentials; -import com.google.gcloud.BasePage; +import com.google.gcloud.PageImpl; import com.google.gcloud.BaseService; import com.google.gcloud.ExceptionHandler; import com.google.gcloud.ExceptionHandler.Interceptor; @@ -226,7 +226,7 @@ public BlobInfo get(BlobId blob) { } private abstract static class BasePageFetcher - implements BasePage.NextPageFetcher { + implements PageImpl.NextPageFetcher { private static final long serialVersionUID = 8236329004030295223L; protected final Map requestOptions; @@ -304,7 +304,7 @@ public BucketInfo apply(com.google.api.services.storage.model.Bucket bucketPb) { return BucketInfo.fromPb(bucketPb); } }); - return new BasePage<>(new BucketPageFetcher(serviceOptions, cursor, optionsMap), cursor, + return new PageImpl<>(new BucketPageFetcher(serviceOptions, cursor, optionsMap), cursor, buckets); } catch (RetryHelperException e) { throw StorageException.translateAndThrow(e); @@ -335,7 +335,7 @@ public BlobInfo apply(StorageObject storageObject) { return BlobInfo.fromPb(storageObject); } }); - return new BasePage<>(new BlobPageFetcher(bucket, serviceOptions, cursor, optionsMap), + return new PageImpl<>(new BlobPageFetcher(bucket, serviceOptions, cursor, optionsMap), cursor, blobs); } catch (RetryHelperException e) { diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java index b6fbb09bbb4f..decac7b1e0d2 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java @@ -27,7 +27,7 @@ import static org.junit.Assert.assertTrue; import com.google.common.collect.ImmutableList; -import com.google.gcloud.BasePage; +import com.google.gcloud.PageImpl; import com.google.gcloud.Page; import com.google.gcloud.storage.BatchResponse.Result; @@ -117,7 +117,7 @@ public void testDelete() throws Exception { @Test public void testList() throws Exception { StorageOptions storageOptions = createStrictMock(StorageOptions.class); - BasePage blobInfoPage = new BasePage<>(null, "c", BLOB_INFO_RESULTS); + PageImpl blobInfoPage = new PageImpl<>(null, "c", BLOB_INFO_RESULTS); expect(storage.list(BUCKET_INFO.name())).andReturn(blobInfoPage); expect(storage.options()).andReturn(storageOptions); expect(storageOptions.service()).andReturn(storage); diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java index 0239a2bf0326..a125a64df6d6 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java @@ -21,7 +21,7 @@ import com.google.common.collect.ImmutableMap; import com.google.gcloud.AuthCredentials; -import com.google.gcloud.BasePage; +import com.google.gcloud.PageImpl; import com.google.gcloud.RestorableState; import com.google.gcloud.RetryParams; import com.google.gcloud.spi.StorageRpc; @@ -55,7 +55,7 @@ public class SerializationTest { Collections.singletonList(BatchResponse.Result.of(true)), Collections.>emptyList(), Collections.>emptyList()); - private static final BasePage PAGE_RESULT = new BasePage<>( + private static final PageImpl PAGE_RESULT = new PageImpl<>( null, "c", Collections.singletonList(BlobInfo.builder("b", "n").build())); private static final Storage.BlobListOption BLOB_LIST_OPTIONS = Storage.BlobListOption.maxResults(100); From 26471e6c30b19e19671cc73a2ea6c593a91b57ea Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 4 Nov 2015 20:49:45 +0100 Subject: [PATCH 04/48] Use diamond operator instead of explicit type param for PageImpl --- .../src/main/java/com/google/gcloud/storage/Bucket.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java index fe149a84ccc8..1f696d07ac33 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java @@ -210,8 +210,8 @@ public boolean delete(BucketSourceOption... options) { public Page list(Storage.BlobListOption... options) { Page infoPage = storage.list(info.name(), options); StorageOptions storageOptions = storage.options(); - return new PageImpl(new BlobPageFetcher(storageOptions, infoPage), - infoPage.nextPageCursor(), new LazyBlobIterable(storageOptions, infoPage.values())); + return new PageImpl<>(new BlobPageFetcher(storageOptions, infoPage), infoPage.nextPageCursor(), + new LazyBlobIterable(storageOptions, infoPage.values())); } /** From deecc14fe1015d7f3e62323da57471f9d7dd8ec1 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Mon, 2 Nov 2015 13:40:39 +0100 Subject: [PATCH 05/48] Add support for selected fields to blob get and list - Add AclField and BlobField classes to Storage - Add BlobGetOption class to Storage that supports the .fields option - Use BlobGetOption in Storage.get instead of BlobSourceOption - Add .fields option to BlobListOption - Updated Blob.exists to use selected fields - Use BlobGetOption in BatchRequest.toGet instead of BlobSourceOption - Add unit and integration tests for selected fields --- .../google/gcloud/spi/DefaultStorageRpc.java | 5 +- .../com/google/gcloud/spi/StorageRpc.java | 3 +- .../google/gcloud/storage/BatchRequest.java | 11 +- .../java/com/google/gcloud/storage/Blob.java | 33 ++- .../com/google/gcloud/storage/Bucket.java | 4 +- .../com/google/gcloud/storage/Storage.java | 261 +++++++++++++++++- .../google/gcloud/storage/StorageImpl.java | 8 +- .../gcloud/storage/BatchRequestTest.java | 11 +- .../com/google/gcloud/storage/BlobTest.java | 8 +- .../com/google/gcloud/storage/BucketTest.java | 2 +- .../google/gcloud/storage/ITStorageTest.java | 83 +++++- .../gcloud/storage/StorageImplTest.java | 121 +++++++- 12 files changed, 519 insertions(+), 31 deletions(-) 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 70cad8c7773e..29552d5121e5 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 @@ -15,6 +15,7 @@ package com.google.gcloud.spi; import static com.google.gcloud.spi.StorageRpc.Option.DELIMITER; +import static com.google.gcloud.spi.StorageRpc.Option.FIELDS; import static com.google.gcloud.spi.StorageRpc.Option.IF_GENERATION_MATCH; import static com.google.gcloud.spi.StorageRpc.Option.IF_GENERATION_NOT_MATCH; import static com.google.gcloud.spi.StorageRpc.Option.IF_METAGENERATION_MATCH; @@ -168,6 +169,7 @@ public Tuple> list(String bucket, Map .setPrefix(PREFIX.getString(options)) .setMaxResults(MAX_RESULTS.getLong(options)) .setPageToken(PAGE_TOKEN.getString(options)) + .setFields(FIELDS.getString(options)) .execute(); return Tuple.>of( objects.getNextPageToken(), objects.getItems()); @@ -207,7 +209,8 @@ private Storage.Objects.Get getRequest(StorageObject object, Map opti .setIfMetagenerationMatch(IF_METAGENERATION_MATCH.getLong(options)) .setIfMetagenerationNotMatch(IF_METAGENERATION_NOT_MATCH.getLong(options)) .setIfGenerationMatch(IF_GENERATION_MATCH.getLong(options)) - .setIfGenerationNotMatch(IF_GENERATION_NOT_MATCH.getLong(options)); + .setIfGenerationNotMatch(IF_GENERATION_NOT_MATCH.getLong(options)) + .setFields(FIELDS.getString(options)); } @Override diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/spi/StorageRpc.java b/gcloud-java-storage/src/main/java/com/google/gcloud/spi/StorageRpc.java index 40382a857fca..e4b1be785951 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/spi/StorageRpc.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/spi/StorageRpc.java @@ -47,7 +47,8 @@ enum Option { MAX_RESULTS("maxResults"), PAGE_TOKEN("pageToken"), DELIMITER("delimiter"), - VERSIONS("versions"); + VERSIONS("versions"), + FIELDS("fields"); private final String value; diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BatchRequest.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BatchRequest.java index 6e815648497a..bf77c731754e 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BatchRequest.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BatchRequest.java @@ -18,6 +18,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; +import com.google.gcloud.storage.Storage.BlobGetOption; import com.google.gcloud.storage.Storage.BlobSourceOption; import com.google.gcloud.storage.Storage.BlobTargetOption; @@ -35,13 +36,13 @@ public final class BatchRequest implements Serializable { private final Map> toDelete; private final Map> toUpdate; - private final Map> toGet; + private final Map> toGet; public static class Builder { private Map> toDelete = new LinkedHashMap<>(); private Map> toUpdate = new LinkedHashMap<>(); - private Map> toGet = new LinkedHashMap<>(); + private Map> toGet = new LinkedHashMap<>(); private Builder() {} @@ -72,7 +73,7 @@ public Builder update(BlobInfo blobInfo, BlobTargetOption... options) { /** * Retrieve metadata for the given blob. */ - public Builder get(String bucket, String blob, BlobSourceOption... options) { + public Builder get(String bucket, String blob, BlobGetOption... options) { toGet.put(BlobId.of(bucket, blob), Lists.newArrayList(options)); return this; } @@ -80,7 +81,7 @@ public Builder get(String bucket, String blob, BlobSourceOption... options) { /** * Retrieve metadata for the given blob. */ - public Builder get(BlobId blob, BlobSourceOption... options) { + public Builder get(BlobId blob, BlobGetOption... options) { toGet.put(blob, Lists.newArrayList(options)); return this; } @@ -120,7 +121,7 @@ public Map> toUpdate() { return toUpdate; } - public Map> toGet() { + public Map> toGet() { return toGet; } diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Blob.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Blob.java index 8f988922aad9..88f25c7e5cbd 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Blob.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Blob.java @@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.gcloud.storage.Blob.BlobSourceOption.convert; +import static com.google.gcloud.storage.Blob.BlobSourceOption.toGetOptions; import com.google.common.base.Function; import com.google.common.collect.Lists; @@ -29,6 +30,7 @@ import com.google.gcloud.storage.Storage.SignUrlOption; import java.net.URL; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -71,6 +73,21 @@ private Storage.BlobSourceOption convert(BlobInfo blobInfo) { } } + private Storage.BlobGetOption toGetOption(BlobInfo blobInfo) { + switch (rpcOption()) { + case IF_GENERATION_MATCH: + return Storage.BlobGetOption.generationMatch(blobInfo.generation()); + case IF_GENERATION_NOT_MATCH: + return Storage.BlobGetOption.generationNotMatch(blobInfo.generation()); + case IF_METAGENERATION_MATCH: + return Storage.BlobGetOption.metagenerationMatch(blobInfo.metageneration()); + case IF_METAGENERATION_NOT_MATCH: + return Storage.BlobGetOption.metagenerationNotMatch(blobInfo.metageneration()); + default: + throw new AssertionError("Unexpected enum value"); + } + } + public static BlobSourceOption generationMatch() { return new BlobSourceOption(StorageRpc.Option.IF_GENERATION_MATCH); } @@ -95,6 +112,15 @@ static Storage.BlobSourceOption[] convert(BlobInfo blobInfo, BlobSourceOption... } return convertedOptions; } + + static Storage.BlobGetOption[] toGetOptions(BlobInfo blobInfo, BlobSourceOption... options) { + Storage.BlobGetOption[] convertedOptions = new Storage.BlobGetOption[options.length]; + int index = 0; + for (BlobSourceOption option : options) { + convertedOptions[index++] = option.toGetOption(blobInfo); + } + return convertedOptions; + } } /** @@ -159,7 +185,10 @@ public BlobId id() { * @throws StorageException upon failure */ public boolean exists(BlobSourceOption... options) { - return storage.get(info.blobId(), convert(info, options)) != null; + int length = options.length; + Storage.BlobGetOption[] getOptions = Arrays.copyOf(toGetOptions(info, options), length + 1); + getOptions[length] = Storage.BlobGetOption.fields(); + return storage.get(info.blobId(), getOptions) != null; } /** @@ -180,7 +209,7 @@ public byte[] content(Storage.BlobSourceOption... options) { * @throws StorageException upon failure */ public Blob reload(BlobSourceOption... options) { - return new Blob(storage, storage.get(info.blobId(), convert(info, options))); + return new Blob(storage, storage.get(info.blobId(), toGetOptions(info, options))); } /** diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java index 1f696d07ac33..3b659f0cd355 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java @@ -24,7 +24,7 @@ import com.google.common.collect.Iterators; import com.google.gcloud.PageImpl; import com.google.gcloud.Page; -import com.google.gcloud.storage.Storage.BlobSourceOption; +import com.google.gcloud.storage.Storage.BlobGetOption; import com.google.gcloud.storage.Storage.BlobTargetOption; import com.google.gcloud.storage.Storage.BlobWriteOption; import com.google.gcloud.storage.Storage.BucketSourceOption; @@ -221,7 +221,7 @@ public Page list(Storage.BlobListOption... options) { * @param options blob search options * @throws StorageException upon failure */ - public Blob get(String blob, BlobSourceOption... options) { + public Blob get(String blob, BlobGetOption... options) { return new Blob(storage, storage.get(BlobId.of(info.name(), blob), options)); } diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java index 2fd4df0cc6ba..4438342b853f 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java @@ -19,9 +19,11 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import com.google.gcloud.AuthCredentials.ServiceAccountAuthCredentials; import com.google.gcloud.Service; import com.google.gcloud.Page; @@ -33,6 +35,7 @@ import java.net.URL; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; @@ -70,6 +73,209 @@ String entry() { } } + public static abstract class EntityField { + + private final String selector; + + public EntityField(String selector) { + this.selector = selector; + } + + public String selector() { + return selector; + } + } + + public static class AclField extends EntityField { + + public AclField(String selector) { + super(selector); + } + + public static AclField bucket() { + return new AclField("bucket"); + } + + public static AclField domain() { + return new AclField("domain"); + } + + public static AclField email() { + return new AclField("email"); + } + + public static AclField entity() { + return new AclField("entity"); + } + + public static AclField entityId() { + return new AclField("entityId"); + } + + public static AclField etag() { + return new AclField("etag"); + } + + public static AclField generation() { + return new AclField("generation"); + } + + public static AclField id() { + return new AclField("id"); + } + + public static AclField kind() { + return new AclField("kind"); + } + + public static AclField object() { + return new AclField("object"); + } + + public static AclField projectTeam() { + return new AclField("projectTeam"); + } + + public static AclField role() { + return new AclField("role"); + } + + public static AclField selfLink() { + return new AclField("selfLink"); + } + + static String selector(AclField... aclFields) { + HashSet fieldStrings = Sets.newHashSetWithExpectedSize(aclFields.length + 2); + fieldStrings.add(AclField.role().selector()); + fieldStrings.add(AclField.entity().selector()); + for (AclField field : aclFields) { + fieldStrings.add(field.selector()); + } + return new StringBuffer() + .append("acl(") + .append(Joiner.on(",").join(fieldStrings)) + .append(")") + .toString(); + } + } + + public static class BlobField extends EntityField { + + public BlobField(String selector) { + super(selector); + } + + public static BlobField acl(AclField... aclFields) { + return new BlobField(AclField.selector(aclFields)); + } + + public static BlobField bucket() { + return new BlobField("bucket"); + } + + public static BlobField cacheControl() { + return new BlobField("cacheControl"); + } + + public static BlobField componentCount() { + return new BlobField("componentCount"); + } + + public static BlobField contentDisposition() { + return new BlobField("contentDisposition"); + } + + public static BlobField contentEncoding() { + return new BlobField("contentEncoding"); + } + + public static BlobField contentLanguage() { + return new BlobField("contentLanguage"); + } + + public static BlobField contentType() { + return new BlobField("contentType"); + } + + public static BlobField crc32c() { + return new BlobField("crc32c"); + } + + public static BlobField etag() { + return new BlobField("etag"); + } + + public static BlobField generation() { + return new BlobField("generation"); + } + + public static BlobField id() { + return new BlobField("id"); + } + + public static BlobField kind() { + return new BlobField("kind"); + } + + public static BlobField md5Hash() { + return new BlobField("md5Hash"); + } + + public static BlobField mediaLink() { + return new BlobField("mediaLink"); + } + + public static BlobField metadata() { + return new BlobField("metadata"); + } + + public static BlobField metageneration() { + return new BlobField("metageneration"); + } + + public static BlobField name() { + return new BlobField("name"); + } + + public static BlobField owner() { + return new BlobField("owner"); + } + + public static BlobField selfLink() { + return new BlobField("selfLink"); + } + + public static BlobField size() { + return new BlobField("size"); + } + + public static BlobField storageClass() { + return new BlobField("storageClass"); + } + + public static BlobField timeCreated() { + return new BlobField("timeCreated"); + } + + public static BlobField timeDeleted() { + return new BlobField("timeDeleted"); + } + + public static BlobField updated() { + return new BlobField("updated"); + } + + static String selector(BlobField... fields) { + HashSet fieldStrings = Sets.newHashSetWithExpectedSize(fields.length + 2); + fieldStrings.add(bucket().selector()); + fieldStrings.add(name().selector()); + for (BlobField field : fields) { + fieldStrings.add(field.selector()); + } + return Joiner.on(',').join(fieldStrings); + } + } + class BucketTargetOption extends Option { private static final long serialVersionUID = -5880204616982900975L; @@ -277,6 +483,45 @@ public static BlobSourceOption metagenerationNotMatch(long metageneration) { } } + class BlobGetOption extends Option { + + private static final long serialVersionUID = 803817709703661480L; + + private BlobGetOption(StorageRpc.Option rpcOption, long value) { + super(rpcOption, value); + } + + private BlobGetOption(StorageRpc.Option rpcOption, String value) { + super(rpcOption, value); + } + + public static BlobGetOption generationMatch(long generation) { + return new BlobGetOption(StorageRpc.Option.IF_GENERATION_MATCH, generation); + } + + public static BlobGetOption generationNotMatch(long generation) { + return new BlobGetOption(StorageRpc.Option.IF_GENERATION_NOT_MATCH, generation); + } + + public static BlobGetOption metagenerationMatch(long metageneration) { + return new BlobGetOption(StorageRpc.Option.IF_METAGENERATION_MATCH, metageneration); + } + + public static BlobGetOption metagenerationNotMatch(long metageneration) { + return new BlobGetOption(StorageRpc.Option.IF_METAGENERATION_NOT_MATCH, metageneration); + } + + /** + * Returns an option to specify the blob's fields to be returned by the RPC call. If this option + * is not provided all blob's fields are returned. {@code BlobGetOption.fields}) can be used to + * specify only the fields of interest. Blob name and bucket are always returned, even if not + * specified. + */ + public static BlobGetOption fields(BlobField... fields) { + return new BlobGetOption(StorageRpc.Option.FIELDS, BlobField.selector(fields)); + } + } + class BucketListOption extends Option { private static final long serialVersionUID = 8754017079673290353L; @@ -321,6 +566,18 @@ public static BlobListOption prefix(String prefix) { public static BlobListOption recursive(boolean recursive) { return new BlobListOption(StorageRpc.Option.DELIMITER, recursive); } + + /** + * Returns an option to specify the blob's fields to be returned by the RPC call. If this option + * is not provided all blob's fields are returned. {@code BlobListOption.fields}) can be used to + * specify only the fields of interest. Blob name and bucket are always returned, even if not + * specified. + */ + public static BlobListOption fields(BlobField... fields) { + StringBuilder builder = new StringBuilder(); + builder.append("items(").append(BlobField.selector(fields)).append(")"); + return new BlobListOption(StorageRpc.Option.FIELDS, builder.toString()); + } } class SignUrlOption implements Serializable { @@ -807,14 +1064,14 @@ private static void checkContentType(BlobInfo blobInfo) throws IllegalArgumentEx * * @throws StorageException upon failure */ - BlobInfo get(String bucket, String blob, BlobSourceOption... options); + BlobInfo get(String bucket, String blob, BlobGetOption... options); /** * Return the requested blob or {@code null} if not found. * * @throws StorageException upon failure */ - BlobInfo get(BlobId blob, BlobSourceOption... options); + BlobInfo get(BlobId blob, BlobGetOption... options); /** * Return the requested blob or {@code null} if not found. diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java index d1e85368fecb..4d1a2ba09957 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java @@ -192,12 +192,12 @@ public com.google.api.services.storage.model.Bucket call() { } @Override - public BlobInfo get(String bucket, String blob, BlobSourceOption... options) { + public BlobInfo get(String bucket, String blob, BlobGetOption... options) { return get(BlobId.of(bucket, blob), options); } @Override - public BlobInfo get(BlobId blob, BlobSourceOption... options) { + public BlobInfo get(BlobId blob, BlobGetOption... options) { final StorageObject storedObject = blob.toPb(); final Map optionsMap = optionMap(options); try { @@ -222,7 +222,7 @@ public StorageObject call() { @Override public BlobInfo get(BlobId blob) { - return get(blob, new BlobSourceOption[0]); + return get(blob, new BlobGetOption[0]); } private abstract static class BasePageFetcher @@ -510,7 +510,7 @@ public BatchResponse apply(BatchRequest batchRequest) { } List>> toGet = Lists.newArrayListWithCapacity(batchRequest.toGet().size()); - for (Map.Entry> entry : batchRequest.toGet().entrySet()) { + for (Map.Entry> entry : batchRequest.toGet().entrySet()) { BlobId blob = entry.getKey(); Map optionsMap = optionMap(null, null, entry.getValue()); toGet.add(Tuple.>of(blob.toPb(), optionsMap)); diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BatchRequestTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BatchRequestTest.java index 06b1105d7b9b..600c8af0d554 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BatchRequestTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BatchRequestTest.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertTrue; import com.google.common.collect.Iterables; +import com.google.gcloud.storage.Storage.BlobGetOption; import com.google.gcloud.storage.Storage.BlobSourceOption; import com.google.gcloud.storage.Storage.BlobTargetOption; @@ -42,7 +43,7 @@ public void testBatchRequest() { .update(BlobInfo.builder("b2", "o1").build(), BlobTargetOption.predefinedAcl(PUBLIC_READ)) .update(BlobInfo.builder("b2", "o2").build()) .get("b3", "o1") - .get("b3", "o2", BlobSourceOption.generationMatch(1)) + .get("b3", "o2", BlobGetOption.generationMatch(1)) .get("b3", "o3") .build(); @@ -68,16 +69,14 @@ public void testBatchRequest() { assertTrue(Iterables.isEmpty(update.getValue())); assertFalse(updates.hasNext()); - Iterator>> gets = request - .toGet().entrySet().iterator(); - Entry> get = gets.next(); + Iterator>> gets = request.toGet().entrySet().iterator(); + Entry> get = gets.next(); assertEquals(BlobId.of("b3", "o1"), get.getKey()); assertTrue(Iterables.isEmpty(get.getValue())); get = gets.next(); assertEquals(BlobId.of("b3", "o2"), get.getKey()); assertEquals(1, Iterables.size(get.getValue())); - assertEquals(BlobSourceOption.generationMatch(1), - Iterables.getFirst(get.getValue(), null)); + assertEquals(BlobGetOption.generationMatch(1), Iterables.getFirst(get.getValue(), null)); get = gets.next(); assertEquals(BlobId.of("b3", "o3"), get.getKey()); assertTrue(Iterables.isEmpty(get.getValue())); diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobTest.java index defb1d35e3f4..02e325716c8b 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobTest.java @@ -72,14 +72,16 @@ public void testInfo() throws Exception { @Test public void testExists_True() throws Exception { - expect(storage.get(BLOB_INFO.blobId(), new Storage.BlobSourceOption[0])).andReturn(BLOB_INFO); + Storage.BlobGetOption[] expectedOptions = {Storage.BlobGetOption.fields()}; + expect(storage.get(BLOB_INFO.blobId(), expectedOptions)).andReturn(BLOB_INFO); replay(storage); assertTrue(blob.exists()); } @Test public void testExists_False() throws Exception { - expect(storage.get(BLOB_INFO.blobId(), new Storage.BlobSourceOption[0])).andReturn(null); + Storage.BlobGetOption[] expectedOptions = {Storage.BlobGetOption.fields()}; + expect(storage.get(BLOB_INFO.blobId(), expectedOptions)).andReturn(null); replay(storage); assertFalse(blob.exists()); } @@ -95,7 +97,7 @@ public void testContent() throws Exception { @Test public void testReload() throws Exception { BlobInfo updatedInfo = BLOB_INFO.toBuilder().cacheControl("c").build(); - expect(storage.get(BLOB_INFO.blobId(), new Storage.BlobSourceOption[0])).andReturn(updatedInfo); + expect(storage.get(BLOB_INFO.blobId(), new Storage.BlobGetOption[0])).andReturn(updatedInfo); replay(storage); Blob updatedBlob = blob.reload(); assertSame(storage, blob.storage()); diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java index decac7b1e0d2..99c3e6a8737b 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java @@ -137,7 +137,7 @@ public void testList() throws Exception { @Test public void testGet() throws Exception { BlobInfo info = BlobInfo.builder("b", "n").build(); - expect(storage.get(BlobId.of(bucket.info().name(), "n"), new Storage.BlobSourceOption[0])) + expect(storage.get(BlobId.of(bucket.info().name(), "n"), new Storage.BlobGetOption[0])) .andReturn(info); replay(storage); Blob blob = bucket.get("n"); diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java index d15e07dfeff7..ad003cb5f887 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java @@ -160,6 +160,87 @@ public void testCreateBlobMd5Fail() throws UnsupportedEncodingException { } } + @Test + public void testGetBlobEmptySelectedFields() { + String blobName = "test-get-empty-selected-fields-blob"; + BlobInfo blob = BlobInfo.builder(BUCKET, blobName).contentType(CONTENT_TYPE).build(); + assertNotNull(storage.create(blob)); + BlobInfo remoteBlob = storage.get(blob.blobId(), Storage.BlobGetOption.fields()); + assertEquals(blob.blobId(), remoteBlob.blobId()); + assertNull(remoteBlob.contentType()); + assertTrue(storage.delete(BUCKET, blobName)); + } + + @Test + public void testGetBlobSelectedFields() { + String blobName = "test-get-selected-fields-blob"; + BlobInfo blob = BlobInfo.builder(BUCKET, blobName) + .contentType(CONTENT_TYPE) + .metadata(ImmutableMap.of("k", "v")) + .build(); + assertNotNull(storage.create(blob)); + BlobInfo remoteBlob = storage.get(blob.blobId(), Storage.BlobGetOption.fields( + Storage.BlobField.metadata())); + assertEquals(blob.blobId(), remoteBlob.blobId()); + assertEquals(ImmutableMap.of("k", "v"), remoteBlob.metadata()); + assertNull(remoteBlob.contentType()); + assertTrue(storage.delete(BUCKET, blobName)); + } + + @Test + public void testListBlobsSelectedFields() { + String[] blobNames = {"test-list-blobs-selected-fields-blob1", + "test-list-blobs-selected-fields-blob2"}; + ImmutableMap metadata = ImmutableMap.of("k", "v"); + BlobInfo blob1 = BlobInfo.builder(BUCKET, blobNames[0]) + .contentType(CONTENT_TYPE) + .metadata(metadata) + .build(); + BlobInfo blob2 = BlobInfo.builder(BUCKET, blobNames[1]) + .contentType(CONTENT_TYPE) + .metadata(metadata) + .build(); + assertNotNull(storage.create(blob1)); + assertNotNull(storage.create(blob2)); + ListResult result = storage.list(BUCKET, + Storage.BlobListOption.prefix("test-list-blobs-selected-fields-blob"), + Storage.BlobListOption.fields(Storage.BlobField.metadata())); + int index = 0; + for (BlobInfo remoteBlob : result) { + assertEquals(BUCKET, remoteBlob.bucket()); + assertEquals(blobNames[index++], remoteBlob.name()); + assertEquals(metadata, remoteBlob.metadata()); + assertNull(remoteBlob.contentType()); + } + assertTrue(storage.delete(BUCKET, blobNames[0])); + assertTrue(storage.delete(BUCKET, blobNames[1])); + } + + @Test + public void testListBlobsEmptySelectedFields() { + String[] blobNames = {"test-list-blobs-empty-selected-fields-blob1", + "test-list-blobs-empty-selected-fields-blob2"}; + BlobInfo blob1 = BlobInfo.builder(BUCKET, blobNames[0]) + .contentType(CONTENT_TYPE) + .build(); + BlobInfo blob2 = BlobInfo.builder(BUCKET, blobNames[1]) + .contentType(CONTENT_TYPE) + .build(); + assertNotNull(storage.create(blob1)); + assertNotNull(storage.create(blob2)); + ListResult result = storage.list(BUCKET, + Storage.BlobListOption.prefix("test-list-blobs-empty-selected-fields-blob"), + Storage.BlobListOption.fields()); + int index = 0; + for (BlobInfo remoteBlob : result) { + assertEquals(BUCKET, remoteBlob.bucket()); + assertEquals(blobNames[index++], remoteBlob.name()); + assertNull(remoteBlob.contentType()); + } + assertTrue(storage.delete(BUCKET, blobNames[0])); + assertTrue(storage.delete(BUCKET, blobNames[1])); + } + @Test public void testUpdateBlob() { String blobName = "test-update-blob"; @@ -442,7 +523,7 @@ public void testBatchRequestFail() { BatchRequest batchRequest = BatchRequest.builder() .update(updatedBlob, Storage.BlobTargetOption.generationMatch()) .delete(BUCKET, blobName, Storage.BlobSourceOption.generationMatch(-1L)) - .get(BUCKET, blobName, Storage.BlobSourceOption.generationMatch(-1L)) + .get(BUCKET, blobName, Storage.BlobGetOption.generationMatch(-1L)) .build(); BatchResponse updateResponse = storage.apply(batchRequest); assertEquals(1, updateResponse.updates().size()); diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java index 6c77b4fcfc99..9abb96c63948 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java @@ -144,7 +144,18 @@ public class StorageImplTest { private static final Map BUCKET_SOURCE_OPTIONS = ImmutableMap.of( StorageRpc.Option.IF_METAGENERATION_MATCH, BUCKET_SOURCE_METAGENERATION.value()); - // Blob source options + // Blob read/source options + private static final Storage.BlobGetOption BLOB_GET_METAGENERATION = + Storage.BlobGetOption.metagenerationMatch(BLOB_INFO1.metageneration()); + private static final Storage.BlobGetOption BLOB_GET_GENERATION = + Storage.BlobGetOption.generationMatch(BLOB_INFO1.generation()); + private static final Storage.BlobGetOption BLOB_GET_FIELDS = + Storage.BlobGetOption.fields(Storage.BlobField.contentType(), Storage.BlobField.crc32c()); + private static final Storage.BlobGetOption BLOB_GET_EMPTY_FIELDS = + Storage.BlobGetOption.fields(); + private static final Map BLOB_GET_OPTIONS = ImmutableMap.of( + StorageRpc.Option.IF_METAGENERATION_MATCH, BLOB_GET_METAGENERATION.value(), + StorageRpc.Option.IF_GENERATION_MATCH, BLOB_GET_GENERATION.value()); private static final Storage.BlobSourceOption BLOB_SOURCE_METAGENERATION = Storage.BlobSourceOption.metagenerationMatch(BLOB_INFO1.metageneration()); private static final Storage.BlobSourceOption BLOB_SOURCE_GENERATION = @@ -170,6 +181,10 @@ public class StorageImplTest { Storage.BlobListOption.maxResults(42L); private static final Storage.BlobListOption BLOB_LIST_PREFIX = Storage.BlobListOption.prefix("prefix"); + private static final Storage.BlobListOption BLOB_LIST_FIELDS = + Storage.BlobListOption.fields(Storage.BlobField.contentType(), Storage.BlobField.md5Hash()); + private static final Storage.BlobListOption BLOB_LIST_EMPTY_FIELDS = + Storage.BlobListOption.fields(); private static final Map BLOB_LIST_OPTIONS = ImmutableMap.of( StorageRpc.Option.MAX_RESULTS, BLOB_LIST_MAX_RESULT.value(), StorageRpc.Option.PREFIX, BLOB_LIST_PREFIX.value()); @@ -383,12 +398,56 @@ public void testGetBlob() { @Test public void testGetBlobWithOptions() { EasyMock.expect( - storageRpcMock.get(BlobId.of(BUCKET_NAME1, BLOB_NAME1).toPb(), BLOB_SOURCE_OPTIONS)) + storageRpcMock.get(BlobId.of(BUCKET_NAME1, BLOB_NAME1).toPb(), BLOB_GET_OPTIONS)) .andReturn(BLOB_INFO1.toPb()); EasyMock.replay(storageRpcMock); storage = options.service(); BlobInfo blob = - storage.get(BUCKET_NAME1, BLOB_NAME1, BLOB_SOURCE_METAGENERATION, BLOB_SOURCE_GENERATION); + storage.get(BUCKET_NAME1, BLOB_NAME1, BLOB_GET_METAGENERATION, BLOB_GET_GENERATION); + assertEquals(BLOB_INFO1, blob); + } + + @Test + public void testGetWithSelectedFields() { + Capture> capturedOptions = + Capture.>newInstance(); + EasyMock.expect(storageRpcMock.get(EasyMock.eq(BlobId.of(BUCKET_NAME1, BLOB_NAME1).toPb()), + EasyMock.capture(capturedOptions))).andReturn(BLOB_INFO1.toPb()); + EasyMock.replay(storageRpcMock); + storage = options.service(); + BlobInfo blob = storage.get(BUCKET_NAME1, BLOB_NAME1, BLOB_GET_METAGENERATION, + BLOB_GET_GENERATION, BLOB_GET_FIELDS); + assertEquals(BLOB_GET_METAGENERATION.value(), + capturedOptions.getValue().get(BLOB_GET_METAGENERATION.rpcOption())); + assertEquals(BLOB_GET_GENERATION.value(), + capturedOptions.getValue().get(BLOB_GET_GENERATION.rpcOption())); + String selector = (String) capturedOptions.getValue().get(BLOB_GET_FIELDS.rpcOption()); + assertTrue(selector.contains("bucket")); + assertTrue(selector.contains("name")); + assertTrue(selector.contains("contentType")); + assertTrue(selector.contains("crc32c")); + assertEquals(30, selector.length()); + assertEquals(BLOB_INFO1, blob); + } + + @Test + public void testGetWithEmptyFields() { + Capture> capturedOptions = + Capture.>newInstance(); + EasyMock.expect(storageRpcMock.get(EasyMock.eq(BlobId.of(BUCKET_NAME1, BLOB_NAME1).toPb()), + EasyMock.capture(capturedOptions))).andReturn(BLOB_INFO1.toPb()); + EasyMock.replay(storageRpcMock); + storage = options.service(); + BlobInfo blob = storage.get(BUCKET_NAME1, BLOB_NAME1, BLOB_GET_METAGENERATION, + BLOB_GET_GENERATION, BLOB_GET_EMPTY_FIELDS); + assertEquals(BLOB_GET_METAGENERATION.value(), + capturedOptions.getValue().get(BLOB_GET_METAGENERATION.rpcOption())); + assertEquals(BLOB_GET_GENERATION.value(), + capturedOptions.getValue().get(BLOB_GET_GENERATION.rpcOption())); + String selector = (String) capturedOptions.getValue().get(BLOB_GET_FIELDS.rpcOption()); + assertTrue(selector.contains("bucket")); + assertTrue(selector.contains("name")); + assertEquals(11, selector.length()); assertEquals(BLOB_INFO1, blob); } @@ -473,6 +532,62 @@ public void testListBlobsWithOptions() { assertArrayEquals(blobList.toArray(), Iterables.toArray(page.values(), BlobInfo.class)); } + @Test + public void testListBlobsWithSelectedFields() { + String cursor = "cursor"; + Capture> capturedOptions = + Capture.>newInstance(); + ImmutableList blobList = ImmutableList.of(BLOB_INFO1, BLOB_INFO2); + Tuple> result = + Tuple.of(cursor, Iterables.transform(blobList, BlobInfo.TO_PB_FUNCTION)); + EasyMock.expect( + storageRpcMock.list(EasyMock.eq(BUCKET_NAME1), EasyMock.capture(capturedOptions))) + .andReturn(result); + EasyMock.replay(storageRpcMock); + storage = options.service(); + ListResult listResult = + storage.list(BUCKET_NAME1, BLOB_LIST_MAX_RESULT, BLOB_LIST_PREFIX, BLOB_LIST_FIELDS); + assertEquals(BLOB_LIST_MAX_RESULT.value(), + capturedOptions.getValue().get(BLOB_LIST_MAX_RESULT.rpcOption())); + assertEquals(BLOB_LIST_PREFIX.value(), + capturedOptions.getValue().get(BLOB_LIST_PREFIX.rpcOption())); + String selector = (String) capturedOptions.getValue().get(BLOB_LIST_FIELDS.rpcOption()); + assertTrue(selector.contains("bucket")); + assertTrue(selector.contains("name")); + assertTrue(selector.contains("contentType")); + assertTrue(selector.contains("md5Hash")); + assertEquals(38, selector.length()); + assertEquals(cursor, listResult.nextPageCursor()); + assertArrayEquals(blobList.toArray(), Iterables.toArray(listResult, BlobInfo.class)); + } + + @Test + public void testListBlobsWithEmptyFields() { + String cursor = "cursor"; + Capture> capturedOptions = + Capture.>newInstance(); + ImmutableList blobList = ImmutableList.of(BLOB_INFO1, BLOB_INFO2); + Tuple> result = + Tuple.of(cursor, Iterables.transform(blobList, BlobInfo.TO_PB_FUNCTION)); + EasyMock.expect( + storageRpcMock.list(EasyMock.eq(BUCKET_NAME1), EasyMock.capture(capturedOptions))) + .andReturn(result); + EasyMock.replay(storageRpcMock); + storage = options.service(); + ListResult listResult = + storage.list(BUCKET_NAME1, BLOB_LIST_MAX_RESULT, BLOB_LIST_PREFIX, BLOB_LIST_EMPTY_FIELDS); + assertEquals(BLOB_LIST_MAX_RESULT.value(), + capturedOptions.getValue().get(BLOB_LIST_MAX_RESULT.rpcOption())); + assertEquals(BLOB_LIST_PREFIX.value(), + capturedOptions.getValue().get(BLOB_LIST_PREFIX.rpcOption())); + String selector = (String) capturedOptions.getValue().get(BLOB_LIST_EMPTY_FIELDS.rpcOption()); + assertTrue(selector.contains("bucket")); + assertTrue(selector.contains("name")); + assertEquals(18, selector.length()); + assertEquals(cursor, listResult.nextPageCursor()); + assertArrayEquals(blobList.toArray(), Iterables.toArray(listResult, BlobInfo.class)); + } + @Test public void testUpdateBucket() { BucketInfo updatedBucketInfo = BUCKET_INFO1.toBuilder().indexPage("some-page").build(); From bea01573f3aec62ff7c96867467089eebf872975 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Tue, 3 Nov 2015 16:22:23 +0100 Subject: [PATCH 06/48] Add support for selected fields to bucket get and list - Remove AclField and make BlobField an enum type - Add BucketField enum to Storage - Add BucketGetOption class and use if for storage.get(bucket) - Add BucketSourceOption class to Bucket - Updated and add tests --- .../java/com/google/gcloud/storage/Blob.java | 21 +- .../com/google/gcloud/storage/Bucket.java | 67 ++++- .../com/google/gcloud/storage/Storage.java | 268 +++++++----------- .../google/gcloud/storage/StorageImpl.java | 2 +- .../google/gcloud/storage/ITStorageTest.java | 4 +- .../gcloud/storage/StorageImplTest.java | 111 +++++++- 6 files changed, 282 insertions(+), 191 deletions(-) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Blob.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Blob.java index 88f25c7e5cbd..d35fcef026c8 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Blob.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Blob.java @@ -18,7 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.gcloud.storage.Blob.BlobSourceOption.convert; +import static com.google.gcloud.storage.Blob.BlobSourceOption.toSourceOptions; import static com.google.gcloud.storage.Blob.BlobSourceOption.toGetOptions; import com.google.common.base.Function; @@ -58,7 +58,7 @@ private BlobSourceOption(StorageRpc.Option rpcOption) { super(rpcOption, null); } - private Storage.BlobSourceOption convert(BlobInfo blobInfo) { + private Storage.BlobSourceOption toSourceOptions(BlobInfo blobInfo) { switch (rpcOption()) { case IF_GENERATION_MATCH: return Storage.BlobSourceOption.generationMatch(blobInfo.generation()); @@ -104,11 +104,12 @@ public static BlobSourceOption metagenerationNotMatch() { return new BlobSourceOption(StorageRpc.Option.IF_METAGENERATION_NOT_MATCH); } - static Storage.BlobSourceOption[] convert(BlobInfo blobInfo, BlobSourceOption... options) { + static Storage.BlobSourceOption[] toSourceOptions(BlobInfo blobInfo, + BlobSourceOption... options) { Storage.BlobSourceOption[] convertedOptions = new Storage.BlobSourceOption[options.length]; int index = 0; for (BlobSourceOption option : options) { - convertedOptions[index++] = option.convert(blobInfo); + convertedOptions[index++] = option.toSourceOptions(blobInfo); } return convertedOptions; } @@ -126,7 +127,7 @@ static Storage.BlobGetOption[] toGetOptions(BlobInfo blobInfo, BlobSourceOption. /** * Constructs a {@code Blob} object for the provided {@code BlobInfo}. The storage service is used * to issue requests. - * + * * @param storage the storage service used for issuing requests * @param info blob's info */ @@ -138,7 +139,7 @@ public Blob(Storage storage, BlobInfo info) { /** * Creates a {@code Blob} object for the provided bucket and blob names. Performs an RPC call to * get the latest blob information. - * + * * @param storage the storage service used for issuing requests * @param bucket bucket's name * @param blob blob's name @@ -152,7 +153,7 @@ public static Blob load(Storage storage, String bucket, String blob) { /** * Creates a {@code Blob} object for the provided {@code blobId}. Performs an RPC call to get the * latest blob information. - * + * * @param storage the storage service used for issuing requests * @param blobId blob's identifier * @return the {@code Blob} object or {@code null} if not found. @@ -253,7 +254,7 @@ public Blob update(BlobInfo blobInfo, BlobTargetOption... options) { */ public CopyWriter copyTo(BlobId targetBlob, BlobSourceOption... options) { CopyRequest copyRequest = CopyRequest.builder().source(info.bucket(), info.name()) - .sourceOptions(convert(info, options)).target(targetBlob).build(); + .sourceOptions(toSourceOptions(info, options)).target(targetBlob).build(); return storage.copy(copyRequest); } @@ -265,7 +266,7 @@ public CopyWriter copyTo(BlobId targetBlob, BlobSourceOption... options) { * @throws StorageException upon failure */ public boolean delete(BlobSourceOption... options) { - return storage.delete(info.blobId(), convert(info, options)); + return storage.delete(info.blobId(), toSourceOptions(info, options)); } /** @@ -304,7 +305,7 @@ public CopyWriter copyTo(String targetBucket, String targetBlob, BlobSourceOptio * @throws StorageException upon failure */ public BlobReadChannel reader(BlobSourceOption... options) { - return storage.reader(info.blobId(), convert(info, options)); + return storage.reader(info.blobId(), toSourceOptions(info, options)); } /** diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java index 3b659f0cd355..4f2b5731e47a 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java @@ -24,10 +24,10 @@ import com.google.common.collect.Iterators; import com.google.gcloud.PageImpl; import com.google.gcloud.Page; +import com.google.gcloud.spi.StorageRpc; import com.google.gcloud.storage.Storage.BlobGetOption; import com.google.gcloud.storage.Storage.BlobTargetOption; import com.google.gcloud.storage.Storage.BlobWriteOption; -import com.google.gcloud.storage.Storage.BucketSourceOption; import com.google.gcloud.storage.Storage.BucketTargetOption; import java.io.IOException; @@ -119,6 +119,66 @@ public boolean equals(Object obj) { } } + public static class BucketSourceOption extends Option { + + private static final long serialVersionUID = 6928872234155522371L; + + private BucketSourceOption(StorageRpc.Option rpcOption) { + super(rpcOption, null); + } + + private Storage.BucketSourceOption toSourceOptions(BucketInfo bucketInfo) { + switch (rpcOption()) { + case IF_METAGENERATION_MATCH: + return Storage.BucketSourceOption.metagenerationMatch(bucketInfo.metageneration()); + case IF_METAGENERATION_NOT_MATCH: + return Storage.BucketSourceOption.metagenerationNotMatch(bucketInfo.metageneration()); + default: + throw new AssertionError("Unexpected enum value"); + } + } + + private Storage.BucketGetOption toGetOption(BucketInfo bucketInfo) { + switch (rpcOption()) { + case IF_METAGENERATION_MATCH: + return Storage.BucketGetOption.metagenerationMatch(bucketInfo.metageneration()); + case IF_METAGENERATION_NOT_MATCH: + return Storage.BucketGetOption.metagenerationNotMatch(bucketInfo.metageneration()); + default: + throw new AssertionError("Unexpected enum value"); + } + } + + public static BucketSourceOption metagenerationMatch() { + return new BucketSourceOption(StorageRpc.Option.IF_METAGENERATION_MATCH); + } + + public static BucketSourceOption metagenerationNotMatch() { + return new BucketSourceOption(StorageRpc.Option.IF_METAGENERATION_NOT_MATCH); + } + + static Storage.BucketSourceOption[] toSourceOptions(BucketInfo bucketInfo, + BucketSourceOption... options) { + Storage.BucketSourceOption[] convertedOptions = + new Storage.BucketSourceOption[options.length]; + int index = 0; + for (BucketSourceOption option : options) { + convertedOptions[index++] = option.toSourceOptions(bucketInfo); + } + return convertedOptions; + } + + static Storage.BucketGetOption[] toGetOptions(BucketInfo bucketInfo, + BucketSourceOption... options) { + Storage.BucketGetOption[] convertedOptions = new Storage.BucketGetOption[options.length]; + int index = 0; + for (BucketSourceOption option : options) { + convertedOptions[index++] = option.toGetOption(bucketInfo); + } + return convertedOptions; + } + } + /** * Constructs a {@code Bucket} object for the provided {@code BucketInfo}. The storage service is * used to issue requests. @@ -170,7 +230,8 @@ public boolean exists() { * @throws StorageException upon failure */ public Bucket reload(BucketSourceOption... options) { - return new Bucket(storage, storage.get(info.name(), options)); + return new Bucket(storage, storage.get(info.name(), + BucketSourceOption.toGetOptions(info, options))); } /** @@ -198,7 +259,7 @@ public Bucket update(BucketInfo bucketInfo, BucketTargetOption... options) { * @throws StorageException upon failure */ public boolean delete(BucketSourceOption... options) { - return storage.delete(info.name(), options); + return storage.delete(info.name(), BucketSourceOption.toSourceOptions(info, options)); } /** diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java index 4438342b853f..04e3a6bc687f 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java @@ -86,189 +86,84 @@ public String selector() { } } - public static class AclField extends EntityField { + enum BucketField { + ID("id"), + SELF_LINK("selfLink"), + NAME("name"), + TIME_CREATED("timeCreated"), + UPDATED("updated"), + METAGENERATION("metageneration"), + ACL("acl"), + DEFAULT_OBJECT_ACL("defaultObjectAcl"), + OWNER("owner"), + LOCATION("location"), + WEBSITE("website"), + VERSIONING("versioning"), + CORS("cors"), + STORAGE_CLASS("storageClass"), + ETAG("etag"); - public AclField(String selector) { - super(selector); - } - - public static AclField bucket() { - return new AclField("bucket"); - } - - public static AclField domain() { - return new AclField("domain"); - } - - public static AclField email() { - return new AclField("email"); - } - - public static AclField entity() { - return new AclField("entity"); - } - - public static AclField entityId() { - return new AclField("entityId"); - } - - public static AclField etag() { - return new AclField("etag"); - } - - public static AclField generation() { - return new AclField("generation"); - } - - public static AclField id() { - return new AclField("id"); - } - - public static AclField kind() { - return new AclField("kind"); - } - - public static AclField object() { - return new AclField("object"); - } - - public static AclField projectTeam() { - return new AclField("projectTeam"); - } + private final String selector; - public static AclField role() { - return new AclField("role"); + BucketField(String selector) { + this.selector = selector; } - public static AclField selfLink() { - return new AclField("selfLink"); + public String selector() { + return selector; } - static String selector(AclField... aclFields) { - HashSet fieldStrings = Sets.newHashSetWithExpectedSize(aclFields.length + 2); - fieldStrings.add(AclField.role().selector()); - fieldStrings.add(AclField.entity().selector()); - for (AclField field : aclFields) { + static String selector(BucketField... fields) { + HashSet fieldStrings = Sets.newHashSetWithExpectedSize(fields.length + 2); + fieldStrings.add(NAME.selector()); + for (BucketField field : fields) { fieldStrings.add(field.selector()); } - return new StringBuffer() - .append("acl(") - .append(Joiner.on(",").join(fieldStrings)) - .append(")") - .toString(); + return Joiner.on(',').join(fieldStrings); } } - public static class BlobField extends EntityField { - - public BlobField(String selector) { - super(selector); - } - - public static BlobField acl(AclField... aclFields) { - return new BlobField(AclField.selector(aclFields)); - } - - public static BlobField bucket() { - return new BlobField("bucket"); - } - - public static BlobField cacheControl() { - return new BlobField("cacheControl"); - } - - public static BlobField componentCount() { - return new BlobField("componentCount"); - } - - public static BlobField contentDisposition() { - return new BlobField("contentDisposition"); - } - - public static BlobField contentEncoding() { - return new BlobField("contentEncoding"); - } - - public static BlobField contentLanguage() { - return new BlobField("contentLanguage"); - } - - public static BlobField contentType() { - return new BlobField("contentType"); - } - - public static BlobField crc32c() { - return new BlobField("crc32c"); - } - - public static BlobField etag() { - return new BlobField("etag"); - } - - public static BlobField generation() { - return new BlobField("generation"); - } - - public static BlobField id() { - return new BlobField("id"); - } - - public static BlobField kind() { - return new BlobField("kind"); - } - - public static BlobField md5Hash() { - return new BlobField("md5Hash"); - } - - public static BlobField mediaLink() { - return new BlobField("mediaLink"); - } - - public static BlobField metadata() { - return new BlobField("metadata"); - } - - public static BlobField metageneration() { - return new BlobField("metageneration"); - } + enum BlobField { + ACL("acl"), + BUCKET("bucket"), + CACHE_CONTROL("cacheControl"), + COMPONENT_COUNT("componentCount"), + CONTENT_DISPOSITION("contentDisposition"), + CONTENT_ENCODING("contentEncoding"), + CONTENT_LANGUAGE("contentLanguage"), + CONTENT_TYPE("contentType"), + CRC32C("crc32c"), + ETAG("etag"), + GENERATION("generation"), + ID("id"), + KIND("kind"), + MD5HASH("md5Hash"), + MEDIA_LINK("mediaLink"), + METADATA("metadata"), + METAGENERATION("metageneration"), + NAME("name"), + OWNER("owner"), + SELF_LINK("selfLink"), + SIZE("size"), + STORAGE_CLASS("storageClass"), + TIME_CREATED("timeCreated"), + TIME_DELETED("timeDeleted"), + UPDATED("updated"); - public static BlobField name() { - return new BlobField("name"); - } - - public static BlobField owner() { - return new BlobField("owner"); - } - - public static BlobField selfLink() { - return new BlobField("selfLink"); - } - - public static BlobField size() { - return new BlobField("size"); - } - - public static BlobField storageClass() { - return new BlobField("storageClass"); - } - - public static BlobField timeCreated() { - return new BlobField("timeCreated"); - } + private final String selector; - public static BlobField timeDeleted() { - return new BlobField("timeDeleted"); + BlobField(String selector) { + this.selector = selector; } - public static BlobField updated() { - return new BlobField("updated"); + public String selector() { + return selector; } static String selector(BlobField... fields) { HashSet fieldStrings = Sets.newHashSetWithExpectedSize(fields.length + 2); - fieldStrings.add(bucket().selector()); - fieldStrings.add(name().selector()); + fieldStrings.add(BUCKET.selector()); + fieldStrings.add(NAME.selector()); for (BlobField field : fields) { fieldStrings.add(field.selector()); } @@ -322,6 +217,37 @@ public static BucketSourceOption metagenerationNotMatch(long metageneration) { } } + class BucketGetOption extends Option { + + private static final long serialVersionUID = 1901844869484087395L; + + private BucketGetOption(StorageRpc.Option rpcOption, long metageneration) { + super(rpcOption, metageneration); + } + + private BucketGetOption(StorageRpc.Option rpcOption, String value) { + super(rpcOption, value); + } + + public static BucketGetOption metagenerationMatch(long metageneration) { + return new BucketGetOption(StorageRpc.Option.IF_METAGENERATION_MATCH, metageneration); + } + + public static BucketGetOption metagenerationNotMatch(long metageneration) { + return new BucketGetOption(StorageRpc.Option.IF_METAGENERATION_NOT_MATCH, metageneration); + } + + /** + * Returns an option to specify the bucket's fields to be returned by the RPC call. If this + * option is not provided all bucket's fields are returned. {@code BucketGetOption.fields}) can + * be used to specify only the fields of interest. Bucket name is always returned, even if not + * specified. + */ + public static BucketGetOption fields(BucketField... fields) { + return new BucketGetOption(StorageRpc.Option.FIELDS, BucketField.selector(fields)); + } + } + class BlobTargetOption extends Option { private static final long serialVersionUID = 214616862061934846L; @@ -541,6 +467,18 @@ public static BucketListOption startPageToken(String pageToken) { public static BucketListOption prefix(String prefix) { return new BucketListOption(StorageRpc.Option.PREFIX, prefix); } + + /** + * Returns an option to specify the bucket's fields to be returned by the RPC call. If this + * option is not provided all bucket's fields are returned. {@code BucketListOption.fields}) can + * be used to specify only the fields of interest. Bucket name is always returned, even if not + * specified. + */ + public static BucketListOption fields(BucketField... fields) { + StringBuilder builder = new StringBuilder(); + builder.append("items(").append(BucketField.selector(fields)).append(")"); + return new BucketListOption(StorageRpc.Option.FIELDS, builder.toString()); + } } class BlobListOption extends Option { @@ -1057,7 +995,7 @@ private static void checkContentType(BlobInfo blobInfo) throws IllegalArgumentEx * * @throws StorageException upon failure */ - BucketInfo get(String bucket, BucketSourceOption... options); + BucketInfo get(String bucket, BucketGetOption... options); /** * Return the requested blob or {@code null} if not found. diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java index 4d1a2ba09957..4c85113e940e 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java @@ -167,7 +167,7 @@ public StorageObject call() { } @Override - public BucketInfo get(String bucket, BucketSourceOption... options) { + public BucketInfo get(String bucket, BucketGetOption... options) { final com.google.api.services.storage.model.Bucket bucketPb = BucketInfo.of(bucket).toPb(); final Map optionsMap = optionMap(options); try { diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java index ad003cb5f887..8a9a747f948d 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java @@ -180,7 +180,7 @@ public void testGetBlobSelectedFields() { .build(); assertNotNull(storage.create(blob)); BlobInfo remoteBlob = storage.get(blob.blobId(), Storage.BlobGetOption.fields( - Storage.BlobField.metadata())); + Storage.BlobField.METADATA)); assertEquals(blob.blobId(), remoteBlob.blobId()); assertEquals(ImmutableMap.of("k", "v"), remoteBlob.metadata()); assertNull(remoteBlob.contentType()); @@ -204,7 +204,7 @@ public void testListBlobsSelectedFields() { assertNotNull(storage.create(blob2)); ListResult result = storage.list(BUCKET, Storage.BlobListOption.prefix("test-list-blobs-selected-fields-blob"), - Storage.BlobListOption.fields(Storage.BlobField.metadata())); + Storage.BlobListOption.fields(Storage.BlobField.METADATA)); int index = 0; for (BlobInfo remoteBlob : result) { assertEquals(BUCKET, remoteBlob.bucket()); diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java index 9abb96c63948..f5c8cff1a335 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java @@ -138,19 +138,27 @@ public class StorageImplTest { private static final Storage.BlobWriteOption BLOB_WRITE_CRC2C = Storage.BlobWriteOption.crc32cMatch(); - // Bucket source options + // Bucket get/source options private static final Storage.BucketSourceOption BUCKET_SOURCE_METAGENERATION = Storage.BucketSourceOption.metagenerationMatch(BUCKET_INFO1.metageneration()); private static final Map BUCKET_SOURCE_OPTIONS = ImmutableMap.of( StorageRpc.Option.IF_METAGENERATION_MATCH, BUCKET_SOURCE_METAGENERATION.value()); + private static final Storage.BucketGetOption BUCKET_GET_METAGENERATION = + Storage.BucketGetOption.metagenerationMatch(BUCKET_INFO1.metageneration()); + private static final Storage.BucketGetOption BUCKET_GET_FIELDS = + Storage.BucketGetOption.fields(Storage.BucketField.LOCATION, Storage.BucketField.ACL); + private static final Storage.BucketGetOption BUCKET_GET_EMPTY_FIELDS = + Storage.BucketGetOption.fields(); + private static final Map BUCKET_GET_OPTIONS = ImmutableMap.of( + StorageRpc.Option.IF_METAGENERATION_MATCH, BUCKET_SOURCE_METAGENERATION.value()); - // Blob read/source options + // Blob get/source options private static final Storage.BlobGetOption BLOB_GET_METAGENERATION = Storage.BlobGetOption.metagenerationMatch(BLOB_INFO1.metageneration()); private static final Storage.BlobGetOption BLOB_GET_GENERATION = Storage.BlobGetOption.generationMatch(BLOB_INFO1.generation()); private static final Storage.BlobGetOption BLOB_GET_FIELDS = - Storage.BlobGetOption.fields(Storage.BlobField.contentType(), Storage.BlobField.crc32c()); + Storage.BlobGetOption.fields(Storage.BlobField.CONTENT_TYPE, Storage.BlobField.CRC32C); private static final Storage.BlobGetOption BLOB_GET_EMPTY_FIELDS = Storage.BlobGetOption.fields(); private static final Map BLOB_GET_OPTIONS = ImmutableMap.of( @@ -172,6 +180,10 @@ public class StorageImplTest { Storage.BucketListOption.maxResults(42L); private static final Storage.BucketListOption BUCKET_LIST_PREFIX = Storage.BucketListOption.prefix("prefix"); + private static final Storage.BucketListOption BUCKET_LIST_FIELDS = + Storage.BucketListOption.fields(Storage.BucketField.LOCATION, Storage.BucketField.ACL); + private static final Storage.BucketListOption BUCKET_LIST_EMPTY_FIELDS = + Storage.BucketListOption.fields(); private static final Map BUCKET_LIST_OPTIONS = ImmutableMap.of( StorageRpc.Option.MAX_RESULTS, BUCKET_LIST_MAX_RESULT.value(), StorageRpc.Option.PREFIX, BUCKET_LIST_PREFIX.value()); @@ -182,7 +194,7 @@ public class StorageImplTest { private static final Storage.BlobListOption BLOB_LIST_PREFIX = Storage.BlobListOption.prefix("prefix"); private static final Storage.BlobListOption BLOB_LIST_FIELDS = - Storage.BlobListOption.fields(Storage.BlobField.contentType(), Storage.BlobField.md5Hash()); + Storage.BlobListOption.fields(Storage.BlobField.CONTENT_TYPE, Storage.BlobField.MD5HASH); private static final Storage.BlobListOption BLOB_LIST_EMPTY_FIELDS = Storage.BlobListOption.fields(); private static final Map BLOB_LIST_OPTIONS = ImmutableMap.of( @@ -374,16 +386,51 @@ public void testGetBucket() { @Test public void testGetBucketWithOptions() { - EasyMock.expect(storageRpcMock.get(BucketInfo.of(BUCKET_NAME1).toPb(), BUCKET_SOURCE_OPTIONS)) + EasyMock.expect(storageRpcMock.get(BucketInfo.of(BUCKET_NAME1).toPb(), BUCKET_GET_OPTIONS)) .andReturn(BUCKET_INFO1.toPb()); EasyMock.replay(storageRpcMock); storage = options.service(); - BucketInfo bucket = - storage.get(BUCKET_NAME1, - Storage.BucketSourceOption.metagenerationMatch(BUCKET_INFO1.metageneration())); + BucketInfo bucket = storage.get(BUCKET_NAME1, BUCKET_GET_METAGENERATION); assertEquals(BUCKET_INFO1, bucket); } + @Test + public void testGetBucketWithSelectedFields() { + Capture> capturedOptions = + Capture.>newInstance(); + EasyMock.expect(storageRpcMock.get(EasyMock.eq(BucketInfo.of(BUCKET_NAME1).toPb()), + EasyMock.capture(capturedOptions))).andReturn(BUCKET_INFO1.toPb()); + EasyMock.replay(storageRpcMock); + storage = options.service(); + BucketInfo bucket = storage.get(BUCKET_NAME1, BUCKET_GET_METAGENERATION, BUCKET_GET_FIELDS); + assertEquals(BUCKET_GET_METAGENERATION.value(), + capturedOptions.getValue().get(BUCKET_GET_METAGENERATION.rpcOption())); + String selector = (String) capturedOptions.getValue().get(BLOB_GET_FIELDS.rpcOption()); + assertTrue(selector.contains("name")); + assertTrue(selector.contains("location")); + assertTrue(selector.contains("acl")); + assertEquals(17, selector.length()); + assertEquals(BUCKET_INFO1.name(), bucket.name()); + } + + @Test + public void testGetBucketWithEmptyFields() { + Capture> capturedOptions = + Capture.>newInstance(); + EasyMock.expect(storageRpcMock.get(EasyMock.eq(BucketInfo.of(BUCKET_NAME1).toPb()), + EasyMock.capture(capturedOptions))).andReturn(BUCKET_INFO1.toPb()); + EasyMock.replay(storageRpcMock); + storage = options.service(); + BucketInfo bucket = storage.get(BUCKET_NAME1, BUCKET_GET_METAGENERATION, + BUCKET_GET_EMPTY_FIELDS); + assertEquals(BUCKET_GET_METAGENERATION.value(), + capturedOptions.getValue().get(BUCKET_GET_METAGENERATION.rpcOption())); + String selector = (String) capturedOptions.getValue().get(BLOB_GET_FIELDS.rpcOption()); + assertTrue(selector.contains("name")); + assertEquals(4, selector.length()); + assertEquals(BUCKET_INFO1.name(), bucket.name()); + } + @Test public void testGetBlob() { EasyMock.expect( @@ -408,7 +455,7 @@ public void testGetBlobWithOptions() { } @Test - public void testGetWithSelectedFields() { + public void testGetBlobWithSelectedFields() { Capture> capturedOptions = Capture.>newInstance(); EasyMock.expect(storageRpcMock.get(EasyMock.eq(BlobId.of(BUCKET_NAME1, BLOB_NAME1).toPb()), @@ -431,7 +478,7 @@ public void testGetWithSelectedFields() { } @Test - public void testGetWithEmptyFields() { + public void testGetBlobWithEmptyFields() { Capture> capturedOptions = Capture.>newInstance(); EasyMock.expect(storageRpcMock.get(EasyMock.eq(BlobId.of(BUCKET_NAME1, BLOB_NAME1).toPb()), @@ -491,6 +538,48 @@ public void testListBucketsWithOptions() { assertArrayEquals(bucketList.toArray(), Iterables.toArray(page.values(), BucketInfo.class)); } + @Test + public void testListBucketsWithSelectedFields() { + String cursor = "cursor"; + Capture> capturedOptions = + Capture.>newInstance(); + ImmutableList bucketList = ImmutableList.of(BUCKET_INFO1, BUCKET_INFO2); + Tuple> result = + Tuple.of(cursor, Iterables.transform(bucketList, BucketInfo.TO_PB_FUNCTION)); + EasyMock.expect(storageRpcMock.list(EasyMock.capture(capturedOptions))).andReturn(result); + EasyMock.replay(storageRpcMock); + storage = options.service(); + ListResult listResult = storage.list(BUCKET_LIST_FIELDS); + String selector = (String) capturedOptions.getValue().get(BLOB_LIST_FIELDS.rpcOption()); + assertTrue(selector.contains("items")); + assertTrue(selector.contains("name")); + assertTrue(selector.contains("acl")); + assertTrue(selector.contains("location")); + assertEquals(24, selector.length()); + assertEquals(cursor, listResult.nextPageCursor()); + assertArrayEquals(bucketList.toArray(), Iterables.toArray(listResult, BucketInfo.class)); + } + + @Test + public void testListBucketsWithEmptyFields() { + String cursor = "cursor"; + Capture> capturedOptions = + Capture.>newInstance(); + ImmutableList bucketList = ImmutableList.of(BUCKET_INFO1, BUCKET_INFO2); + Tuple> result = + Tuple.of(cursor, Iterables.transform(bucketList, BucketInfo.TO_PB_FUNCTION)); + EasyMock.expect(storageRpcMock.list(EasyMock.capture(capturedOptions))).andReturn(result); + EasyMock.replay(storageRpcMock); + storage = options.service(); + ListResult listResult = storage.list(BUCKET_LIST_EMPTY_FIELDS); + String selector = (String) capturedOptions.getValue().get(BLOB_LIST_FIELDS.rpcOption()); + assertTrue(selector.contains("items")); + assertTrue(selector.contains("name")); + assertEquals(11, selector.length()); + assertEquals(cursor, listResult.nextPageCursor()); + assertArrayEquals(bucketList.toArray(), Iterables.toArray(listResult, BucketInfo.class)); + } + @Test public void testListBlobs() { String cursor = "cursor"; @@ -552,6 +641,7 @@ public void testListBlobsWithSelectedFields() { assertEquals(BLOB_LIST_PREFIX.value(), capturedOptions.getValue().get(BLOB_LIST_PREFIX.rpcOption())); String selector = (String) capturedOptions.getValue().get(BLOB_LIST_FIELDS.rpcOption()); + assertTrue(selector.contains("items")); assertTrue(selector.contains("bucket")); assertTrue(selector.contains("name")); assertTrue(selector.contains("contentType")); @@ -581,6 +671,7 @@ public void testListBlobsWithEmptyFields() { assertEquals(BLOB_LIST_PREFIX.value(), capturedOptions.getValue().get(BLOB_LIST_PREFIX.rpcOption())); String selector = (String) capturedOptions.getValue().get(BLOB_LIST_EMPTY_FIELDS.rpcOption()); + assertTrue(selector.contains("items")); assertTrue(selector.contains("bucket")); assertTrue(selector.contains("name")); assertEquals(18, selector.length()); From f11c05a4846d598984fee5c132493d962fdf92e0 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 4 Nov 2015 08:47:27 +0100 Subject: [PATCH 07/48] Add field selection to StorageRpc bucket get and list --- .../src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java | 2 ++ 1 file changed, 2 insertions(+) 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 29552d5121e5..b1e188f1d1fb 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 @@ -151,6 +151,7 @@ public Tuple> list(Map options) { .setPrefix(PREFIX.getString(options)) .setMaxResults(MAX_RESULTS.getLong(options)) .setPageToken(PAGE_TOKEN.getString(options)) + .setFields(FIELDS.getString(options)) .execute(); return Tuple.>of(buckets.getNextPageToken(), buckets.getItems()); } catch (IOException ex) { @@ -186,6 +187,7 @@ public Bucket get(Bucket bucket, Map options) { .setProjection(DEFAULT_PROJECTION) .setIfMetagenerationMatch(IF_METAGENERATION_MATCH.getLong(options)) .setIfMetagenerationNotMatch(IF_METAGENERATION_NOT_MATCH.getLong(options)) + .setFields(FIELDS.getString(options)) .execute(); } catch (IOException ex) { throw translate(ex); From ba4bfa6017b39800abfda831ee071664802e6186 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 4 Nov 2015 08:49:43 +0100 Subject: [PATCH 08/48] Add field selection to Bucket.exist --- .../java/com/google/gcloud/storage/Bucket.java | 15 ++++++++++----- .../com/google/gcloud/storage/BucketTest.java | 6 ++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java index 4f2b5731e47a..7c386373995f 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java @@ -18,6 +18,8 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.gcloud.storage.Bucket.BucketSourceOption.toGetOptions; +import static com.google.gcloud.storage.Bucket.BucketSourceOption.toSourceOptions; import com.google.common.base.Function; import com.google.common.base.MoreObjects; @@ -35,6 +37,7 @@ import java.io.ObjectInputStream; import java.io.Serializable; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -218,8 +221,11 @@ public BucketInfo info() { * @return true if this bucket exists, false otherwise * @throws StorageException upon failure */ - public boolean exists() { - return storage.get(info.name()) != null; + public boolean exists(BucketSourceOption... options) { + int length = options.length; + Storage.BucketGetOption[] getOptions = Arrays.copyOf(toGetOptions(info, options), length + 1); + getOptions[length] = Storage.BucketGetOption.fields(); + return storage.get(info.name(), getOptions) != null; } /** @@ -230,8 +236,7 @@ public boolean exists() { * @throws StorageException upon failure */ public Bucket reload(BucketSourceOption... options) { - return new Bucket(storage, storage.get(info.name(), - BucketSourceOption.toGetOptions(info, options))); + return new Bucket(storage, storage.get(info.name(), toGetOptions(info, options))); } /** @@ -259,7 +264,7 @@ public Bucket update(BucketInfo bucketInfo, BucketTargetOption... options) { * @throws StorageException upon failure */ public boolean delete(BucketSourceOption... options) { - return storage.delete(info.name(), BucketSourceOption.toSourceOptions(info, options)); + return storage.delete(info.name(), toSourceOptions(info, options)); } /** diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java index 99c3e6a8737b..5d8fc5a9dffc 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java @@ -75,14 +75,16 @@ public void testInfo() throws Exception { @Test public void testExists_True() throws Exception { - expect(storage.get(BUCKET_INFO.name())).andReturn(BUCKET_INFO); + Storage.BucketGetOption[] expectedOptions = {Storage.BucketGetOption.fields()}; + expect(storage.get(BUCKET_INFO.name(), expectedOptions)).andReturn(BUCKET_INFO); replay(storage); assertTrue(bucket.exists()); } @Test public void testExists_False() throws Exception { - expect(storage.get(BUCKET_INFO.name())).andReturn(null); + Storage.BucketGetOption[] expectedOptions = {Storage.BucketGetOption.fields()}; + expect(storage.get(BUCKET_INFO.name(), expectedOptions)).andReturn(null); replay(storage); assertFalse(bucket.exists()); } From 46b60df4a132b669bb8752bc7bf02bd5f24c57d1 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 4 Nov 2015 08:51:40 +0100 Subject: [PATCH 09/48] Delete EntityField class and remove non-accessible fields from Bucket/BlobField --- .../java/com/google/gcloud/storage/Storage.java | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java index 04e3a6bc687f..52387310de71 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java @@ -73,25 +73,11 @@ String entry() { } } - public static abstract class EntityField { - - private final String selector; - - public EntityField(String selector) { - this.selector = selector; - } - - public String selector() { - return selector; - } - } - enum BucketField { ID("id"), SELF_LINK("selfLink"), NAME("name"), TIME_CREATED("timeCreated"), - UPDATED("updated"), METAGENERATION("metageneration"), ACL("acl"), DEFAULT_OBJECT_ACL("defaultObjectAcl"), @@ -114,7 +100,7 @@ public String selector() { } static String selector(BucketField... fields) { - HashSet fieldStrings = Sets.newHashSetWithExpectedSize(fields.length + 2); + HashSet fieldStrings = Sets.newHashSetWithExpectedSize(fields.length + 1); fieldStrings.add(NAME.selector()); for (BucketField field : fields) { fieldStrings.add(field.selector()); @@ -146,7 +132,6 @@ enum BlobField { SELF_LINK("selfLink"), SIZE("size"), STORAGE_CLASS("storageClass"), - TIME_CREATED("timeCreated"), TIME_DELETED("timeDeleted"), UPDATED("updated"); From 603d50c0bddbc5c816ced52211cdfb6ae0e55a64 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 4 Nov 2015 09:02:47 +0100 Subject: [PATCH 10/48] Add IT tests for bucket's field selection, add test for selecting all fields --- .../google/gcloud/storage/ITStorageTest.java | 77 ++++++++++++++++--- .../gcloud/storage/StorageImplTest.java | 24 +++--- 2 files changed, 79 insertions(+), 22 deletions(-) diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java index 8a9a747f948d..659c3d94ad4d 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java @@ -26,7 +26,10 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.gcloud.Page; import com.google.gcloud.RestorableState; +import com.google.gcloud.storage.Storage.BlobField; +import com.google.gcloud.storage.Storage.BucketField; import com.google.gcloud.storage.testing.RemoteGcsHelper; import org.junit.AfterClass; @@ -80,17 +83,49 @@ public static void afterClass() @Test(timeout = 5000) public void testListBuckets() throws InterruptedException { - Iterator bucketIterator = - storage.list(Storage.BucketListOption.prefix(BUCKET)).values().iterator(); + Iterator bucketIterator = storage.list(Storage.BucketListOption.prefix(BUCKET), + Storage.BucketListOption.fields()).values().iterator(); while (!bucketIterator.hasNext()) { Thread.sleep(500); - bucketIterator = storage.list(Storage.BucketListOption.prefix(BUCKET)).values().iterator(); + bucketIterator = storage.list(Storage.BucketListOption.prefix(BUCKET), + Storage.BucketListOption.fields()).values().iterator(); } while (bucketIterator.hasNext()) { - assertTrue(bucketIterator.next().name().startsWith(BUCKET)); + BucketInfo remoteBucket = bucketIterator.next(); + assertTrue(remoteBucket.name().startsWith(BUCKET)); + assertNull(remoteBucket.createTime()); + assertNull(remoteBucket.selfLink()); } } + @Test + public void testGetBucketSelectedFields() { + BucketInfo remoteBucket = storage.get(BUCKET, Storage.BucketGetOption.fields(BucketField.ID)); + assertEquals(BUCKET, remoteBucket.name()); + assertNull(remoteBucket.createTime()); + assertNotNull(remoteBucket.id()); + } + + @Test + public void testGetBucketAllSelectedFields() { + BucketInfo remoteBucket = storage.get(BUCKET, Storage.BucketGetOption.fields(BucketField.ACL, + BucketField.CORS, BucketField.DEFAULT_OBJECT_ACL, BucketField.ETAG, BucketField.ID, + BucketField.LOCATION, BucketField.METAGENERATION, BucketField.NAME, BucketField.OWNER, + BucketField.SELF_LINK, BucketField.STORAGE_CLASS, BucketField.TIME_CREATED, + BucketField.VERSIONING, BucketField.WEBSITE)); + assertEquals(BUCKET, remoteBucket.name()); + assertNotNull(remoteBucket.createTime()); + assertNotNull(remoteBucket.selfLink()); + } + + @Test + public void testGetBucketEmptyFields() { + BucketInfo remoteBucket = storage.get(BUCKET, Storage.BucketGetOption.fields()); + assertEquals(BUCKET, remoteBucket.name()); + assertNull(remoteBucket.createTime()); + assertNull(remoteBucket.selfLink()); + } + @Test public void testCreateBlob() { String blobName = "test-create-blob"; @@ -180,13 +215,35 @@ public void testGetBlobSelectedFields() { .build(); assertNotNull(storage.create(blob)); BlobInfo remoteBlob = storage.get(blob.blobId(), Storage.BlobGetOption.fields( - Storage.BlobField.METADATA)); + BlobField.METADATA)); assertEquals(blob.blobId(), remoteBlob.blobId()); assertEquals(ImmutableMap.of("k", "v"), remoteBlob.metadata()); assertNull(remoteBlob.contentType()); assertTrue(storage.delete(BUCKET, blobName)); } + @Test + public void testGetBlobAllSelectedFields() { + String blobName = "test-get-all-selected-fields-blob"; + BlobInfo blob = BlobInfo.builder(BUCKET, blobName) + .contentType(CONTENT_TYPE) + .metadata(ImmutableMap.of("k", "v")) + .build(); + assertNotNull(storage.create(blob)); + BlobInfo remoteBlob = storage.get(blob.blobId(), Storage.BlobGetOption.fields( + BlobField.ACL, BlobField.BUCKET, BlobField.CACHE_CONTROL, BlobField.COMPONENT_COUNT, + BlobField.CONTENT_DISPOSITION, BlobField.CONTENT_ENCODING, BlobField.CONTENT_LANGUAGE, + BlobField.CONTENT_TYPE, BlobField.CRC32C, BlobField.ETAG, BlobField.GENERATION, + BlobField.ID, BlobField.KIND, BlobField.MD5HASH, BlobField.MEDIA_LINK, BlobField.METADATA, + BlobField.METAGENERATION, BlobField.NAME, BlobField.OWNER, BlobField.SELF_LINK, + BlobField.SIZE, BlobField.STORAGE_CLASS, BlobField.TIME_DELETED, BlobField.UPDATED)); + assertEquals(blob.blobId(), remoteBlob.blobId()); + assertEquals(ImmutableMap.of("k", "v"), remoteBlob.metadata()); + assertNotNull(remoteBlob.id()); + assertNotNull(remoteBlob.selfLink()); + assertTrue(storage.delete(BUCKET, blobName)); + } + @Test public void testListBlobsSelectedFields() { String[] blobNames = {"test-list-blobs-selected-fields-blob1", @@ -202,11 +259,11 @@ public void testListBlobsSelectedFields() { .build(); assertNotNull(storage.create(blob1)); assertNotNull(storage.create(blob2)); - ListResult result = storage.list(BUCKET, + Page page = storage.list(BUCKET, Storage.BlobListOption.prefix("test-list-blobs-selected-fields-blob"), - Storage.BlobListOption.fields(Storage.BlobField.METADATA)); + Storage.BlobListOption.fields(BlobField.METADATA)); int index = 0; - for (BlobInfo remoteBlob : result) { + for (BlobInfo remoteBlob : page.values()) { assertEquals(BUCKET, remoteBlob.bucket()); assertEquals(blobNames[index++], remoteBlob.name()); assertEquals(metadata, remoteBlob.metadata()); @@ -228,11 +285,11 @@ public void testListBlobsEmptySelectedFields() { .build(); assertNotNull(storage.create(blob1)); assertNotNull(storage.create(blob2)); - ListResult result = storage.list(BUCKET, + Page page = storage.list(BUCKET, Storage.BlobListOption.prefix("test-list-blobs-empty-selected-fields-blob"), Storage.BlobListOption.fields()); int index = 0; - for (BlobInfo remoteBlob : result) { + for (BlobInfo remoteBlob : page.values()) { assertEquals(BUCKET, remoteBlob.bucket()); assertEquals(blobNames[index++], remoteBlob.name()); assertNull(remoteBlob.contentType()); diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java index f5c8cff1a335..d5e2f8de7397 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java @@ -549,15 +549,15 @@ public void testListBucketsWithSelectedFields() { EasyMock.expect(storageRpcMock.list(EasyMock.capture(capturedOptions))).andReturn(result); EasyMock.replay(storageRpcMock); storage = options.service(); - ListResult listResult = storage.list(BUCKET_LIST_FIELDS); + Page page = storage.list(BUCKET_LIST_FIELDS); String selector = (String) capturedOptions.getValue().get(BLOB_LIST_FIELDS.rpcOption()); assertTrue(selector.contains("items")); assertTrue(selector.contains("name")); assertTrue(selector.contains("acl")); assertTrue(selector.contains("location")); assertEquals(24, selector.length()); - assertEquals(cursor, listResult.nextPageCursor()); - assertArrayEquals(bucketList.toArray(), Iterables.toArray(listResult, BucketInfo.class)); + assertEquals(cursor, page.nextPageCursor()); + assertArrayEquals(bucketList.toArray(), Iterables.toArray(page.values(), BucketInfo.class)); } @Test @@ -571,13 +571,13 @@ public void testListBucketsWithEmptyFields() { EasyMock.expect(storageRpcMock.list(EasyMock.capture(capturedOptions))).andReturn(result); EasyMock.replay(storageRpcMock); storage = options.service(); - ListResult listResult = storage.list(BUCKET_LIST_EMPTY_FIELDS); + Page page = storage.list(BUCKET_LIST_EMPTY_FIELDS); String selector = (String) capturedOptions.getValue().get(BLOB_LIST_FIELDS.rpcOption()); assertTrue(selector.contains("items")); assertTrue(selector.contains("name")); assertEquals(11, selector.length()); - assertEquals(cursor, listResult.nextPageCursor()); - assertArrayEquals(bucketList.toArray(), Iterables.toArray(listResult, BucketInfo.class)); + assertEquals(cursor, page.nextPageCursor()); + assertArrayEquals(bucketList.toArray(), Iterables.toArray(page.values(), BucketInfo.class)); } @Test @@ -634,7 +634,7 @@ public void testListBlobsWithSelectedFields() { .andReturn(result); EasyMock.replay(storageRpcMock); storage = options.service(); - ListResult listResult = + Page page = storage.list(BUCKET_NAME1, BLOB_LIST_MAX_RESULT, BLOB_LIST_PREFIX, BLOB_LIST_FIELDS); assertEquals(BLOB_LIST_MAX_RESULT.value(), capturedOptions.getValue().get(BLOB_LIST_MAX_RESULT.rpcOption())); @@ -647,8 +647,8 @@ public void testListBlobsWithSelectedFields() { assertTrue(selector.contains("contentType")); assertTrue(selector.contains("md5Hash")); assertEquals(38, selector.length()); - assertEquals(cursor, listResult.nextPageCursor()); - assertArrayEquals(blobList.toArray(), Iterables.toArray(listResult, BlobInfo.class)); + assertEquals(cursor, page.nextPageCursor()); + assertArrayEquals(blobList.toArray(), Iterables.toArray(page.values(), BlobInfo.class)); } @Test @@ -664,7 +664,7 @@ public void testListBlobsWithEmptyFields() { .andReturn(result); EasyMock.replay(storageRpcMock); storage = options.service(); - ListResult listResult = + Page page = storage.list(BUCKET_NAME1, BLOB_LIST_MAX_RESULT, BLOB_LIST_PREFIX, BLOB_LIST_EMPTY_FIELDS); assertEquals(BLOB_LIST_MAX_RESULT.value(), capturedOptions.getValue().get(BLOB_LIST_MAX_RESULT.rpcOption())); @@ -675,8 +675,8 @@ public void testListBlobsWithEmptyFields() { assertTrue(selector.contains("bucket")); assertTrue(selector.contains("name")); assertEquals(18, selector.length()); - assertEquals(cursor, listResult.nextPageCursor()); - assertArrayEquals(blobList.toArray(), Iterables.toArray(listResult, BlobInfo.class)); + assertEquals(cursor, page.nextPageCursor()); + assertArrayEquals(blobList.toArray(), Iterables.toArray(page.values(), BlobInfo.class)); } @Test From af7a08b4e03506fd830fa8d0fcbed8b7e279e8e1 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 4 Nov 2015 23:05:53 +0100 Subject: [PATCH 11/48] Use BlobField and BucketField .values() in IT tests --- .../com/google/gcloud/storage/ITStorageTest.java | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java index 659c3d94ad4d..423e972a8de6 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java @@ -108,11 +108,8 @@ public void testGetBucketSelectedFields() { @Test public void testGetBucketAllSelectedFields() { - BucketInfo remoteBucket = storage.get(BUCKET, Storage.BucketGetOption.fields(BucketField.ACL, - BucketField.CORS, BucketField.DEFAULT_OBJECT_ACL, BucketField.ETAG, BucketField.ID, - BucketField.LOCATION, BucketField.METAGENERATION, BucketField.NAME, BucketField.OWNER, - BucketField.SELF_LINK, BucketField.STORAGE_CLASS, BucketField.TIME_CREATED, - BucketField.VERSIONING, BucketField.WEBSITE)); + BucketInfo remoteBucket = storage.get(BUCKET, + Storage.BucketGetOption.fields(BucketField.values())); assertEquals(BUCKET, remoteBucket.name()); assertNotNull(remoteBucket.createTime()); assertNotNull(remoteBucket.selfLink()); @@ -230,13 +227,8 @@ public void testGetBlobAllSelectedFields() { .metadata(ImmutableMap.of("k", "v")) .build(); assertNotNull(storage.create(blob)); - BlobInfo remoteBlob = storage.get(blob.blobId(), Storage.BlobGetOption.fields( - BlobField.ACL, BlobField.BUCKET, BlobField.CACHE_CONTROL, BlobField.COMPONENT_COUNT, - BlobField.CONTENT_DISPOSITION, BlobField.CONTENT_ENCODING, BlobField.CONTENT_LANGUAGE, - BlobField.CONTENT_TYPE, BlobField.CRC32C, BlobField.ETAG, BlobField.GENERATION, - BlobField.ID, BlobField.KIND, BlobField.MD5HASH, BlobField.MEDIA_LINK, BlobField.METADATA, - BlobField.METAGENERATION, BlobField.NAME, BlobField.OWNER, BlobField.SELF_LINK, - BlobField.SIZE, BlobField.STORAGE_CLASS, BlobField.TIME_DELETED, BlobField.UPDATED)); + BlobInfo remoteBlob = storage.get(blob.blobId(), + Storage.BlobGetOption.fields(BlobField.values())); assertEquals(blob.blobId(), remoteBlob.blobId()); assertEquals(ImmutableMap.of("k", "v"), remoteBlob.metadata()); assertNotNull(remoteBlob.id()); From 6636e23cac4c18a9fcc4a826aecc531294a564c0 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Wed, 4 Nov 2015 17:04:25 -0800 Subject: [PATCH 12/48] Create BaseServiceException in gcloud-java-core --- .../google/gcloud/BaseServiceException.java | 51 +++++++++++++++++++ .../gcloud/BaseServiceExceptionTest.java | 45 ++++++++++++++++ .../gcloud/datastore/DatastoreException.java | 50 +++++++++--------- .../datastore/DatastoreExceptionTest.java | 12 ++--- .../gcloud/datastore/DatastoreTest.java | 4 +- .../gcloud/storage/StorageException.java | 24 ++------- 6 files changed, 135 insertions(+), 51 deletions(-) create mode 100644 gcloud-java-core/src/main/java/com/google/gcloud/BaseServiceException.java create mode 100644 gcloud-java-core/src/test/java/com/google/gcloud/BaseServiceExceptionTest.java 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 new file mode 100644 index 000000000000..45c047d4710a --- /dev/null +++ b/gcloud-java-core/src/main/java/com/google/gcloud/BaseServiceException.java @@ -0,0 +1,51 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.gcloud; + +/** + * Base service exception. + */ +public class BaseServiceException extends RuntimeException { + + private static final long serialVersionUID = 5028833760039966178L; + + private final int code; + private final boolean retryable; + + public BaseServiceException(int code, String message, boolean retryable) { + super(message); + this.code = code; + this.retryable = retryable; + } + + public BaseServiceException(int code, String message, boolean retryable, Exception cause) { + super(message, cause); + this.code = code; + this.retryable = retryable; + } + + /** + * Returns the code associated with this exception. + */ + public int code() { + return code; + } + + public boolean retryable() { + return retryable; + } +} diff --git a/gcloud-java-core/src/test/java/com/google/gcloud/BaseServiceExceptionTest.java b/gcloud-java-core/src/test/java/com/google/gcloud/BaseServiceExceptionTest.java new file mode 100644 index 000000000000..f30fd3abfb79 --- /dev/null +++ b/gcloud-java-core/src/test/java/com/google/gcloud/BaseServiceExceptionTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.gcloud; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +/** + * Tests for {@link BaseServiceException}. + */ +public class BaseServiceExceptionTest { + + private final int code = 1; + private final String message = "some message"; + private final boolean retryable = true; + + @Test + public void testBaseServiceException() { + BaseServiceException serviceException = new BaseServiceException(code, message, retryable); + assertEquals(serviceException.code(), code); + assertEquals(serviceException.getMessage(), message); + assertEquals(serviceException.getCause(), null); + + Exception cause = new RuntimeException(); + serviceException = new BaseServiceException(code, message, retryable, cause); + assertEquals(serviceException.code(), code); + assertEquals(serviceException.getMessage(), message); + assertEquals(serviceException.getCause(), cause); + } +} diff --git a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreException.java b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreException.java index 562578a26428..ecbdd57b6bfb 100644 --- a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreException.java +++ b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreException.java @@ -18,6 +18,7 @@ import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableMap; +import com.google.gcloud.BaseServiceException; import com.google.gcloud.RetryHelper; import com.google.gcloud.RetryHelper.RetryHelperException; import com.google.gcloud.spi.DatastoreRpc.DatastoreRpcException; @@ -26,21 +27,21 @@ import java.util.HashMap; import java.util.Map; -public class DatastoreException extends RuntimeException { +public class DatastoreException extends BaseServiceException { - private static final long serialVersionUID = 8170357898917041899L; - private static final ImmutableMap REASON_TO_CODE; - private static final ImmutableMap HTTP_TO_CODE; + private static final long serialVersionUID = -2336749234060754893L; + private static final ImmutableMap REASON_TO_CODE; + private static final ImmutableMap HTTP_TO_CODE; - private final Code code; + private final ErrorInfo errorInfo; /** - * An error code to represent the failure. + * Represent metadata about {@link DatastoreException}s. * * @see Google Cloud * Datastore error codes */ - public enum Code { + public enum ErrorInfo { ABORTED(Reason.ABORTED), DEADLINE_EXCEEDED(Reason.DEADLINE_EXCEEDED), @@ -57,11 +58,11 @@ public enum Code { private final String description; private final int httpStatus; - Code(Reason reason) { + ErrorInfo(Reason reason) { this(reason.retryable(), reason.description(), reason.httpStatus()); } - Code(boolean retryable, String description, int httpStatus) { + ErrorInfo(boolean retryable, String description, int httpStatus) { this.retryable = retryable; this.description = description; this.httpStatus = httpStatus; @@ -89,9 +90,9 @@ DatastoreException translate(DatastoreRpcException exception, String message) { } static { - ImmutableMap.Builder builder = ImmutableMap.builder(); - Map httpCodes = new HashMap<>(); - for (Code code : Code.values()) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + Map httpCodes = new HashMap<>(); + for (ErrorInfo code : ErrorInfo.values()) { builder.put(code.name(), code); httpCodes.put(code.httpStatus(), code); } @@ -99,20 +100,21 @@ DatastoreException translate(DatastoreRpcException exception, String message) { HTTP_TO_CODE = ImmutableMap.copyOf(httpCodes); } - public DatastoreException(Code code, String message, Exception cause) { - super(MoreObjects.firstNonNull(message, code.description), cause); - this.code = code; + public DatastoreException(ErrorInfo errorInfo, String message, Exception cause) { + super(errorInfo.httpStatus(), MoreObjects.firstNonNull(message, errorInfo.description), + errorInfo.retryable(), cause); + this.errorInfo = errorInfo; } - public DatastoreException(Code code, String message) { - this(code, message, null); + public DatastoreException(ErrorInfo errorInfo, String message) { + this(errorInfo, message, null); } /** * Returns the code associated with this exception. */ - public Code code() { - return code; + public ErrorInfo errorInfo() { + return errorInfo; } static DatastoreException translateAndThrow(RetryHelperException ex) { @@ -122,7 +124,7 @@ static DatastoreException translateAndThrow(RetryHelperException ex) { if (ex instanceof RetryHelper.RetryInterruptedException) { RetryHelper.RetryInterruptedException.propagate(); } - throw new DatastoreException(Code.UNKNOWN, ex.getMessage(), ex); + throw new DatastoreException(ErrorInfo.UNKNOWN, ex.getMessage(), ex); } /** @@ -133,9 +135,9 @@ static DatastoreException translateAndThrow(RetryHelperException ex) { */ static DatastoreException translateAndThrow(DatastoreRpcException exception) { String message = exception.getMessage(); - Code code = REASON_TO_CODE.get(exception.reason()); + ErrorInfo code = REASON_TO_CODE.get(exception.reason()); if (code == null) { - code = MoreObjects.firstNonNull(HTTP_TO_CODE.get(exception.httpStatus()), Code.UNKNOWN); + code = MoreObjects.firstNonNull(HTTP_TO_CODE.get(exception.httpStatus()), ErrorInfo.UNKNOWN); } throw code.translate(exception, message); } @@ -147,10 +149,10 @@ static DatastoreException translateAndThrow(DatastoreRpcException exception) { * @throws DatastoreException every time */ static DatastoreException throwInvalidRequest(String massage, Object... params) { - throw new DatastoreException(Code.FAILED_PRECONDITION, String.format(massage, params)); + throw new DatastoreException(ErrorInfo.FAILED_PRECONDITION, String.format(massage, params)); } static DatastoreException propagateUserException(Exception ex) { - throw new DatastoreException(Code.UNKNOWN, ex.getMessage(), ex); + throw new DatastoreException(ErrorInfo.UNKNOWN, ex.getMessage(), ex); } } diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreExceptionTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreExceptionTest.java index a64a3531c19d..20c2f742579a 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreExceptionTest.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreExceptionTest.java @@ -19,7 +19,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; -import com.google.gcloud.datastore.DatastoreException.Code; +import com.google.gcloud.datastore.DatastoreException.ErrorInfo; import com.google.gcloud.spi.DatastoreRpc.DatastoreRpcException; import com.google.gcloud.spi.DatastoreRpc.DatastoreRpcException.Reason; @@ -30,14 +30,14 @@ public class DatastoreExceptionTest { @Test public void testCode() throws Exception { for (Reason reason : Reason.values()) { - Code code = Code.valueOf(reason.name()); + ErrorInfo code = ErrorInfo.valueOf(reason.name()); assertEquals(reason.retryable(), code.retryable()); assertEquals(reason.description(), code.description()); assertEquals(reason.httpStatus(), code.httpStatus()); } - DatastoreException exception = new DatastoreException(Code.ABORTED, "bla"); - assertEquals(Code.ABORTED, exception.code()); + DatastoreException exception = new DatastoreException(ErrorInfo.ABORTED, "bla"); + assertEquals(ErrorInfo.ABORTED, exception.errorInfo()); } @Test @@ -47,7 +47,7 @@ public void testTranslateAndThrow() throws Exception { DatastoreException.translateAndThrow(new DatastoreRpcException(reason)); fail("Exception expected"); } catch (DatastoreException ex) { - assertEquals(reason.name(), ex.code().name()); + assertEquals(reason.name(), ex.errorInfo().name()); } } } @@ -58,7 +58,7 @@ public void testThrowInvalidRequest() throws Exception { DatastoreException.throwInvalidRequest("message %s %d", "a", 1); fail("Exception expected"); } catch (DatastoreException ex) { - assertEquals(Code.FAILED_PRECONDITION, ex.code()); + assertEquals(ErrorInfo.FAILED_PRECONDITION, ex.errorInfo()); assertEquals("message a 1", ex.getMessage()); } } diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java index f639ca3fdac0..9b42c99b0da1 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java @@ -197,7 +197,7 @@ public void testTransactionWithRead() { transaction.commit(); fail("Expecting a failure"); } catch (DatastoreException expected) { - assertEquals(DatastoreException.Code.ABORTED, expected.code()); + assertEquals(DatastoreException.ErrorInfo.ABORTED, expected.errorInfo()); } } @@ -225,7 +225,7 @@ public void testTransactionWithQuery() { transaction.commit(); fail("Expecting a failure"); } catch (DatastoreException expected) { - assertEquals(DatastoreException.Code.ABORTED, expected.code()); + assertEquals(DatastoreException.ErrorInfo.ABORTED, expected.errorInfo()); } } diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageException.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageException.java index e354e3a6d427..c1075ae28c8b 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageException.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageException.java @@ -16,8 +16,10 @@ package com.google.gcloud.storage; +import com.google.gcloud.BaseServiceException; import com.google.gcloud.RetryHelper; import com.google.gcloud.RetryHelper.RetryHelperException; +import com.google.gcloud.RetryHelper.RetryInterruptedException; /** * Storage service exception. @@ -25,29 +27,13 @@ * @see Google Cloud * Storage error codes */ -public class StorageException extends RuntimeException { +public class StorageException extends BaseServiceException { - private static final long serialVersionUID = -3748432005065428084L; + private static final long serialVersionUID = 8088235105953640145L; private static final int UNKNOWN_CODE = -1; - private final int code; - private final boolean retryable; - public StorageException(int code, String message, boolean retryable) { - super(message); - this.code = code; - this.retryable = retryable; - } - - /** - * Returns the code associated with this exception. - */ - public int code() { - return code; - } - - public boolean retryable() { - return retryable; + super(code, message, retryable); } /** From b57a13d6d0e44a7bb5374bf9950551d5e4d5a23b Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Wed, 4 Nov 2015 19:06:58 -0800 Subject: [PATCH 13/48] Rename enum, fix docs, and make accessors package private --- .../google/gcloud/BaseServiceException.java | 5 +- .../gcloud/datastore/DatastoreException.java | 75 +++++++++---------- .../datastore/DatastoreExceptionTest.java | 20 ++--- .../gcloud/datastore/DatastoreTest.java | 4 +- 4 files changed, 52 insertions(+), 52 deletions(-) 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 45c047d4710a..cd0933426756 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 @@ -17,7 +17,7 @@ package com.google.gcloud; /** - * Base service exception. + * Base class for all service exceptions. */ public class BaseServiceException extends RuntimeException { @@ -45,6 +45,9 @@ public int code() { return code; } + /** + * Returns {@code true} when it is safe to retry the operation that caused this exception. + */ public boolean retryable() { return retryable; } diff --git a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreException.java b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreException.java index ecbdd57b6bfb..dded1d11875e 100644 --- a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreException.java +++ b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreException.java @@ -30,18 +30,18 @@ public class DatastoreException extends BaseServiceException { private static final long serialVersionUID = -2336749234060754893L; - private static final ImmutableMap REASON_TO_CODE; - private static final ImmutableMap HTTP_TO_CODE; + private static final ImmutableMap REASON_TO_ERROR; + private static final ImmutableMap HTTP_TO_ERROR; - private final ErrorInfo errorInfo; + private final DatastoreError error; /** - * Represent metadata about {@link DatastoreException}s. + * Represents Datastore errors. * * @see Google Cloud * Datastore error codes */ - public enum ErrorInfo { + public enum DatastoreError { ABORTED(Reason.ABORTED), DEADLINE_EXCEEDED(Reason.DEADLINE_EXCEEDED), @@ -58,29 +58,25 @@ public enum ErrorInfo { private final String description; private final int httpStatus; - ErrorInfo(Reason reason) { + DatastoreError(Reason reason) { this(reason.retryable(), reason.description(), reason.httpStatus()); } - ErrorInfo(boolean retryable, String description, int httpStatus) { + DatastoreError(boolean retryable, String description, int httpStatus) { this.retryable = retryable; this.description = description; this.httpStatus = httpStatus; } - public String description() { + String description() { return description; } - public int httpStatus() { + int httpStatus() { return httpStatus; } - /** - * Returns {@code true} if this exception is transient and the same request could be retried. - * For any retry it is highly recommended to apply an exponential backoff. - */ - public boolean retryable() { + boolean retryable() { return retryable; } @@ -90,31 +86,31 @@ DatastoreException translate(DatastoreRpcException exception, String message) { } static { - ImmutableMap.Builder builder = ImmutableMap.builder(); - Map httpCodes = new HashMap<>(); - for (ErrorInfo code : ErrorInfo.values()) { - builder.put(code.name(), code); - httpCodes.put(code.httpStatus(), code); + ImmutableMap.Builder builder = ImmutableMap.builder(); + Map httpCodes = new HashMap<>(); + for (DatastoreError error : DatastoreError.values()) { + builder.put(error.name(), error); + httpCodes.put(error.httpStatus(), error); } - REASON_TO_CODE = builder.build(); - HTTP_TO_CODE = ImmutableMap.copyOf(httpCodes); + REASON_TO_ERROR = builder.build(); + HTTP_TO_ERROR = ImmutableMap.copyOf(httpCodes); } - public DatastoreException(ErrorInfo errorInfo, String message, Exception cause) { - super(errorInfo.httpStatus(), MoreObjects.firstNonNull(message, errorInfo.description), - errorInfo.retryable(), cause); - this.errorInfo = errorInfo; + public DatastoreException(DatastoreError error, String message, Exception cause) { + super(error.httpStatus(), MoreObjects.firstNonNull(message, error.description), + error.retryable(), cause); + this.error = error; } - public DatastoreException(ErrorInfo errorInfo, String message) { - this(errorInfo, message, null); + public DatastoreException(DatastoreError error, String message) { + this(error, message, null); } /** - * Returns the code associated with this exception. + * Returns the DatastoreError associated with this exception. */ - public ErrorInfo errorInfo() { - return errorInfo; + public DatastoreError datastoreError() { + return error; } static DatastoreException translateAndThrow(RetryHelperException ex) { @@ -124,35 +120,36 @@ static DatastoreException translateAndThrow(RetryHelperException ex) { if (ex instanceof RetryHelper.RetryInterruptedException) { RetryHelper.RetryInterruptedException.propagate(); } - throw new DatastoreException(ErrorInfo.UNKNOWN, ex.getMessage(), ex); + throw new DatastoreException(DatastoreError.UNKNOWN, ex.getMessage(), ex); } /** - * Translate DatastoreException to DatastoreException based on their + * Translate DatastoreRpcExceptions to DatastoreExceptions based on their * HTTP error codes. This method will always throw a new DatastoreException. * * @throws DatastoreException every time */ static DatastoreException translateAndThrow(DatastoreRpcException exception) { String message = exception.getMessage(); - ErrorInfo code = REASON_TO_CODE.get(exception.reason()); - if (code == null) { - code = MoreObjects.firstNonNull(HTTP_TO_CODE.get(exception.httpStatus()), ErrorInfo.UNKNOWN); + DatastoreError error = REASON_TO_ERROR.get(exception.reason()); + if (error == null) { + error = MoreObjects.firstNonNull( + HTTP_TO_ERROR.get(exception.httpStatus()), DatastoreError.UNKNOWN); } - throw code.translate(exception, message); + throw error.translate(exception, message); } /** - * Throw a DatastoreException with {@code FAILED_PRECONDITION} code and the {@code message} + * Throw a DatastoreException with {@code FAILED_PRECONDITION} error and the {@code message} * in a nested exception. * * @throws DatastoreException every time */ static DatastoreException throwInvalidRequest(String massage, Object... params) { - throw new DatastoreException(ErrorInfo.FAILED_PRECONDITION, String.format(massage, params)); + throw new DatastoreException(DatastoreError.FAILED_PRECONDITION, String.format(massage, params)); } static DatastoreException propagateUserException(Exception ex) { - throw new DatastoreException(ErrorInfo.UNKNOWN, ex.getMessage(), ex); + throw new DatastoreException(DatastoreError.UNKNOWN, ex.getMessage(), ex); } } diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreExceptionTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreExceptionTest.java index 20c2f742579a..9ad836b15a4e 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreExceptionTest.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreExceptionTest.java @@ -19,7 +19,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; -import com.google.gcloud.datastore.DatastoreException.ErrorInfo; +import com.google.gcloud.datastore.DatastoreException.DatastoreError; import com.google.gcloud.spi.DatastoreRpc.DatastoreRpcException; import com.google.gcloud.spi.DatastoreRpc.DatastoreRpcException.Reason; @@ -28,16 +28,16 @@ public class DatastoreExceptionTest { @Test - public void testCode() throws Exception { + public void testDatastoreError() throws Exception { for (Reason reason : Reason.values()) { - ErrorInfo code = ErrorInfo.valueOf(reason.name()); - assertEquals(reason.retryable(), code.retryable()); - assertEquals(reason.description(), code.description()); - assertEquals(reason.httpStatus(), code.httpStatus()); + DatastoreError error = DatastoreError.valueOf(reason.name()); + assertEquals(reason.retryable(), error.retryable()); + assertEquals(reason.description(), error.description()); + assertEquals(reason.httpStatus(), error.httpStatus()); } - DatastoreException exception = new DatastoreException(ErrorInfo.ABORTED, "bla"); - assertEquals(ErrorInfo.ABORTED, exception.errorInfo()); + DatastoreException exception = new DatastoreException(DatastoreError.ABORTED, "bla"); + assertEquals(DatastoreError.ABORTED, exception.datastoreError()); } @Test @@ -47,7 +47,7 @@ public void testTranslateAndThrow() throws Exception { DatastoreException.translateAndThrow(new DatastoreRpcException(reason)); fail("Exception expected"); } catch (DatastoreException ex) { - assertEquals(reason.name(), ex.errorInfo().name()); + assertEquals(reason.name(), ex.datastoreError().name()); } } } @@ -58,7 +58,7 @@ public void testThrowInvalidRequest() throws Exception { DatastoreException.throwInvalidRequest("message %s %d", "a", 1); fail("Exception expected"); } catch (DatastoreException ex) { - assertEquals(ErrorInfo.FAILED_PRECONDITION, ex.errorInfo()); + assertEquals(DatastoreError.FAILED_PRECONDITION, ex.datastoreError()); assertEquals("message a 1", ex.getMessage()); } } diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java index 9b42c99b0da1..6afd40927264 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java @@ -197,7 +197,7 @@ public void testTransactionWithRead() { transaction.commit(); fail("Expecting a failure"); } catch (DatastoreException expected) { - assertEquals(DatastoreException.ErrorInfo.ABORTED, expected.errorInfo()); + assertEquals(DatastoreException.DatastoreError.ABORTED, expected.datastoreError()); } } @@ -225,7 +225,7 @@ public void testTransactionWithQuery() { transaction.commit(); fail("Expecting a failure"); } catch (DatastoreException expected) { - assertEquals(DatastoreException.ErrorInfo.ABORTED, expected.errorInfo()); + assertEquals(DatastoreException.DatastoreError.ABORTED, expected.datastoreError()); } } From 73d379ba5afd65fa0a112093f48eace1e5acb931 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Thu, 5 Nov 2015 16:56:16 +0100 Subject: [PATCH 14/48] Add sbt/gradle dependencies to READMEs, change update_docs_version.sh --- README.md | 10 +++++++++- gcloud-java-core/README.md | 10 +++++++++- gcloud-java-datastore/README.md | 10 +++++++++- gcloud-java-examples/README.md | 10 +++++++++- gcloud-java-storage/README.md | 10 +++++++++- gcloud-java/README.md | 10 +++++++++- utilities/update_docs_version.sh | 2 ++ 7 files changed, 56 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1b9867fd198f..85a3ef7993f8 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ This client supports the following Google Cloud Platform services: Quickstart ---------- -Add this to your pom.xml file +If you are using Maven, add this to your pom.xml file ```xml com.google.gcloud @@ -28,6 +28,14 @@ Add this to your pom.xml file 0.0.10 ``` +If you are using Gradle, add this to your dependencies +```Groovy +compile 'com.google.gcloud:gcloud-java:jar:0.0.10' +``` +If you are using SBT, add this to your dependencies +```Scala +libraryDependencies += "com.google.gcloud" % "gcloud-java" % "0.0.10" +``` Example Applications -------------------- diff --git a/gcloud-java-core/README.md b/gcloud-java-core/README.md index 2a3be300f4ac..032127540d19 100644 --- a/gcloud-java-core/README.md +++ b/gcloud-java-core/README.md @@ -12,7 +12,7 @@ This module provides common functionality required by service-specific modules o Quickstart ---------- -Add this to your pom.xml file +If you are using Maven, add this to your pom.xml file ```xml com.google.gcloud @@ -20,6 +20,14 @@ Add this to your pom.xml file 0.0.10 ``` +If you are using Gradle, add this to your dependencies +```Groovy +compile 'com.google.gcloud:gcloud-java-core:jar:0.0.10' +``` +If you are using SBT, add this to your dependencies +```Scala +libraryDependencies += "com.google.gcloud" % "gcloud-java-core" % "0.0.10" +``` Java Versions ------------- diff --git a/gcloud-java-datastore/README.md b/gcloud-java-datastore/README.md index bbcdd9d8857c..8915f2d37a55 100644 --- a/gcloud-java-datastore/README.md +++ b/gcloud-java-datastore/README.md @@ -15,7 +15,7 @@ Java idiomatic client for [Google Cloud Datastore] (https://cloud.google.com/dat Quickstart ---------- -Add this to your pom.xml file +If you are using Maven, add this to your pom.xml file ```xml com.google.gcloud @@ -23,6 +23,14 @@ Add this to your pom.xml file 0.0.10 ``` +If you are using Gradle, add this to your dependencies +```Groovy +compile 'com.google.gcloud:gcloud-java-datastore:jar:0.0.10' +``` +If you are using SBT, add this to your dependencies +```Scala +libraryDependencies += "com.google.gcloud" % "gcloud-java-datastore" % "0.0.10" +``` Example Application -------------------- diff --git a/gcloud-java-examples/README.md b/gcloud-java-examples/README.md index 366acd5de929..9afe16a2b1a5 100644 --- a/gcloud-java-examples/README.md +++ b/gcloud-java-examples/README.md @@ -12,7 +12,7 @@ Examples for gcloud-java (Java idiomatic client for [Google Cloud Platform][clou Quickstart ---------- -Add this to your pom.xml file +If you are using Maven, add this to your pom.xml file ```xml com.google.gcloud @@ -20,6 +20,14 @@ Add this to your pom.xml file 0.0.10 ``` +If you are using Gradle, add this to your dependencies +```Groovy +compile 'com.google.gcloud:gcloud-java-examples:jar:0.0.10' +``` +If you are using SBT, add this to your dependencies +```Scala +libraryDependencies += "com.google.gcloud" % "gcloud-java-examples" % "0.0.10" +``` To run examples from your command line: diff --git a/gcloud-java-storage/README.md b/gcloud-java-storage/README.md index 717fd1f1f3e4..8722da76cec4 100644 --- a/gcloud-java-storage/README.md +++ b/gcloud-java-storage/README.md @@ -15,7 +15,7 @@ Java idiomatic client for [Google Cloud Storage] (https://cloud.google.com/stora Quickstart ---------- -Add this to your pom.xml file +If you are using Maven, add this to your pom.xml file ```xml com.google.gcloud @@ -23,6 +23,14 @@ Add this to your pom.xml file 0.0.10 ``` +If you are using Gradle, add this to your dependencies +```Groovy +compile 'com.google.gcloud:gcloud-java-storage:jar:0.0.10' +``` +If you are using SBT, add this to your dependencies +```Scala +libraryDependencies += "com.google.gcloud" % "gcloud-java-storage" % "0.0.10" +``` Example Application ------------------- diff --git a/gcloud-java/README.md b/gcloud-java/README.md index 7e2eee84a8c4..baa1e5c53b1c 100644 --- a/gcloud-java/README.md +++ b/gcloud-java/README.md @@ -20,7 +20,7 @@ This client supports the following Google Cloud Platform services: Quickstart ---------- -Add this to your pom.xml file +If you are using Maven, add this to your pom.xml file ```xml com.google.gcloud @@ -28,6 +28,14 @@ Add this to your pom.xml file 0.0.10 ``` +If you are using Gradle, add this to your dependencies +```Groovy +compile 'com.google.gcloud:gcloud-java:jar:0.0.10' +``` +If you are using SBT, add this to your dependencies +```Scala +libraryDependencies += "com.google.gcloud" % "gcloud-java" % "0.0.10" +``` Java Versions ------------- diff --git a/utilities/update_docs_version.sh b/utilities/update_docs_version.sh index d7e7bdbfb830..4b1641a0bd81 100755 --- a/utilities/update_docs_version.sh +++ b/utilities/update_docs_version.sh @@ -14,6 +14,8 @@ if [ "${RELEASED_VERSION##*-}" != "SNAPSHOT" ]; then for item in ${module_folders[*]} do sed -ri "s/[0-9]+\.[0-9]+\.[0-9]+<\/version>/${RELEASED_VERSION}<\/version>/g" ${item}/README.md + sed -ri "s/:[0-9]+\.[0-9]+\.[0-9]+'/:${RELEASED_VERSION}'/g" ${item}/README.md + sed -ri "s/\"[0-9]+\.[0-9]+\.[0-9]+\"/\"${RELEASED_VERSION}\"/g" ${item}/README.md done git add README.md */README.md From 2203b9188f89a1a410b86888d8c5f7369fb22465 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Wed, 4 Nov 2015 18:31:22 -0800 Subject: [PATCH 15/48] Run coveralls for PRs as well --- utilities/after_success.sh | 56 ++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/utilities/after_success.sh b/utilities/after_success.sh index 26405bcd9db3..05ab5fb373d6 100755 --- a/utilities/after_success.sh +++ b/utilities/after_success.sh @@ -7,35 +7,37 @@ source ./utilities/integration_test_env.sh echo "Travis branch: " ${TRAVIS_BRANCH} echo "Travis pull request: " ${TRAVIS_PULL_REQUEST} echo "Travis JDK version: " ${TRAVIS_JDK_VERSION} -if [ "${TRAVIS_JDK_VERSION}" == "oraclejdk7" -a "${TRAVIS_BRANCH}" == "master" -a "${TRAVIS_PULL_REQUEST}" == "false" ]; then - mvn cobertura:cobertura coveralls:report - SITE_VERSION=$(mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -Ev '(^\[|\w+:)') - if [ "${SITE_VERSION##*-}" != "SNAPSHOT" ]; then - # Deploy site if not a SNAPSHOT - git config --global user.name "travis-ci" - git config --global user.email "travis@travis-ci.org" - git clone --branch gh-pages --single-branch https://github.com/GoogleCloudPlatform/gcloud-java/ tmp_gh-pages - mkdir -p tmp_gh-pages/$SITE_VERSION - mvn site -DskipTests=true - mvn site:stage -DtopSiteURL=http://googlecloudplatform.github.io/gcloud-java/site/${SITE_VERSION}/ - cd tmp_gh-pages - cp -r ../target/staging/$SITE_VERSION/* $SITE_VERSION/ - sed -i "s/{{SITE_VERSION}}/$SITE_VERSION/g" ${SITE_VERSION}/index.html # Update "Quickstart with Maven" to reflect version change - git add $SITE_VERSION - echo "" > index.html - git add index.html - echo "" > apidocs/index.html - git add apidocs/index.html - git commit -m "Added a new site for version $SITE_VERSION and updated the root directory's redirect." - git config --global push.default simple - git push --quiet "https://${CI_DEPLOY_USERNAME}:${CI_DEPLOY_PASSWORD}@github.com/GoogleCloudPlatform/gcloud-java.git" > /dev/null 2>&1 +if [ "${TRAVIS_JDK_VERSION}" == "oraclejdk7" -a "${TRAVIS_BRANCH}" == "master" ]; then + mvn clean cobertura:cobertura coveralls:report + if [ "${TRAVIS_PULL_REQUEST}" == "false" ]; then + SITE_VERSION=$(mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -Ev '(^\[|\w+:)') + if [ "${SITE_VERSION##*-}" != "SNAPSHOT" ]; then + # Deploy site if not a SNAPSHOT + git config --global user.name "travis-ci" + git config --global user.email "travis@travis-ci.org" + git clone --branch gh-pages --single-branch https://github.com/GoogleCloudPlatform/gcloud-java/ tmp_gh-pages + mkdir -p tmp_gh-pages/$SITE_VERSION + mvn site -DskipTests=true + mvn site:stage -DtopSiteURL=http://googlecloudplatform.github.io/gcloud-java/site/${SITE_VERSION}/ + cd tmp_gh-pages + cp -r ../target/staging/$SITE_VERSION/* $SITE_VERSION/ + sed -i "s/{{SITE_VERSION}}/$SITE_VERSION/g" ${SITE_VERSION}/index.html # Update "Quickstart with Maven" to reflect version change + git add $SITE_VERSION + echo "" > index.html + git add index.html + echo "" > apidocs/index.html + git add apidocs/index.html + git commit -m "Added a new site for version $SITE_VERSION and updated the root directory's redirect." + git config --global push.default simple + git push --quiet "https://${CI_DEPLOY_USERNAME}:${CI_DEPLOY_PASSWORD}@github.com/GoogleCloudPlatform/gcloud-java.git" > /dev/null 2>&1 - cd .. - utilities/update_docs_version.sh # Update version in READMEs - mvn clean deploy --settings ~/.m2/settings.xml -P sign-deploy - else - mvn clean deploy -DskipTests=true -Dgpg.skip=true --settings ~/.m2/settings.xml + cd .. + utilities/update_docs_version.sh # Update version in READMEs + mvn clean deploy --settings ~/.m2/settings.xml -P sign-deploy + else + mvn clean deploy -DskipTests=true -Dgpg.skip=true --settings ~/.m2/settings.xml + fi fi else echo "Not deploying artifacts. This is only done with non-pull-request commits to master branch with Oracle Java 7 builds." From fa9348edd3316ad230a8c93a2f858f8cb364a6b0 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Thu, 5 Nov 2015 16:19:53 -0800 Subject: [PATCH 16/48] update location where we look for config file when using gcloud SDK to get project ID --- .../java/com/google/gcloud/ServiceOptions.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java b/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java index 1be1f16115ad..898897833287 100644 --- a/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java @@ -30,6 +30,7 @@ import java.io.BufferedReader; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; @@ -387,8 +388,18 @@ protected static String googleCloudProjectId() { } else { configDir = new File(System.getProperty("user.home"), ".config/gcloud"); } - try (BufferedReader reader = - new BufferedReader(new FileReader(new File(configDir, "properties")))) { + FileReader fileReader; + try { + fileReader = new FileReader(new File(configDir, "configurations/config_default")); + } catch (FileNotFoundException newConfigFileNotFoundEx) { + try { + fileReader = new FileReader(new File(configDir, "properties")); + } catch (FileNotFoundException oldConfigFileNotFoundEx) { + // return null if we can't find config file + return null; + } + } + try (BufferedReader reader = new BufferedReader(fileReader)) { String line; String section = null; Pattern projectPattern = Pattern.compile("^project\\s*=\\s*(.*)$"); From f4c3a327ca0030fed4326a004e717bb62e0e969e Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Thu, 5 Nov 2015 19:08:14 -0800 Subject: [PATCH 17/48] Add more detail to README's authentication section --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1b9867fd198f..4b07bc7579d1 100644 --- a/README.md +++ b/README.md @@ -44,9 +44,19 @@ There are multiple ways to authenticate to use Google Cloud services. 1. When using `gcloud-java` libraries from within Compute/App Engine, no additional authentication steps are necessary. 2. When using `gcloud-java` libraries elsewhere, there are two options: - * [Generate a JSON service account key](https://cloud.google.com/storage/docs/authentication?hl=en#service_accounts). Supply a path to the downloaded JSON credentials file when building the options supplied to datastore/storage constructor. + * [Generate a JSON service account key](https://cloud.google.com/storage/docs/authentication?hl=en#service_accounts). After downloading that key, you must do one of the following: + * Define the environment variable GOOGLE_APPLICATION_CREDENTIALS to be the location of the key. For example, `export GOOGLE_APPLICATION_CREDENTIALS=/path/to/my/key.json` + * Supply the downloaded JSON credentials file when building the options supplied to datastore/storage constructor. For example, `StorageOptions.builder().authCredentials(AuthCredentials.createForJson(new FileInputStream("/path/to/my/key.json")).build().service()` returns a `Storage` object that has the necessary permissions. * If running locally for development/testing, you can use use [Google Cloud SDK](https://cloud.google.com/sdk/?hl=en). To use the SDK authentication, [download the SDK](https://cloud.google.com/sdk/?hl=en) if you haven't already. Then login using the SDK (`gcloud auth login` in command line), and set your current project using `gcloud config set project PROJECT_ID`. +`gcloud-java` looks for credentials in the following order, stopping once it finds credentials: + +1. Credentials supplied to the `DatastoreOptions`/`ServiceOptions` builder +2. App Engine credentials +3. Key file pointed to by the GOOGLE_APPLICATION_CREDENTIALS environment variable +4. Google SDK credentials +5. Compute Engine credentials + Google Cloud Datastore ---------------------- From fe57e9865b20a4dee394c8042cd9306a20291149 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Thu, 5 Nov 2015 19:57:55 -0800 Subject: [PATCH 18/48] Add project ID order and clean docs language --- README.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4b07bc7579d1..d6da19e83ed0 100644 --- a/README.md +++ b/README.md @@ -46,17 +46,30 @@ There are multiple ways to authenticate to use Google Cloud services. 2. When using `gcloud-java` libraries elsewhere, there are two options: * [Generate a JSON service account key](https://cloud.google.com/storage/docs/authentication?hl=en#service_accounts). After downloading that key, you must do one of the following: * Define the environment variable GOOGLE_APPLICATION_CREDENTIALS to be the location of the key. For example, `export GOOGLE_APPLICATION_CREDENTIALS=/path/to/my/key.json` - * Supply the downloaded JSON credentials file when building the options supplied to datastore/storage constructor. For example, `StorageOptions.builder().authCredentials(AuthCredentials.createForJson(new FileInputStream("/path/to/my/key.json")).build().service()` returns a `Storage` object that has the necessary permissions. + * Supply the JSON credentials file when building the service options. For example, this Storage object has the necessary permissions to interact with your Google Cloud Storage data: + ```java + Storage storage = StorageOptions.builder() + .authCredentials(AuthCredentials.createForJson(new FileInputStream("/path/to/my/key.json")) + .build() + .service(); + ``` * If running locally for development/testing, you can use use [Google Cloud SDK](https://cloud.google.com/sdk/?hl=en). To use the SDK authentication, [download the SDK](https://cloud.google.com/sdk/?hl=en) if you haven't already. Then login using the SDK (`gcloud auth login` in command line), and set your current project using `gcloud config set project PROJECT_ID`. `gcloud-java` looks for credentials in the following order, stopping once it finds credentials: -1. Credentials supplied to the `DatastoreOptions`/`ServiceOptions` builder +1. Credentials supplied when building the service options 2. App Engine credentials 3. Key file pointed to by the GOOGLE_APPLICATION_CREDENTIALS environment variable -4. Google SDK credentials +4. Google Cloud SDK credentials 5. Compute Engine credentials +Note that this sequence is different than the order in which `gcloud-java` determines the project ID. The project ID is determined in the following order: + +1. Project ID supplied when building the service options +2. Project ID specified by the environment variable `GCLOUD_PROJECT` +3. App Engine project ID +4. Google Cloud SDK project ID + Google Cloud Datastore ---------------------- From 7a723996f7c352fd93ceae91f41e474de256873d Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Fri, 6 Nov 2015 11:31:14 +0100 Subject: [PATCH 19/48] Add iterateAll method to Page, update example and snippet --- .../src/main/java/com/google/gcloud/Page.java | 22 ++++++++++-- .../main/java/com/google/gcloud/PageImpl.java | 35 +++++++++++++++++++ .../java/com/google/gcloud/PageImplTest.java | 31 ++++++++++++---- .../gcloud/examples/StorageExample.java | 19 ++++------ .../gcloud/storage/RemoteGcsHelperTest.java | 6 ++++ 5 files changed, 91 insertions(+), 22 deletions(-) diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/Page.java b/gcloud-java-core/src/main/java/com/google/gcloud/Page.java index 1b7754562716..2819b56a17a0 100644 --- a/gcloud-java-core/src/main/java/com/google/gcloud/Page.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/Page.java @@ -16,11 +16,22 @@ package com.google.gcloud; +import java.util.Iterator; + /** * Interface for Google Cloud paginated results. * *

- * A typical {@code Page} usage: + * Use {@code Page} to iterate through all values (also in next pages): + *

 {@code
+ * Page page = ...; // get a Page instance
+ * Iterator iterator = page.iterateAll();
+ * while (iterator.hasNext()) {
+ *   T value = iterator.next();
+ *   // do something with value
+ * }}
+ *

+ * Or handle pagination explicitly: *

 {@code
  * Page page = ...; // get a Page instance
  * while (page != null) {
@@ -28,8 +39,7 @@
  *     // do something with value
  *   }
  *   page = page.nextPage();
- * }
- * }
+ * }} */ public interface Page { @@ -38,6 +48,12 @@ public interface Page { */ Iterable values(); + /** + * Returns an iterator for all values, possibly also in the next pages. Once current page's values + * are traversed the iterator fetches next page, if any. + */ + Iterator iterateAll(); + /** * Returns the cursor for the nextPage or {@code null} if no more results. */ diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/PageImpl.java b/gcloud-java-core/src/main/java/com/google/gcloud/PageImpl.java index 3925079c8d4b..5f70b22ec577 100644 --- a/gcloud-java-core/src/main/java/com/google/gcloud/PageImpl.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/PageImpl.java @@ -16,8 +16,11 @@ package com.google.gcloud; +import com.google.common.collect.AbstractIterator; + import java.io.Serializable; import java.util.Collections; +import java.util.Iterator; import java.util.Objects; /** @@ -35,6 +38,33 @@ public interface NextPageFetcher extends Serializable { Page nextPage(); } + static class PageIterator extends AbstractIterator { + + private Iterator currentPageIterator; + private Page currentPage; + + PageIterator(Page currentPage) { + this.currentPageIterator = currentPage.values().iterator(); + this.currentPage = currentPage; + } + + @Override + protected T computeNext() { + if (currentPageIterator.hasNext()) { + return currentPageIterator.next(); + } + Page nextPage = currentPage.nextPage(); + if (nextPage != null) { + currentPage = nextPage; + currentPageIterator = currentPage.values().iterator(); + if (currentPageIterator.hasNext()) { + return currentPageIterator.next(); + } + } + return endOfData(); + } + } + /** * Creates a {@code PageImpl} object. In order for the object to be serializable the {@code * results} parameter must be serializable. @@ -50,6 +80,11 @@ public Iterable values() { return results == null ? Collections.EMPTY_LIST : results; } + @Override + public Iterator iterateAll() { + return new PageIterator(this); + } + @Override public String nextPageCursor() { return cursor; diff --git a/gcloud-java-core/src/test/java/com/google/gcloud/PageImplTest.java b/gcloud-java-core/src/test/java/com/google/gcloud/PageImplTest.java index 78aa3feaa281..fb289186de8d 100644 --- a/gcloud-java-core/src/test/java/com/google/gcloud/PageImplTest.java +++ b/gcloud-java-core/src/test/java/com/google/gcloud/PageImplTest.java @@ -26,21 +26,38 @@ public class PageImplTest { + private static final ImmutableList VALUES = ImmutableList.of("1", "2"); + private static final ImmutableList NEXT_VALUES = ImmutableList.of("3", "4"); + private static final ImmutableList ALL_VALUES = ImmutableList.builder() + .addAll(VALUES) + .addAll(NEXT_VALUES) + .build(); + @Test - public void testPage() throws Exception { - ImmutableList values = ImmutableList.of("1", "2"); - final PageImpl nextResult = - new PageImpl<>(null, "c", Collections.emptyList()); + public void testPage() { + final PageImpl nextResult = new PageImpl<>(null, "c", NEXT_VALUES); PageImpl.NextPageFetcher fetcher = new PageImpl.NextPageFetcher() { - @Override public PageImpl nextPage() { return nextResult; } }; - PageImpl result = new PageImpl<>(fetcher, "c", values); + PageImpl result = new PageImpl<>(fetcher, "c", VALUES); assertEquals(nextResult, result.nextPage()); assertEquals("c", result.nextPageCursor()); - assertEquals(values, ImmutableList.copyOf(result.values().iterator())); + assertEquals(VALUES, result.values()); + } + + @Test + public void testIterateAll() { + final PageImpl nextResult = new PageImpl<>(null, "c", NEXT_VALUES); + PageImpl.NextPageFetcher fetcher = new PageImpl.NextPageFetcher() { + @Override + public PageImpl nextPage() { + return nextResult; + } + }; + PageImpl result = new PageImpl<>(fetcher, "c", VALUES); + assertEquals(ALL_VALUES, ImmutableList.copyOf(result.iterateAll())); } } diff --git a/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java index 7cf7fe2454fc..b7a36de7589e 100644 --- a/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java +++ b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java @@ -53,6 +53,7 @@ import java.security.cert.CertificateException; import java.util.Arrays; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -214,12 +215,9 @@ String parse(String... args) { public void run(Storage storage, String bucketName) { if (bucketName == null) { // list buckets - Page bucketPage = storage.list(); - while (bucketPage != null) { - for (BucketInfo b : bucketPage.values()) { - System.out.println(b); - } - bucketPage = bucketPage.nextPage(); + Iterator bucketInfoIterator = storage.list().iterateAll(); + while (bucketInfoIterator.hasNext()) { + System.out.println(bucketInfoIterator.next()); } } else { // list a bucket's blobs @@ -228,12 +226,9 @@ public void run(Storage storage, String bucketName) { System.out.println("No such bucket"); return; } - Page blobPage = bucket.list(); - while (blobPage != null) { - for (Blob b : blobPage.values()) { - System.out.println(b.info()); - } - blobPage = blobPage.nextPage(); + Iterator blobIterator = bucket.list().iterateAll(); + while (blobIterator.hasNext()) { + System.out.println(blobIterator.next().info()); } } } diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java index ff6fd68fd1eb..1da45fae466e 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java @@ -33,6 +33,7 @@ import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.Iterator; import java.util.List; import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -90,6 +91,11 @@ public Page nextPage() { public Iterable values() { return BLOB_LIST; } + + @Override + public Iterator iterateAll() { + return BLOB_LIST.iterator(); + } }; private static String keyPath = "/does/not/exist/key." + UUID.randomUUID().toString() + ".json"; From c0842501db691237da0a2f0d4c466dfbe596bad1 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Fri, 6 Nov 2015 10:00:34 -0800 Subject: [PATCH 20/48] Add project ID section --- README.md | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d6da19e83ed0..3f76a2d28211 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,36 @@ Example Applications - [`StorageExample`](https://github.com/GoogleCloudPlatform/gcloud-java/blob/master/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java) - A simple command line interface providing some of Cloud Storage's functionality - Read more about using this application on the [`gcloud-java-examples` docs page](http://googlecloudplatform.github.io/gcloud-java/apidocs/?com/google/gcloud/examples/StorageExample.html). +Specifying a Project +-------------------- + +Most `gcloud-java` libraries require a project ID. There are multiple ways to specify this project ID. + +1. When using `gcloud-java` libraries from within Compute/App Engine, there's no need to specify a project ID. It is automatically inferred from the production environment. +2. When using `gcloud-java` elsewhere, you can do one of the following: + * Supply the project ID when building the service options. For example, to use Datastore from a project with ID "PROJECT_ID", you can write: + + ```java + Datastore datastore = DatastoreOptions.builder().projectId("PROJECT_ID").build().service(); + ``` + * Specify the environment variable `GCLOUD_PROJECT`. For example, type the following into command line: + + ```bash + export GCLOUD_PROJECT=PROJECT_ID + ``` + * Set the project ID using the [Google Cloud SDK](https://cloud.google.com/sdk/?hl=en). To use the SDK, [download the SDK](https://cloud.google.com/sdk/?hl=en) if you haven't already, and set the project ID from the command line. For example: + + ``` + gcloud config set project PROJECT_ID + ``` + +`gcloud-java` determines the project ID from the following sources in the listed order, stopping once it finds a value: + +1. Project ID supplied when building the service options. +2. Project ID specified by the environment variable `GCLOUD_PROJECT`. +3. Project ID used by App Engine. +4. Project ID specified in the Google Cloud SDK. + Authentication -------------- @@ -45,7 +75,10 @@ There are multiple ways to authenticate to use Google Cloud services. 1. When using `gcloud-java` libraries from within Compute/App Engine, no additional authentication steps are necessary. 2. When using `gcloud-java` libraries elsewhere, there are two options: * [Generate a JSON service account key](https://cloud.google.com/storage/docs/authentication?hl=en#service_accounts). After downloading that key, you must do one of the following: - * Define the environment variable GOOGLE_APPLICATION_CREDENTIALS to be the location of the key. For example, `export GOOGLE_APPLICATION_CREDENTIALS=/path/to/my/key.json` + * Define the environment variable GOOGLE_APPLICATION_CREDENTIALS to be the location of the key. For example: + ```bash + export GOOGLE_APPLICATION_CREDENTIALS=/path/to/my/key.json + ``` * Supply the JSON credentials file when building the service options. For example, this Storage object has the necessary permissions to interact with your Google Cloud Storage data: ```java Storage storage = StorageOptions.builder() @@ -53,7 +86,7 @@ There are multiple ways to authenticate to use Google Cloud services. .build() .service(); ``` - * If running locally for development/testing, you can use use [Google Cloud SDK](https://cloud.google.com/sdk/?hl=en). To use the SDK authentication, [download the SDK](https://cloud.google.com/sdk/?hl=en) if you haven't already. Then login using the SDK (`gcloud auth login` in command line), and set your current project using `gcloud config set project PROJECT_ID`. + * If running locally for development/testing, you can use use Google Cloud SDK. Download the SDK if you haven't already, then login using the SDK (`gcloud auth login` in command line). Be sure your current project is set correctly by running `gcloud config set project PROJECT_ID`. `gcloud-java` looks for credentials in the following order, stopping once it finds credentials: @@ -63,13 +96,6 @@ There are multiple ways to authenticate to use Google Cloud services. 4. Google Cloud SDK credentials 5. Compute Engine credentials -Note that this sequence is different than the order in which `gcloud-java` determines the project ID. The project ID is determined in the following order: - -1. Project ID supplied when building the service options -2. Project ID specified by the environment variable `GCLOUD_PROJECT` -3. App Engine project ID -4. Google Cloud SDK project ID - Google Cloud Datastore ---------------------- From 67fdcc08177ec9973465da032f1c504160709f34 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Fri, 6 Nov 2015 11:00:44 -0800 Subject: [PATCH 21/48] fix order of project ID lookup, cleanup --- README.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 3f76a2d28211..0447040de628 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,8 @@ Example Applications - [`StorageExample`](https://github.com/GoogleCloudPlatform/gcloud-java/blob/master/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java) - A simple command line interface providing some of Cloud Storage's functionality - Read more about using this application on the [`gcloud-java-examples` docs page](http://googlecloudplatform.github.io/gcloud-java/apidocs/?com/google/gcloud/examples/StorageExample.html). -Specifying a Project --------------------- +Specifying a Project ID +----------------------- Most `gcloud-java` libraries require a project ID. There are multiple ways to specify this project ID. @@ -49,11 +49,7 @@ Most `gcloud-java` libraries require a project ID. There are multiple ways to s ```java Datastore datastore = DatastoreOptions.builder().projectId("PROJECT_ID").build().service(); ``` - * Specify the environment variable `GCLOUD_PROJECT`. For example, type the following into command line: - - ```bash - export GCLOUD_PROJECT=PROJECT_ID - ``` + * Specify the environment variable `GCLOUD_PROJECT` to be your desired project ID. * Set the project ID using the [Google Cloud SDK](https://cloud.google.com/sdk/?hl=en). To use the SDK, [download the SDK](https://cloud.google.com/sdk/?hl=en) if you haven't already, and set the project ID from the command line. For example: ``` @@ -62,10 +58,11 @@ Most `gcloud-java` libraries require a project ID. There are multiple ways to s `gcloud-java` determines the project ID from the following sources in the listed order, stopping once it finds a value: -1. Project ID supplied when building the service options. -2. Project ID specified by the environment variable `GCLOUD_PROJECT`. -3. Project ID used by App Engine. -4. Project ID specified in the Google Cloud SDK. +1. Project ID supplied when building the service options +2. Project ID specified by the environment variable `GCLOUD_PROJECT` +3. App Engine project ID +4. Compute Engine project ID +5. Google Cloud SDK project ID Authentication -------------- @@ -86,7 +83,7 @@ There are multiple ways to authenticate to use Google Cloud services. .build() .service(); ``` - * If running locally for development/testing, you can use use Google Cloud SDK. Download the SDK if you haven't already, then login using the SDK (`gcloud auth login` in command line). Be sure your current project is set correctly by running `gcloud config set project PROJECT_ID`. + * If running locally for development/testing, you can use use Google Cloud SDK. Download the SDK if you haven't already, then login using the SDK (`gcloud auth login` in command line). Be sure to set your project ID as described above. `gcloud-java` looks for credentials in the following order, stopping once it finds credentials: From 2ce257f54600cf4c5e1342635c6eb9bf287cbc7b Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Fri, 6 Nov 2015 17:41:50 -0800 Subject: [PATCH 22/48] update auth dependency --- gcloud-java-core/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gcloud-java-core/pom.xml b/gcloud-java-core/pom.xml index e849594226db..f12267db49e4 100644 --- a/gcloud-java-core/pom.xml +++ b/gcloud-java-core/pom.xml @@ -20,12 +20,12 @@ com.google.auth google-auth-library-credentials - 0.1.0 + 0.3.0 com.google.auth google-auth-library-oauth2-http - 0.1.0 + 0.3.0 com.google.http-client From 076127d6ce599716519eeffd5595fe8c5313b5df Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Sat, 7 Nov 2015 23:50:45 +0100 Subject: [PATCH 23/48] Add loop for empty pages in PageImpl.iterateAll --- .../main/java/com/google/gcloud/PageImpl.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/PageImpl.java b/gcloud-java-core/src/main/java/com/google/gcloud/PageImpl.java index 5f70b22ec577..5e83b53b33a9 100644 --- a/gcloud-java-core/src/main/java/com/google/gcloud/PageImpl.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/PageImpl.java @@ -50,18 +50,14 @@ static class PageIterator extends AbstractIterator { @Override protected T computeNext() { - if (currentPageIterator.hasNext()) { - return currentPageIterator.next(); - } - Page nextPage = currentPage.nextPage(); - if (nextPage != null) { - currentPage = nextPage; - currentPageIterator = currentPage.values().iterator(); - if (currentPageIterator.hasNext()) { - return currentPageIterator.next(); + while (!currentPageIterator.hasNext()) { + currentPage = currentPage.nextPage(); + if (currentPage == null) { + return endOfData(); } + currentPageIterator = currentPage.values().iterator(); } - return endOfData(); + return currentPageIterator.next(); } } From b2e11319cd3263b9489d47327462586660a49ea3 Mon Sep 17 00:00:00 2001 From: aozarov Date: Tue, 10 Nov 2015 09:09:24 -0800 Subject: [PATCH 24/48] scope appliation default credentials --- .../src/main/java/com/google/gcloud/AuthCredentials.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/AuthCredentials.java b/gcloud-java-core/src/main/java/com/google/gcloud/AuthCredentials.java index 73c66279ea53..800fcf340689 100644 --- a/gcloud-java-core/src/main/java/com/google/gcloud/AuthCredentials.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/AuthCredentials.java @@ -252,7 +252,7 @@ public boolean equals(Object obj) { @Override protected HttpRequestInitializer httpRequestInitializer(HttpTransport transport, Set scopes) { - return new HttpCredentialsAdapter(googleCredentials); + return new HttpCredentialsAdapter(googleCredentials.createScoped(scopes)); } @Override From d3db640dcf383bced4618f0d3e52f974d4e09690 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Tue, 10 Nov 2015 09:45:33 -0800 Subject: [PATCH 25/48] Revert 2de9135149e57cec18b070028452db1efef03125 --- gcloud-java-core/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gcloud-java-core/pom.xml b/gcloud-java-core/pom.xml index f12267db49e4..e849594226db 100644 --- a/gcloud-java-core/pom.xml +++ b/gcloud-java-core/pom.xml @@ -20,12 +20,12 @@ com.google.auth google-auth-library-credentials - 0.3.0 + 0.1.0 com.google.auth google-auth-library-oauth2-http - 0.3.0 + 0.1.0 com.google.http-client From ad12f4143bbcb5d6557055452717c7380cf54959 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Tue, 10 Nov 2015 12:59:34 -0800 Subject: [PATCH 26/48] Allow services to avoid setting project ID --- .../java/com/google/gcloud/ServiceOptions.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java b/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java index 898897833287..d91b3c35c8dd 100644 --- a/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java @@ -306,7 +306,10 @@ public B readTimeout(int readTimeout) { protected ServiceOptions(Class> serviceFactoryClass, Class> rpcFactoryClass, Builder builder) { - projectId = checkNotNull(builder.projectId != null ? builder.projectId : defaultProject()); + projectId = builder.projectId != null ? builder.projectId : defaultProject(); + if (projectIdRequired()) { + checkNotNull(projectId); + } host = firstNonNull(builder.host, defaultHost()); httpTransportFactory = firstNonNull(builder.httpTransportFactory, getFromServiceLoader(HttpTransportFactory.class, DefaultHttpTransportFactory.INSTANCE)); @@ -325,6 +328,16 @@ protected ServiceOptions(Class> ser clock = firstNonNull(builder.clock, Clock.defaultClock()); } + /** + * Returns whether a service requires a project ID. This method may be overridden in + * service-specific Options objects. + * + * @return true if a project ID is required to use the service, false if not. + */ + public boolean projectIdRequired() { + return true; + } + private static AuthCredentials defaultAuthCredentials() { // Consider App Engine. This will not be needed once issue #21 is fixed. if (appEngineAppId() != null) { @@ -462,6 +475,8 @@ public ServiceRpcT rpc() { /** * Returns the project id. + * + * Return value can be null (for services that don't require a project id). */ public String projectId() { return projectId; From 93c834e954e7ce595d86b8fd45a9f2851dfcad4a Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Tue, 10 Nov 2015 13:18:01 -0800 Subject: [PATCH 27/48] Update version to 0.0.11 in preparation for 0.0.11 release --- gcloud-java-core/pom.xml | 2 +- gcloud-java-datastore/pom.xml | 2 +- gcloud-java-examples/pom.xml | 2 +- gcloud-java-storage/pom.xml | 2 +- gcloud-java/pom.xml | 2 +- pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gcloud-java-core/pom.xml b/gcloud-java-core/pom.xml index e849594226db..0dd04b1e837d 100644 --- a/gcloud-java-core/pom.xml +++ b/gcloud-java-core/pom.xml @@ -11,7 +11,7 @@ com.google.gcloud gcloud-java-pom - 0.0.11-SNAPSHOT + 0.0.11 gcloud-java-core diff --git a/gcloud-java-datastore/pom.xml b/gcloud-java-datastore/pom.xml index c7c57d91ae1d..b576ce47fdc8 100644 --- a/gcloud-java-datastore/pom.xml +++ b/gcloud-java-datastore/pom.xml @@ -11,7 +11,7 @@ com.google.gcloud gcloud-java-pom - 0.0.11-SNAPSHOT + 0.0.11 gcloud-java-datastore diff --git a/gcloud-java-examples/pom.xml b/gcloud-java-examples/pom.xml index 55548e756be3..b1d3a3f27c2b 100644 --- a/gcloud-java-examples/pom.xml +++ b/gcloud-java-examples/pom.xml @@ -11,7 +11,7 @@ com.google.gcloud gcloud-java-pom - 0.0.11-SNAPSHOT + 0.0.11 gcloud-java-examples diff --git a/gcloud-java-storage/pom.xml b/gcloud-java-storage/pom.xml index 82b67277f4fe..910aab0e35f7 100644 --- a/gcloud-java-storage/pom.xml +++ b/gcloud-java-storage/pom.xml @@ -11,7 +11,7 @@ com.google.gcloud gcloud-java-pom - 0.0.11-SNAPSHOT + 0.0.11 gcloud-java-storage diff --git a/gcloud-java/pom.xml b/gcloud-java/pom.xml index 6ad0fce8f1b1..1ccb13fcb214 100644 --- a/gcloud-java/pom.xml +++ b/gcloud-java/pom.xml @@ -11,7 +11,7 @@ com.google.gcloud gcloud-java-pom - 0.0.11-SNAPSHOT + 0.0.11 diff --git a/pom.xml b/pom.xml index e35a620247d1..df842cdb9bbc 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.gcloud gcloud-java-pom pom - 0.0.11-SNAPSHOT + 0.0.11 GCloud Java https://github.com/GoogleCloudPlatform/gcloud-java From ffbfba48a6426ff63c08ff2117e58681f251fbf2 Mon Sep 17 00:00:00 2001 From: travis-ci Date: Tue, 10 Nov 2015 22:15:04 +0000 Subject: [PATCH 28/48] Updating version in README files. --- README.md | 6 +++--- gcloud-java-core/README.md | 6 +++--- gcloud-java-datastore/README.md | 6 +++--- gcloud-java-examples/README.md | 6 +++--- gcloud-java-storage/README.md | 6 +++--- gcloud-java/README.md | 6 +++--- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 9ba994d572c1..0fd576a6a127 100644 --- a/README.md +++ b/README.md @@ -25,16 +25,16 @@ If you are using Maven, add this to your pom.xml file com.google.gcloud gcloud-java - 0.0.10 + 0.0.11 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.gcloud:gcloud-java:jar:0.0.10' +compile 'com.google.gcloud:gcloud-java:jar:0.0.11' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.gcloud" % "gcloud-java" % "0.0.10" +libraryDependencies += "com.google.gcloud" % "gcloud-java" % "0.0.11" ``` Example Applications diff --git a/gcloud-java-core/README.md b/gcloud-java-core/README.md index 032127540d19..f84fb33993e7 100644 --- a/gcloud-java-core/README.md +++ b/gcloud-java-core/README.md @@ -17,16 +17,16 @@ If you are using Maven, add this to your pom.xml file com.google.gcloud gcloud-java-core - 0.0.10 + 0.0.11 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.gcloud:gcloud-java-core:jar:0.0.10' +compile 'com.google.gcloud:gcloud-java-core:jar:0.0.11' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.gcloud" % "gcloud-java-core" % "0.0.10" +libraryDependencies += "com.google.gcloud" % "gcloud-java-core" % "0.0.11" ``` Java Versions diff --git a/gcloud-java-datastore/README.md b/gcloud-java-datastore/README.md index 8915f2d37a55..67483fae2b6e 100644 --- a/gcloud-java-datastore/README.md +++ b/gcloud-java-datastore/README.md @@ -20,16 +20,16 @@ If you are using Maven, add this to your pom.xml file com.google.gcloud gcloud-java-datastore - 0.0.10 + 0.0.11 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.gcloud:gcloud-java-datastore:jar:0.0.10' +compile 'com.google.gcloud:gcloud-java-datastore:jar:0.0.11' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.gcloud" % "gcloud-java-datastore" % "0.0.10" +libraryDependencies += "com.google.gcloud" % "gcloud-java-datastore" % "0.0.11" ``` Example Application diff --git a/gcloud-java-examples/README.md b/gcloud-java-examples/README.md index 9afe16a2b1a5..bc738de41b51 100644 --- a/gcloud-java-examples/README.md +++ b/gcloud-java-examples/README.md @@ -17,16 +17,16 @@ If you are using Maven, add this to your pom.xml file com.google.gcloud gcloud-java-examples - 0.0.10 + 0.0.11 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.gcloud:gcloud-java-examples:jar:0.0.10' +compile 'com.google.gcloud:gcloud-java-examples:jar:0.0.11' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.gcloud" % "gcloud-java-examples" % "0.0.10" +libraryDependencies += "com.google.gcloud" % "gcloud-java-examples" % "0.0.11" ``` To run examples from your command line: diff --git a/gcloud-java-storage/README.md b/gcloud-java-storage/README.md index 8722da76cec4..f2b99388ff0f 100644 --- a/gcloud-java-storage/README.md +++ b/gcloud-java-storage/README.md @@ -20,16 +20,16 @@ If you are using Maven, add this to your pom.xml file com.google.gcloud gcloud-java-storage - 0.0.10 + 0.0.11 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.gcloud:gcloud-java-storage:jar:0.0.10' +compile 'com.google.gcloud:gcloud-java-storage:jar:0.0.11' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.gcloud" % "gcloud-java-storage" % "0.0.10" +libraryDependencies += "com.google.gcloud" % "gcloud-java-storage" % "0.0.11" ``` Example Application diff --git a/gcloud-java/README.md b/gcloud-java/README.md index baa1e5c53b1c..eaaed21af5fe 100644 --- a/gcloud-java/README.md +++ b/gcloud-java/README.md @@ -25,16 +25,16 @@ If you are using Maven, add this to your pom.xml file com.google.gcloud gcloud-java - 0.0.10 + 0.0.11 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.gcloud:gcloud-java:jar:0.0.10' +compile 'com.google.gcloud:gcloud-java:jar:0.0.11' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.gcloud" % "gcloud-java" % "0.0.10" +libraryDependencies += "com.google.gcloud" % "gcloud-java" % "0.0.11" ``` Java Versions From fc72ea0b0e246921c491f8460cd9ce7dab94e82c Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Tue, 10 Nov 2015 14:35:11 -0800 Subject: [PATCH 29/48] Update version to 0.0.12-SNAPSHOT --- gcloud-java-core/pom.xml | 2 +- gcloud-java-datastore/pom.xml | 2 +- gcloud-java-examples/pom.xml | 2 +- gcloud-java-storage/pom.xml | 2 +- gcloud-java/pom.xml | 2 +- pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gcloud-java-core/pom.xml b/gcloud-java-core/pom.xml index 0dd04b1e837d..e13933bd2beb 100644 --- a/gcloud-java-core/pom.xml +++ b/gcloud-java-core/pom.xml @@ -11,7 +11,7 @@ com.google.gcloud gcloud-java-pom - 0.0.11 + 0.0.12-SNAPSHOT gcloud-java-core diff --git a/gcloud-java-datastore/pom.xml b/gcloud-java-datastore/pom.xml index b576ce47fdc8..b58e9e0ffc74 100644 --- a/gcloud-java-datastore/pom.xml +++ b/gcloud-java-datastore/pom.xml @@ -11,7 +11,7 @@ com.google.gcloud gcloud-java-pom - 0.0.11 + 0.0.12-SNAPSHOT gcloud-java-datastore diff --git a/gcloud-java-examples/pom.xml b/gcloud-java-examples/pom.xml index b1d3a3f27c2b..c461846acab2 100644 --- a/gcloud-java-examples/pom.xml +++ b/gcloud-java-examples/pom.xml @@ -11,7 +11,7 @@ com.google.gcloud gcloud-java-pom - 0.0.11 + 0.0.12-SNAPSHOT gcloud-java-examples diff --git a/gcloud-java-storage/pom.xml b/gcloud-java-storage/pom.xml index 910aab0e35f7..ef3ddec79816 100644 --- a/gcloud-java-storage/pom.xml +++ b/gcloud-java-storage/pom.xml @@ -11,7 +11,7 @@ com.google.gcloud gcloud-java-pom - 0.0.11 + 0.0.12-SNAPSHOT gcloud-java-storage diff --git a/gcloud-java/pom.xml b/gcloud-java/pom.xml index 1ccb13fcb214..d26c38f517d5 100644 --- a/gcloud-java/pom.xml +++ b/gcloud-java/pom.xml @@ -11,7 +11,7 @@ com.google.gcloud gcloud-java-pom - 0.0.11 + 0.0.12-SNAPSHOT diff --git a/pom.xml b/pom.xml index df842cdb9bbc..78cbfe11d351 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.gcloud gcloud-java-pom pom - 0.0.11 + 0.0.12-SNAPSHOT GCloud Java https://github.com/GoogleCloudPlatform/gcloud-java From 6c408256e1621c7e0f3640fb7a4ffdef139f5241 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Tue, 10 Nov 2015 15:02:44 -0800 Subject: [PATCH 30/48] Make projectIdRequired() method protected. Also supply nice error message if project could not be determined and is required --- .../src/main/java/com/google/gcloud/ServiceOptions.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java b/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java index d91b3c35c8dd..0793470ade83 100644 --- a/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/ServiceOptions.java @@ -17,7 +17,7 @@ package com.google.gcloud; import static com.google.common.base.MoreObjects.firstNonNull; -import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkArgument; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.api.client.extensions.appengine.http.UrlFetchTransport; @@ -308,7 +308,10 @@ protected ServiceOptions(Class> ser Builder builder) { projectId = builder.projectId != null ? builder.projectId : defaultProject(); if (projectIdRequired()) { - checkNotNull(projectId); + checkArgument( + projectId != null, + "A project ID is required for this service but could not be determined from the builder or " + + "the environment. Please set a project ID using the builder."); } host = firstNonNull(builder.host, defaultHost()); httpTransportFactory = firstNonNull(builder.httpTransportFactory, @@ -334,7 +337,7 @@ protected ServiceOptions(Class> ser * * @return true if a project ID is required to use the service, false if not. */ - public boolean projectIdRequired() { + protected boolean projectIdRequired() { return true; } From bfd54bdefbf2e8b79b1e96d71c7adbd05eda2e7a Mon Sep 17 00:00:00 2001 From: aozarov Date: Tue, 10 Nov 2015 16:37:56 -0800 Subject: [PATCH 31/48] replace rewrite with copy in the javadoc --- .../src/main/java/com/google/gcloud/storage/CopyWriter.java | 4 ++-- .../src/main/java/com/google/gcloud/storage/Storage.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/CopyWriter.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/CopyWriter.java index 142f8d4b6de7..5f2632b2acde 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/CopyWriter.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/CopyWriter.java @@ -79,14 +79,14 @@ public long blobSize() { } /** - * Returns {@code true} of blob rewrite finished, {@code false} otherwise. + * Returns {@code true} if blob copy has finished, {@code false} otherwise. */ public boolean isDone() { return rewriteResponse.isDone; } /** - * Returns the number of bytes copied. + * Returns the number of bytes copied. */ public long totalBytesCopied() { return rewriteResponse.totalBytesRewritten; diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java index 52387310de71..115449064c66 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java @@ -804,7 +804,7 @@ private CopyRequest(Builder builder) { } /** - * Returns the blob to rewrite, as a {@link BlobId}. + * Returns the blob to copy, as a {@link BlobId}. */ public BlobId source() { return source; @@ -818,7 +818,7 @@ public List sourceOptions() { } /** - * Returns the rewrite target. + * Returns the {@link BlobInfo} for the target blob. */ public BlobInfo target() { return target; From dde30aaf085b0cf3a6615af0495309b2596e488f Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 11 Nov 2015 15:32:36 +0100 Subject: [PATCH 32/48] Add javadoc to Acl --- .../java/com/google/gcloud/storage/Acl.java | 74 ++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Acl.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Acl.java index 3d9731352400..fd75e10d92fa 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Acl.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Acl.java @@ -23,7 +23,10 @@ import java.util.Objects; /** - * Access Control List on for buckets or blobs. + * Access Control List for buckets or blobs. + * + * @see + * About Access Control Lists */ public final class Acl implements Serializable { @@ -36,6 +39,9 @@ public enum Role { OWNER, READER, WRITER } + /** + * Base class for Access Control List entities. + */ public abstract static class Entity implements Serializable { private static final long serialVersionUID = -2707407252771255840L; @@ -52,10 +58,16 @@ public enum Type { this.value = value; } + /** + * Returns the type of entity. + */ public Type type() { return type; } + /** + * Returns the entity's value. + */ protected String value() { return value; } @@ -112,42 +124,75 @@ static Entity fromPb(String entity) { } } + /** + * Class for ACL Domain entities. + */ public static final class Domain extends Entity { private static final long serialVersionUID = -3033025857280447253L; + /** + * Creates a domain entity. + * + * @param domain the domain associated to this entity + */ public Domain(String domain) { super(Type.DOMAIN, domain); } + /** + * Returns the domain associated to this entity. + */ public String domain() { return value(); } } + /** + * Class for ACL Group entities. + */ public static final class Group extends Entity { private static final long serialVersionUID = -1660987136294408826L; + /** + * Creates a group entity. + * + * @param email the group email + */ public Group(String email) { super(Type.GROUP, email); } + /** + * Returns the group email. + */ public String email() { return value(); } } + /** + * Class for ACL User entities. + */ public static final class User extends Entity { private static final long serialVersionUID = 3076518036392737008L; private static final String ALL_USERS = "allUsers"; private static final String ALL_AUTHENTICATED_USERS = "allAuthenticatedUsers"; + /** + * Creates a user entity. + * + * @param email the user email + */ public User(String email) { super(Type.USER, email); } + /** + * Returns the user email. + */ public String email() { return value(); } @@ -174,6 +219,9 @@ public static User ofAllAuthenticatedUsers() { } } + /** + * Class for ACL Project entities. + */ public static final class Project extends Entity { private static final long serialVersionUID = 7933776866530023027L; @@ -185,16 +233,28 @@ public enum ProjectRole { OWNERS, EDITORS, VIEWERS } + /** + * Creates a project entity. + * + * @param pRole a role in the project, used to select project's teams + * @param projectId id of the project + */ public Project(ProjectRole pRole, String projectId) { super(Type.PROJECT, pRole.name().toLowerCase() + "-" + projectId); this.pRole = pRole; this.projectId = projectId; } + /** + * Returns the role in the project for this entity. + */ public ProjectRole projectRole() { return pRole; } + /** + * Returns the project id for this entity. + */ public String projectId() { return projectId; } @@ -214,15 +274,27 @@ String toPb() { } } + /** + * Creats an ACL object. + * + * @param entity the entity for this ACL object + * @param role the role to associate to the {@code entity} object + */ public Acl(Entity entity, Role role) { this.entity = entity; this.role = role; } + /** + * Returns the entity for this ACL object. + */ public Entity entity() { return entity; } + /** + * Returns the role associated to the entity in this ACL object. + */ public Role role() { return role; } From 93dd0c244fdbc6843ed2fc43912fa55a4c9e6258 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 11 Nov 2015 15:34:49 +0100 Subject: [PATCH 33/48] Add javadoc to Blob --- .../java/com/google/gcloud/storage/Blob.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Blob.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Blob.java index d35fcef026c8..a8e315be0e45 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Blob.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Blob.java @@ -50,6 +50,9 @@ public final class Blob { private final Storage storage; private final BlobInfo info; + /** + * Class for specifying blob source options when {@code Blob} methods are used. + */ public static class BlobSourceOption extends Option { private static final long serialVersionUID = 214616862061934846L; @@ -88,18 +91,34 @@ private Storage.BlobGetOption toGetOption(BlobInfo blobInfo) { } } + /** + * Returns an option for blob's generation match. If this option is used the request will fail + * if generation does not match. + */ public static BlobSourceOption generationMatch() { return new BlobSourceOption(StorageRpc.Option.IF_GENERATION_MATCH); } + /** + * Returns an option for blob's generation mismatch. If this option is used the request will + * fail if generation matches. + */ public static BlobSourceOption generationNotMatch() { return new BlobSourceOption(StorageRpc.Option.IF_GENERATION_NOT_MATCH); } + /** + * Returns an option for blob's metageneration match. If this option is used the request will + * fail if metageneration does not match. + */ public static BlobSourceOption metagenerationMatch() { return new BlobSourceOption(StorageRpc.Option.IF_METAGENERATION_MATCH); } + /** + * Returns an option for blob's metageneration mismatch. If this option is used the request will + * fail if metageneration matches. + */ public static BlobSourceOption metagenerationNotMatch() { return new BlobSourceOption(StorageRpc.Option.IF_METAGENERATION_NOT_MATCH); } From 6de12f20c202386d66588059b6c9ec55ff47a058 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 11 Nov 2015 15:35:36 +0100 Subject: [PATCH 34/48] Add javadoc to BlobId --- .../main/java/com/google/gcloud/storage/BlobId.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobId.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobId.java index eafebe09a4cb..d1209826cc3e 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobId.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobId.java @@ -38,10 +38,16 @@ private BlobId(String bucket, String name) { this.name = name; } + /** + * Returns the name of the bucket containing the blob. + */ public String bucket() { return bucket; } + /** + * Returns the name of the blob. + */ public String name() { return name; } @@ -72,6 +78,12 @@ StorageObject toPb() { return storageObject; } + /** + * Creates a blob identifier. + * + * @param bucket the name of the bucket that contains the blob + * @param name the name of the blob + */ public static BlobId of(String bucket, String name) { return new BlobId(checkNotNull(bucket), checkNotNull(name)); } From e2a4500e57e7dd458223cff5020e990539795828 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 11 Nov 2015 15:37:47 +0100 Subject: [PATCH 35/48] Add javadoc to Bucket --- .../main/java/com/google/gcloud/storage/Bucket.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java index 7c386373995f..21aafd92b5d4 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Bucket.java @@ -122,6 +122,9 @@ public boolean equals(Object obj) { } } + /** + * Class for specifying bucket source options when {@code Bucket} methods are used. + */ public static class BucketSourceOption extends Option { private static final long serialVersionUID = 6928872234155522371L; @@ -152,10 +155,18 @@ private Storage.BucketGetOption toGetOption(BucketInfo bucketInfo) { } } + /** + * Returns an option for bucket's metageneration match. If this option is used the request will + * fail if metageneration does not match. + */ public static BucketSourceOption metagenerationMatch() { return new BucketSourceOption(StorageRpc.Option.IF_METAGENERATION_MATCH); } + /** + * Returns an option for bucket's metageneration mismatch. If this option is used the request + * will fail if metageneration matches. + */ public static BucketSourceOption metagenerationNotMatch() { return new BucketSourceOption(StorageRpc.Option.IF_METAGENERATION_NOT_MATCH); } From 9608e61fe5228de7c4faddb9e9c4a850eda69611 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 11 Nov 2015 15:40:43 +0100 Subject: [PATCH 36/48] Add javadoc to Cors --- .../java/com/google/gcloud/storage/Cors.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Cors.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Cors.java index a94359f17a79..bcbbd1030dbc 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Cors.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Cors.java @@ -33,6 +33,9 @@ /** * Cross-Origin Resource Sharing (CORS) configuration for a bucket. + * + * @see + * Cross-Origin Resource Sharing (CORS) */ public final class Cors implements Serializable { @@ -57,6 +60,9 @@ public Bucket.Cors apply(Cors cors) { private final ImmutableList origins; private final ImmutableList responseHeaders; + /** + * Class for a CORS origin. + */ public static final class Origin implements Serializable { private static final long serialVersionUID = -4447958124895577993L; @@ -69,10 +75,16 @@ private Origin(String value) { this.value = checkNotNull(value); } + /** + * Returns an {@code Origin} object for all possible origins. + */ public static Origin any() { return ANY; } + /** + * Returns an {@code Origin} object for the given scheme, host and port. + */ public static Origin of(String scheme, String host, int port) { try { return of(new URI(scheme, null, host, port, null, null, null).toString()); @@ -81,6 +93,9 @@ public static Origin of(String scheme, String host, int port) { } } + /** + * Creates an {@code Origin} object for the provided value. + */ public static Origin of(String value) { if (ANY_URI.equals(value)) { return any(); @@ -111,6 +126,9 @@ public String value() { } } + /** + * CORS configuration builder. + */ public static final class Builder { private Integer maxAgeSeconds; @@ -120,26 +138,42 @@ public static final class Builder { private Builder() {} + /** + * Sets the max time in seconds in which a client can issue requests before sending a new + * preflight request. + */ public Builder maxAgeSeconds(Integer maxAgeSeconds) { this.maxAgeSeconds = maxAgeSeconds; return this; } + /** + * Sets the HTTP methods supported by this CORS configuration. + */ public Builder methods(Iterable methods) { this.methods = methods != null ? ImmutableList.copyOf(methods) : null; return this; } + /** + * Sets the origins for this CORS configuration. + */ public Builder origins(Iterable origins) { this.origins = origins != null ? ImmutableList.copyOf(origins) : null; return this; } + /** + * Sets the response headers supported by this CORS configuration. + */ public Builder responseHeaders(Iterable headers) { this.responseHeaders = headers != null ? ImmutableList.copyOf(headers) : null; return this; } + /** + * Creates a CORS configuration. + */ public Cors build() { return new Cors(this); } @@ -152,22 +186,38 @@ private Cors(Builder builder) { this.responseHeaders = builder.responseHeaders; } + /** + * Returns the max time in seconds in which a client can issue requests before sending a new + * preflight request. + */ public Integer maxAgeSeconds() { return maxAgeSeconds; } + /** + * Returns the HTTP methods supported by this CORS configuration. + */ public List methods() { return methods; } + /** + * Returns the origins in this CORS configuration. + */ public List origins() { return origins; } + /** + * Returns the response headers supported by this CORS configuration. + */ public List responseHeaders() { return responseHeaders; } + /** + * Returns a builder for this CORS configuration. + */ public Builder toBuilder() { return builder() .maxAgeSeconds(maxAgeSeconds) @@ -193,6 +243,9 @@ public boolean equals(Object obj) { && Objects.equals(responseHeaders, other.responseHeaders); } + /** + * Returns a CORS configuration builder. + */ public static Builder builder() { return new Builder(); } From 67bfcdd00e1c475eb74f222d1ea59ef7b0b3e130 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 11 Nov 2015 14:31:53 +0100 Subject: [PATCH 37/48] Switch from enum to String for location and storageClass in BucketInfo, add javadoc --- .../com/google/gcloud/storage/BucketInfo.java | 330 ++++++++++-------- .../google/gcloud/storage/BucketInfoTest.java | 16 +- 2 files changed, 187 insertions(+), 159 deletions(-) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BucketInfo.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BucketInfo.java index 5d69c54e0d96..3f21f74dcd66 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BucketInfo.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BucketInfo.java @@ -80,9 +80,15 @@ public com.google.api.services.storage.model.Bucket apply(BucketInfo bucketInfo) private final List cors; private final List acl; private final List defaultAcl; - private final Location location; - private final StorageClass storageClass; - + private final String location; + private final String storageClass; + + /** + * Base class for bucket's delete rules. Allows to configure automatic deletion of blobs and blobs + * versions. + * + * @see Object Lifecycle Management + */ public abstract static class DeleteRule implements Serializable { private static final long serialVersionUID = 3137971668395933033L; @@ -153,11 +159,23 @@ static DeleteRule fromPb(Rule rule) { } } + /** + * Delete rule class that sets a Time To Live for blobs in the bucket. + * + * @see Object Lifecycle Management + */ public static class AgeDeleteRule extends DeleteRule { private static final long serialVersionUID = 5697166940712116380L; private final int daysToLive; + /** + * Creates an {@code AgeDeleteRule} object. + * + * @param daysToLive blobs' Time To Live expressed in days. The time when the age condition is + * considered to be satisfied is computed by adding {@code daysToLive} days to the + * midnight following blob's creation time in UTC. + */ public AgeDeleteRule(int daysToLive) { super(Type.AGE); this.daysToLive = daysToLive; @@ -205,11 +223,22 @@ Rule toPb() { } } + /** + * Delete rule class for blobs in the bucket that have been created before a certain date. + * + * @see Object Lifecycle Management + */ public static class CreatedBeforeDeleteRule extends DeleteRule { private static final long serialVersionUID = 881692650279195867L; private final long timeMillis; + /** + * Creates an {@code CreatedBeforeDeleteRule} object. + * + * @param timeMillis a date in UTC. Blobs that have been created before midnight of the provided + * date meet the delete condition + */ public CreatedBeforeDeleteRule(long timeMillis) { super(Type.CREATE_BEFORE); this.timeMillis = timeMillis; @@ -225,11 +254,23 @@ void populateCondition(Rule.Condition condition) { } } + /** + * Delete rule class for versioned blobs. Specifies when to delete a blob's version according to + * the number of available newer versions for that blob. + * + * @see Object Lifecycle Management + */ public static class NumNewerVersionsDeleteRule extends DeleteRule { private static final long serialVersionUID = -1955554976528303894L; private final int numNewerVersions; + /** + * Creates an {@code NumNewerVersionsDeleteRule} object. + * + * @param numNewerVersions the number of newer versions. A blob's version meets the delete + * condition when {@code numNewerVersions} newer versions are available. + */ public NumNewerVersionsDeleteRule(int numNewerVersions) { super(Type.NUM_NEWER_VERSIONS); this.numNewerVersions = numNewerVersions; @@ -245,11 +286,22 @@ void populateCondition(Rule.Condition condition) { } } + /** + * Delete rule class to distinguish between live and archived blobs. + * + * @see Object Lifecycle Management + */ public static class IsLiveDeleteRule extends DeleteRule { private static final long serialVersionUID = -3502994563121313364L; private final boolean isLive; + /** + * Creates an {@code IsLiveDeleteRule} object. + * + * @param isLive if set to {@code true} live blobs meet the delete condition. If set to + * {@code false} delete condition is met by archived objects. + */ public IsLiveDeleteRule(boolean isLive) { super(Type.IS_LIVE); this.isLive = isLive; @@ -265,134 +317,6 @@ void populateCondition(Rule.Condition condition) { } } - public static final class StorageClass implements Serializable { - - private static final long serialVersionUID = 374002156285326563L; - private static final ImmutableMap STRING_TO_OPTION; - private static final StorageClass NULL_VALUE = - new StorageClass(Data.nullOf(String.class)); - - private final String value; - - public enum Option { - DURABLE_REDUCED_AVAILABILITY, STANDARD; - - private final StorageClass storageClass; - - Option() { - storageClass = new StorageClass(name()); - } - } - - private StorageClass(String value) { - this.value = checkNotNull(value); - } - - @Override - public String toString() { - return value(); - } - - public String value() { - return value; - } - - public static StorageClass standard() { - return Option.STANDARD.storageClass; - } - - public static StorageClass durableReducedAvailability() { - return Option.DURABLE_REDUCED_AVAILABILITY.storageClass; - } - - public static StorageClass of(String value) { - Option option = STRING_TO_OPTION.get(value.toUpperCase()); - return option == null ? new StorageClass(value) : option.storageClass; - } - - static { - ImmutableMap.Builder map = ImmutableMap.builder(); - for (Option option : Option.values()) { - map.put(option.name(), option); - } - STRING_TO_OPTION = map.build(); - } - } - - public static final class Location implements Serializable { - - private static final long serialVersionUID = 9073107666838637662L; - private static final ImmutableMap STRING_TO_OPTION; - private static final Location NULL_VALUE = new Location(Data.nullOf(String.class)); - - private final String value; - - public enum Option { - US, EU, ASIA; - - private final Location location; - - Option() { - location = new Location(name()); - } - } - - private Location(String value) { - this.value = checkNotNull(value); - } - - @Override - public int hashCode() { - return Objects.hash(value); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - final Location other = (Location) obj; - return Objects.equals(this.value, other.value); - } - - @Override - public String toString() { - return value(); - } - - public String value() { - return value; - } - - public static Location us() { - return Option.US.location; - } - - public static Location eu() { - return Option.EU.location; - } - - public static Location asia() { - return Option.ASIA.location; - } - - public static Location of(String value) { - Option option = STRING_TO_OPTION.get(value.toUpperCase()); - return option == null ? new Location(value) : option.location; - } - - static { - ImmutableMap.Builder map = ImmutableMap.builder(); - for (Option option : Option.values()) { - map.put(option.name(), option); - } - STRING_TO_OPTION = map.build(); - } - } - public static final class Builder { private String id; @@ -403,8 +327,8 @@ public static final class Builder { private String indexPage; private String notFoundPage; private ImmutableList deleteRules; - private StorageClass storageClass; - private Location location; + private String storageClass; + private String location; private String etag; private Long createTime; private Long metageneration; @@ -414,6 +338,9 @@ public static final class Builder { private Builder() {} + /** + * Sets the bucket's name. + */ public Builder name(String name) { this.name = checkNotNull(name); return this; @@ -434,33 +361,57 @@ Builder selfLink(String selfLink) { return this; } + /** + * Sets whether blob versioning should be enabled or not for the bucket. + */ public Builder versioningEnabled(Boolean enable) { this.versioningEnabled = firstNonNull(enable, Data.nullOf(Boolean.class)); return this; } + /** + * Sets the bucket's website index page. + */ public Builder indexPage(String indexPage) { this.indexPage = indexPage; return this; } + /** + * Sets the bucket's website page to return when a resource is not found. + */ public Builder notFoundPage(String notFoundPage) { this.notFoundPage = notFoundPage; return this; } + /** + * Sets bucket's delete rules. + * + * @see Lifecycle Management + */ public Builder deleteRules(Iterable rules) { this.deleteRules = rules != null ? ImmutableList.copyOf(rules) : null; return this; } - public Builder storageClass(StorageClass storageClass) { - this.storageClass = firstNonNull(storageClass, StorageClass.NULL_VALUE); + /** + * Sets the bucket's storage class. A list of supported values is available + * here. + * + * @see Storage Classes + */ + public Builder storageClass(String storageClass) { + this.storageClass = storageClass; return this; } - public Builder location(Location location) { - this.location = firstNonNull(location, Location.NULL_VALUE); + /** + * Sets the bucket's location. A list of supported values is available + * here. + */ + public Builder location(String location) { + this.location = location; return this; } @@ -479,21 +430,43 @@ Builder metageneration(Long metageneration) { return this; } + /** + * Sets the bucket's Cross-Origin Resource Sharing (CORS) configuration. + * + * @see + * Cross-Origin Resource Sharing (CORS) + */ public Builder cors(Iterable cors) { this.cors = cors != null ? ImmutableList.copyOf(cors) : null; return this; } + /** + * Sets the bucket's access control configuration. + * + * @see + * About Access Control Lists + */ public Builder acl(Iterable acl) { this.acl = acl != null ? ImmutableList.copyOf(acl) : null; return this; } + /** + * Sets the default access control configuration to apply to bucket's blobs when no other + * configuration is specified. + * + * @see + * About Access Control Lists + */ public Builder defaultAcl(Iterable acl) { this.defaultAcl = acl != null ? ImmutableList.copyOf(acl) : null; return this; } + /** + * Creates a {@code BucketInfo} object. + */ public BucketInfo build() { checkNotNull(name); return new BucketInfo(this); @@ -519,70 +492,131 @@ private BucketInfo(Builder builder) { deleteRules = builder.deleteRules; } + /** + * Returns the bucket's id. + */ public String id() { return id; } + /** + * Returns the bucket's name. + */ public String name() { return name; } + /** + * Returns the bucket's owner. + */ public Entity owner() { return owner; } + /** + * Returns the URI of this bucket as a string. + */ public String selfLink() { return selfLink; } + /** + * Returns {@code true} if blob versioning is enabled for this bucket, {@code false} otherwise. + */ public Boolean versioningEnabled() { return Data.isNull(versioningEnabled) ? null : versioningEnabled; } + /** + * Returns bucket's website index page. + */ public String indexPage() { return indexPage; } + /** + * Returns bucket's website not found page, used we a resource could not be found. + */ public String notFoundPage() { return notFoundPage; } + /** + * Returns bucket's delete rules. + */ public List deleteRules() { return deleteRules; } + /** + * Returns bucket resource's entity tag. + */ public String etag() { return etag; } + /** + * Returns the time at which the bucket was created. + */ public Long createTime() { return createTime; } + /** + * Returns the metadata generation of this bucket. + */ public Long metageneration() { return metageneration; } - public Location location() { - return location == null || Data.isNull(location.value) ? null : location; + /** + * Returns the bucket's location. + * + * @see Bucket Locations + */ + public String location() { + return location; } - public StorageClass storageClass() { - return storageClass == null || Data.isNull(storageClass.value) ? null : storageClass; + /** + * Returns the bucket's storage class. + * + * @see Storage Classes + */ + public String storageClass() { + return storageClass; } + /** + * Returns the bucket's Cross-Origin Resource Sharing (CORS) configuration. + */ public List cors() { return cors; } + /** + * Returns the bucket's access control configuration. + * + * @see + * About Access Control Lists + */ public List acl() { return acl; } + /** + * Returns the default access control configuration for this bucket's blobs. + * + * @see + * About Access Control Lists + */ public List defaultAcl() { return defaultAcl; } + /** + * Returns a builder for the current bucket. + */ public Builder toBuilder() { return new Builder() .name(name) @@ -633,10 +667,10 @@ com.google.api.services.storage.model.Bucket toPb() { bucketPb.setMetageneration(metageneration); } if (location != null) { - bucketPb.setLocation(location.value()); + bucketPb.setLocation(location); } if (storageClass != null) { - bucketPb.setStorageClass(storageClass.value()); + bucketPb.setStorageClass(storageClass); } if (cors != null) { bucketPb.setCors(transform(cors, Cors.TO_PB_FUNCTION)); @@ -683,10 +717,16 @@ public Rule apply(DeleteRule deleteRule) { return bucketPb; } + /** + * Creates a {@code BucketInfo} object for the provided bucket name. + */ public static BucketInfo of(String name) { return builder(name).build(); } + /** + * Returns a {@code BucketInfo} builder where the bucket's name is set to the provided name. + */ public static Builder builder(String name) { return new Builder().name(name); } @@ -709,10 +749,10 @@ static BucketInfo fromPb(com.google.api.services.storage.model.Bucket bucketPb) builder.createTime(bucketPb.getTimeCreated().getValue()); } if (bucketPb.getLocation() != null) { - builder.location(Location.of(bucketPb.getLocation())); + builder.location(bucketPb.getLocation()); } if (bucketPb.getStorageClass() != null) { - builder.storageClass(StorageClass.of(bucketPb.getStorageClass())); + builder.storageClass(bucketPb.getStorageClass()); } if (bucketPb.getCors() != null) { builder.cors(transform(bucketPb.getCors(), Cors.FROM_PB_FUNCTION)); diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketInfoTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketInfoTest.java index 09ba0e8cda8e..4fa420b4b6e1 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketInfoTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketInfoTest.java @@ -31,10 +31,8 @@ import com.google.gcloud.storage.BucketInfo.DeleteRule; import com.google.gcloud.storage.BucketInfo.DeleteRule.Type; import com.google.gcloud.storage.BucketInfo.IsLiveDeleteRule; -import com.google.gcloud.storage.BucketInfo.Location; import com.google.gcloud.storage.BucketInfo.NumNewerVersionsDeleteRule; import com.google.gcloud.storage.BucketInfo.RawDeleteRule; -import com.google.gcloud.storage.BucketInfo.StorageClass; import org.junit.Test; @@ -59,8 +57,8 @@ public class BucketInfoTest { Collections.singletonList(new AgeDeleteRule(5)); private static final String INDEX_PAGE = "index.html"; private static final String NOT_FOUND_PAGE = "error.html"; - private static final Location LOCATION = Location.asia(); - private static final StorageClass STORAGE_CLASS = StorageClass.standard(); + private static final String LOCATION = "ASIA"; + private static final String STORAGE_CLASS = "STANDARD"; private static final Boolean VERSIONING_ENABLED = true; private static final BucketInfo BUCKET_INFO = BucketInfo.builder("b") .acl(ACL) @@ -149,16 +147,6 @@ private void compareBuckets(BucketInfo expected, BucketInfo value) { assertEquals(expected.versioningEnabled(), value.versioningEnabled()); } - @Test - public void testLocation() { - assertEquals("ASIA", Location.asia().value()); - assertEquals("EU", Location.eu().value()); - assertEquals("US", Location.us().value()); - assertSame(Location.asia(), Location.of("asia")); - assertSame(Location.eu(), Location.of("EU")); - assertSame(Location.us(), Location.of("uS")); - } - @Test public void testDeleteRules() { AgeDeleteRule ageRule = new AgeDeleteRule(10); From ecaf7519522b43431f4c7c24b31b0bd4a09c54ed Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 11 Nov 2015 17:14:52 +0100 Subject: [PATCH 38/48] Add javadoc to BlobInfo --- .../com/google/gcloud/storage/BlobInfo.java | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobInfo.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobInfo.java index 01711a53613e..9662635160e8 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobInfo.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobInfo.java @@ -123,6 +123,9 @@ public static final class Builder { private Builder() {} + /** + * Sets the blob identity. + */ public Builder blobId(BlobId blobId) { this.blobId = checkNotNull(blobId); return this; @@ -133,21 +136,33 @@ Builder id(String id) { return this; } + /** + * Sets the blob's data content type. + */ public Builder contentType(String contentType) { this.contentType = firstNonNull(contentType, Data.nullOf(String.class)); return this; } + /** + * Sets the blob's data content disposition. + */ public Builder contentDisposition(String contentDisposition) { this.contentDisposition = firstNonNull(contentDisposition, Data.nullOf(String.class)); return this; } + /** + * Sets the blob's data content language. + */ public Builder contentLanguage(String contentLanguage) { this.contentLanguage = firstNonNull(contentLanguage, Data.nullOf(String.class)); return this; } + /** + * Sets the blob's data content encoding. + */ public Builder contentEncoding(String contentEncoding) { this.contentEncoding = firstNonNull(contentEncoding, Data.nullOf(String.class)); return this; @@ -158,11 +173,20 @@ Builder componentCount(Integer componentCount) { return this; } + /** + * Sets the blob's data cache control. + */ public Builder cacheControl(String cacheControl) { this.cacheControl = firstNonNull(cacheControl, Data.nullOf(String.class)); return this; } + /** + * Sets the blob's access control configuration. + * + * @see + * About Access Control Lists + */ public Builder acl(List acl) { this.acl = acl != null ? ImmutableList.copyOf(acl) : null; return this; @@ -188,11 +212,18 @@ Builder selfLink(String selfLink) { return this; } + /** + * Sets the MD5 hash of blob's data. MD5 value must be encoded in base64. + */ public Builder md5(String md5) { this.md5 = firstNonNull(md5, Data.nullOf(String.class)); return this; } + /** + * Sets the CRC32C checksum of blob's data. CRC32C value must be encoded in base64 in big-endian + * order. + */ public Builder crc32c(String crc32c) { this.crc32c = firstNonNull(crc32c, Data.nullOf(String.class)); return this; @@ -203,6 +234,9 @@ Builder mediaLink(String mediaLink) { return this; } + /** + * Sets the blob's metadata. + */ public Builder metadata(Map metadata) { this.metadata = metadata != null ? new HashMap(metadata) : Data.nullOf(ImmutableEmptyMap.class); @@ -229,6 +263,9 @@ Builder updateTime(Long updateTime) { return this; } + /** + * Creates a {@code BlobInfo} object. + */ public BlobInfo build() { checkNotNull(blobId); return new BlobInfo(this); @@ -259,98 +296,177 @@ private BlobInfo(Builder builder) { updateTime = builder.updateTime; } + /** + * Returns the blob's identity. + */ public BlobId blobId() { return blobId; } + /** + * Returns the name of the containing bucket. + */ public String bucket() { return blobId().bucket(); } + /** + * Returns the blob's id. + */ public String id() { return id; } + /** + * Returns the blob's name. + */ public String name() { return blobId().name(); } + /** + * Returns the blob's data cache control. + */ public String cacheControl() { return Data.isNull(cacheControl) ? null : cacheControl; } + /** + * Returns the blob's access control configuration. + * + * @see + * About Access Control Lists + */ public List acl() { return acl; } + /** + * Returns the blob's owner. + */ public Acl.Entity owner() { return owner; } + /** + * Returns the blob's data size in bytes. + */ public Long size() { return size; } + /** + * Returns the blob's data content type. + */ public String contentType() { return Data.isNull(contentType) ? null : contentType; } + /** + * Returns the blob's data content encoding. + */ public String contentEncoding() { return Data.isNull(contentEncoding) ? null : contentEncoding; } + /** + * Returns the blob's data content disposition. + */ public String contentDisposition() { return Data.isNull(contentDisposition) ? null : contentDisposition; } + /** + * Returns the blob's data content language. + */ public String contentLanguage() { return Data.isNull(contentLanguage) ? null : contentLanguage; } + /** + * Returns the number of components that make up this object. Components are accumulated through + * the {@link Storage#compose(Storage.ComposeRequest)} operation. + * + * @see Component Count + * Property + */ public Integer componentCount() { return componentCount; } + /** + * Returns blob resource's entity tag. + */ public String etag() { return etag; } + /** + * Returns the URI of this blob as a string. + */ public String selfLink() { return selfLink; } + /** + * Returns the MD5 hash of blob's data encoded in base64. + */ public String md5() { return Data.isNull(md5) ? null : md5; } + /** + * Returns the CRC32C checksum of blob's data encoded in base64 in big-endian order. + */ public String crc32c() { return Data.isNull(crc32c) ? null : crc32c; } + /** + * Returns the blob's media download link. + */ public String mediaLink() { return mediaLink; } + /** + * Returns blob's metadata. + */ public Map metadata() { return metadata == null || Data.isNull(metadata) ? null : Collections.unmodifiableMap(metadata); } + /** + * Returns blob's data generation. + */ public Long generation() { return generation; } + /** + * Returns blob's metageneration. + */ public Long metageneration() { return metageneration; } + /** + * Returns the deletion time of the blob. + */ public Long deleteTime() { return deleteTime; } + /** + * Returns the last modification time of the blob's metadata. + */ public Long updateTime() { return updateTime; } + /** + * Returns a builder for the current blob. + */ public Builder toBuilder() { return new Builder() .blobId(blobId) @@ -444,14 +560,23 @@ public ObjectAccessControl apply(Acl acl) { return storageObject; } + /** + * Returns a {@code BlobInfo} builder where blob identity is set using the provided values. + */ public static Builder builder(BucketInfo bucketInfo, String name) { return builder(bucketInfo.name(), name); } + /** + * Returns a {@code BlobInfo} builder where blob identity is set using the provided values. + */ public static Builder builder(String bucket, String name) { return new Builder().blobId(BlobId.of(bucket, name)); } + /** + * Returns a {@code BlobInfo} builder where blob identity is set to the provided value. + */ public static Builder builder(BlobId blobId) { return new Builder().blobId(blobId); } From b9ef50883ddda7e19f1f9ec4599dca4c279c6ce8 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 11 Nov 2015 17:15:08 +0100 Subject: [PATCH 39/48] Add javadoc to Storage --- .../com/google/gcloud/storage/Storage.java | 222 +++++++++++++++++- 1 file changed, 221 insertions(+), 1 deletion(-) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java index 115449064c66..128099b7eab3 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java @@ -156,6 +156,9 @@ static String selector(BlobField... fields) { } } + /** + * Class for specifying bucket target options. + */ class BucketTargetOption extends Option { private static final long serialVersionUID = -5880204616982900975L; @@ -168,23 +171,40 @@ private BucketTargetOption(StorageRpc.Option rpcOption) { this(rpcOption, null); } + /** + * Returns an option for specifying bucket's predefined ACL configuration. + */ public static BucketTargetOption predefinedAcl(PredefinedAcl acl) { return new BucketTargetOption(StorageRpc.Option.PREDEFINED_ACL, acl.entry()); } + /** + * Returns an option for specifying bucket's default ACL configuration for blobs. + */ public static BucketTargetOption predefinedDefaultObjectAcl(PredefinedAcl acl) { return new BucketTargetOption(StorageRpc.Option.PREDEFINED_DEFAULT_OBJECT_ACL, acl.entry()); } + /** + * Returns an option for bucket's metageneration match. If this option is used the request will + * fail if metageneration does not match. + */ public static BucketTargetOption metagenerationMatch() { return new BucketTargetOption(StorageRpc.Option.IF_METAGENERATION_MATCH); } + /** + * Returns an option for bucket's metageneration mismatch. If this option is used the request + * will fail if metageneration matches. + */ public static BucketTargetOption metagenerationNotMatch() { return new BucketTargetOption(StorageRpc.Option.IF_METAGENERATION_NOT_MATCH); } } + /** + * Class for specifying bucket source options. + */ class BucketSourceOption extends Option { private static final long serialVersionUID = 5185657617120212117L; @@ -193,15 +213,26 @@ private BucketSourceOption(StorageRpc.Option rpcOption, long metageneration) { super(rpcOption, metageneration); } + /** + * Returns an option for bucket's metageneration match. If this option is used the request will + * fail if bucket's metageneration does not match the provided value. + */ public static BucketSourceOption metagenerationMatch(long metageneration) { return new BucketSourceOption(StorageRpc.Option.IF_METAGENERATION_MATCH, metageneration); } + /** + * Returns an option for bucket's metageneration mismatch. If this option is used the request + * will fail if bucket's metageneration matches the provided value. + */ public static BucketSourceOption metagenerationNotMatch(long metageneration) { return new BucketSourceOption(StorageRpc.Option.IF_METAGENERATION_NOT_MATCH, metageneration); } } + /** + * Class for specifying bucket source options. + */ class BucketGetOption extends Option { private static final long serialVersionUID = 1901844869484087395L; @@ -214,10 +245,18 @@ private BucketGetOption(StorageRpc.Option rpcOption, String value) { super(rpcOption, value); } + /** + * Returns an option for bucket's metageneration match. If this option is used the request will + * fail if bucket's metageneration does not match the provided value. + */ public static BucketGetOption metagenerationMatch(long metageneration) { return new BucketGetOption(StorageRpc.Option.IF_METAGENERATION_MATCH, metageneration); } + /** + * Returns an option for bucket's metageneration mismatch. If this option is used the request + * will fail if bucket's metageneration matches the provided value. + */ public static BucketGetOption metagenerationNotMatch(long metageneration) { return new BucketGetOption(StorageRpc.Option.IF_METAGENERATION_NOT_MATCH, metageneration); } @@ -233,6 +272,9 @@ public static BucketGetOption fields(BucketField... fields) { } } + /** + * Class for specifying blob target options. + */ class BlobTargetOption extends Option { private static final long serialVersionUID = 214616862061934846L; @@ -245,26 +287,48 @@ private BlobTargetOption(StorageRpc.Option rpcOption) { this(rpcOption, null); } + /** + * Returns an option for specifying blob's predefined ACL configuration. + */ public static BlobTargetOption predefinedAcl(PredefinedAcl acl) { return new BlobTargetOption(StorageRpc.Option.PREDEFINED_ACL, acl.entry()); } + /** + * Returns an option that causes an operation to succeed only if the target blob does not exist. + */ public static BlobTargetOption doesNotExist() { return new BlobTargetOption(StorageRpc.Option.IF_GENERATION_MATCH, 0L); } + /** + * Returns an option for blob's data generation match. If this option is used the request will + * fail if generation does not match. + */ public static BlobTargetOption generationMatch() { return new BlobTargetOption(StorageRpc.Option.IF_GENERATION_MATCH); } + /** + * Returns an option for blob's data generation mismatch. If this option is used the request + * will fail if generation matches. + */ public static BlobTargetOption generationNotMatch() { return new BlobTargetOption(StorageRpc.Option.IF_GENERATION_NOT_MATCH); } + /** + * Returns an option for blob's metageneration match. If this option is used the request will + * fail if metageneration does not match. + */ public static BlobTargetOption metagenerationMatch() { return new BlobTargetOption(StorageRpc.Option.IF_METAGENERATION_MATCH); } + /** + * Returns an option for blob's metageneration mismatch. If this option is used the request will + * fail if metageneration matches. + */ public static BlobTargetOption metagenerationNotMatch() { return new BlobTargetOption(StorageRpc.Option.IF_METAGENERATION_NOT_MATCH); } @@ -290,6 +354,9 @@ static Tuple convert(BlobInfo info, BlobWriteOptio } } + /** + * Class for specifying blob write options. + */ class BlobWriteOption implements Serializable { private static final long serialVersionUID = -3880421670966224580L; @@ -336,39 +403,72 @@ public boolean equals(Object obj) { return this.option == other.option && Objects.equals(this.value, other.value); } + /** + * Returns an option for specifying blob's predefined ACL configuration. + */ public static BlobWriteOption predefinedAcl(PredefinedAcl acl) { return new BlobWriteOption(Option.PREDEFINED_ACL, acl.entry()); } + /** + * Returns an option that causes an operation to succeed only if the target blob does not exist. + */ public static BlobWriteOption doesNotExist() { return new BlobWriteOption(Option.IF_GENERATION_MATCH, 0L); } + /** + * Returns an option for blob's data generation match. If this option is used the request will + * fail if generation does not match. + */ public static BlobWriteOption generationMatch() { return new BlobWriteOption(Option.IF_GENERATION_MATCH); } + /** + * Returns an option for blob's data generation mismatch. If this option is used the request + * will fail if generation matches. + */ public static BlobWriteOption generationNotMatch() { return new BlobWriteOption(Option.IF_GENERATION_NOT_MATCH); } + /** + * Returns an option for blob's metageneration match. If this option is used the request will + * fail if metageneration does not match. + */ public static BlobWriteOption metagenerationMatch() { return new BlobWriteOption(Option.IF_METAGENERATION_MATCH); } + /** + * Returns an option for blob's metageneration mismatch. If this option is used the request will + * fail if metageneration matches. + */ public static BlobWriteOption metagenerationNotMatch() { return new BlobWriteOption(Option.IF_METAGENERATION_NOT_MATCH); } + /** + * Returns an option for blob's data MD5 hash match. If this option is used the request will + * fail if blobs' data MD5 hash does not match. + */ public static BlobWriteOption md5Match() { return new BlobWriteOption(Option.IF_MD5_MATCH, true); } + /** + * Returns an option for blob's data CRC32C checksum match. If this option is used the request + * will fail if blobs' data CRC32C checksum does not match. + */ public static BlobWriteOption crc32cMatch() { return new BlobWriteOption(Option.IF_CRC32C_MATCH, true); } } + /** + * Class for specifying blob source options. + */ class BlobSourceOption extends Option { private static final long serialVersionUID = -3712768261070182991L; @@ -377,23 +477,42 @@ private BlobSourceOption(StorageRpc.Option rpcOption, long value) { super(rpcOption, value); } + /** + * Returns an option for blob's data generation match. If this option is used the request will + * fail if blob's generation does not match the provided value. + */ public static BlobSourceOption generationMatch(long generation) { return new BlobSourceOption(StorageRpc.Option.IF_GENERATION_MATCH, generation); } + /** + * Returns an option for blob's data generation mismatch. If this option is used the request + * will fail if blob's generation matches the provided value. + */ public static BlobSourceOption generationNotMatch(long generation) { return new BlobSourceOption(StorageRpc.Option.IF_GENERATION_NOT_MATCH, generation); } + /** + * Returns an option for blob's metageneration match. If this option is used the request will + * fail if blob's metageneration does not match the provided value. + */ public static BlobSourceOption metagenerationMatch(long metageneration) { return new BlobSourceOption(StorageRpc.Option.IF_METAGENERATION_MATCH, metageneration); } + /** + * Returns an option for blob's metageneration mismatch. If this option is used the request will + * fail if blob's metageneration matches the provided value. + */ public static BlobSourceOption metagenerationNotMatch(long metageneration) { return new BlobSourceOption(StorageRpc.Option.IF_METAGENERATION_NOT_MATCH, metageneration); } } + /** + * Class for specifying blob get options. + */ class BlobGetOption extends Option { private static final long serialVersionUID = 803817709703661480L; @@ -406,18 +525,34 @@ private BlobGetOption(StorageRpc.Option rpcOption, String value) { super(rpcOption, value); } + /** + * Returns an option for blob's data generation match. If this option is used the request will + * fail if blob's generation does not match the provided value. + */ public static BlobGetOption generationMatch(long generation) { return new BlobGetOption(StorageRpc.Option.IF_GENERATION_MATCH, generation); } + /** + * Returns an option for blob's data generation mismatch. If this option is used the request + * will fail if blob's generation matches the provided value. + */ public static BlobGetOption generationNotMatch(long generation) { return new BlobGetOption(StorageRpc.Option.IF_GENERATION_NOT_MATCH, generation); } + /** + * Returns an option for blob's metageneration match. If this option is used the request will + * fail if blob's metageneration does not match the provided value. + */ public static BlobGetOption metagenerationMatch(long metageneration) { return new BlobGetOption(StorageRpc.Option.IF_METAGENERATION_MATCH, metageneration); } + /** + * Returns an option for blob's metageneration mismatch. If this option is used the request will + * fail if blob's metageneration matches the provided value. + */ public static BlobGetOption metagenerationNotMatch(long metageneration) { return new BlobGetOption(StorageRpc.Option.IF_METAGENERATION_NOT_MATCH, metageneration); } @@ -433,6 +568,9 @@ public static BlobGetOption fields(BlobField... fields) { } } + /** + * Class for specifying bucket list options. + */ class BucketListOption extends Option { private static final long serialVersionUID = 8754017079673290353L; @@ -441,14 +579,23 @@ private BucketListOption(StorageRpc.Option option, Object value) { super(option, value); } + /** + * Returns an option to specify the maximum number of buckets to be returned. + */ public static BucketListOption maxResults(long maxResults) { return new BucketListOption(StorageRpc.Option.MAX_RESULTS, maxResults); } + /** + * Returns an option to specify the page token from which to start listing buckets. + */ public static BucketListOption startPageToken(String pageToken) { return new BucketListOption(StorageRpc.Option.PAGE_TOKEN, pageToken); } + /** + * Returns an option to set a prefix for listed buckets names. + */ public static BucketListOption prefix(String prefix) { return new BucketListOption(StorageRpc.Option.PREFIX, prefix); } @@ -466,6 +613,9 @@ public static BucketListOption fields(BucketField... fields) { } } + /** + * Class for specifying blob list options. + */ class BlobListOption extends Option { private static final long serialVersionUID = 9083383524788661294L; @@ -474,18 +624,30 @@ private BlobListOption(StorageRpc.Option option, Object value) { super(option, value); } + /** + * Returns an option to specify the maximum number of blobs to be returned. + */ public static BlobListOption maxResults(long maxResults) { return new BlobListOption(StorageRpc.Option.MAX_RESULTS, maxResults); } + /** + * Returns an option to specify the page token from which to start listing blobs. + */ public static BlobListOption startPageToken(String pageToken) { return new BlobListOption(StorageRpc.Option.PAGE_TOKEN, pageToken); } + /** + * Returns an option to set a prefix for listed blobs names. + */ public static BlobListOption prefix(String prefix) { return new BlobListOption(StorageRpc.Option.PREFIX, prefix); } + /** + * Returns an option to specify whether blob listing should include subdirectories or not. + */ public static BlobListOption recursive(boolean recursive) { return new BlobListOption(StorageRpc.Option.DELIMITER, recursive); } @@ -503,6 +665,9 @@ public static BlobListOption fields(BlobField... fields) { } } + /** + * Class for specifying signed URL options. + */ class SignUrlOption implements Serializable { private static final long serialVersionUID = 7850569877451099267L; @@ -562,6 +727,12 @@ public static SignUrlOption serviceAccount(ServiceAccountAuthCredentials credent } } + /** + * A class to contain all information needed for a Google Cloud Storage Compose operation. + * + * @see + * Compose Operation + */ class ComposeRequest implements Serializable { private static final long serialVersionUID = -7385681353748590911L; @@ -570,6 +741,9 @@ class ComposeRequest implements Serializable { private final BlobInfo target; private final List targetOptions; + /** + * Class for Compose source blobs. + */ public static class SourceBlob implements Serializable { private static final long serialVersionUID = 4094962795951990439L; @@ -601,6 +775,9 @@ public static class Builder { private final Set targetOptions = new LinkedHashSet<>(); private BlobInfo target; + /** + * Add source blobs for compose operation. + */ public Builder addSource(Iterable blobs) { for (String blob : blobs) { sourceBlobs.add(new SourceBlob(blob)); @@ -608,6 +785,9 @@ public Builder addSource(Iterable blobs) { return this; } + /** + * Add source blobs for compose operation. + */ public Builder addSource(String... blobs) { return addSource(Arrays.asList(blobs)); } @@ -620,21 +800,33 @@ public Builder addSource(String blob, long generation) { return this; } + /** + * Sets compose operation's target blob. + */ public Builder target(BlobInfo target) { this.target = target; return this; } + /** + * Sets compose operation's target blob options. + */ public Builder targetOptions(BlobTargetOption... options) { Collections.addAll(targetOptions, options); return this; } + /** + * Sets compose operation's target blob options. + */ public Builder targetOptions(Iterable options) { Iterables.addAll(targetOptions, options); return this; } + /** + * Creates a {@code ComposeRequest} object. + */ public ComposeRequest build() { checkArgument(!sourceBlobs.isEmpty()); checkNotNull(target); @@ -648,31 +840,59 @@ private ComposeRequest(Builder builder) { targetOptions = ImmutableList.copyOf(builder.targetOptions); } + /** + * Returns compose operation's source blobs. + */ public List sourceBlobs() { return sourceBlobs; } + /** + * Returns compose operation's target blob. + */ public BlobInfo target() { return target; } + /** + * Returns compose operation's target blob's options. + */ public List targetOptions() { return targetOptions; } + /** + * Creates a {@code ComposeRequest} object. + * + * @param sources source blobs names + * @param target target blob + */ public static ComposeRequest of(Iterable sources, BlobInfo target) { return builder().target(target).addSource(sources).build(); } + /** + * Creates a {@code ComposeRequest} object. + * + * @param bucket name of the bucket where the compose operation takes place + * @param sources source blobs names + * @param target target blob name + */ public static ComposeRequest of(String bucket, Iterable sources, String target) { return of(sources, BlobInfo.builder(BlobId.of(bucket, target)).build()); } + /** + * Returns a {@code ComposeRequest} builder. + */ public static Builder builder() { return new Builder(); } } + /** + * A class to contain all information needed for a Google Cloud Storage Copy operation. + */ class CopyRequest implements Serializable { private static final long serialVersionUID = -4498650529476219937L; @@ -786,7 +1006,7 @@ public Builder megabytesCopiedPerChunk(Long megabytesCopiedPerChunk) { } /** - * Creates a {@code CopyRequest}. + * Creates a {@code CopyRequest} object. */ public CopyRequest build() { checkNotNull(source); From 3125167ad845cc5f0c5deeeffa215a56e9fff896 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 11 Nov 2015 17:55:34 +0100 Subject: [PATCH 40/48] Add getDefaultInstance method to StorageOptions and DatastoreOptions --- .../java/com/google/gcloud/datastore/DatastoreOptions.java | 7 +++++++ .../java/com/google/gcloud/storage/StorageOptions.java | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreOptions.java b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreOptions.java index 5338c03a6d56..58c361229f07 100644 --- a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreOptions.java +++ b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreOptions.java @@ -171,6 +171,13 @@ public String namespace() { return namespace; } + /** + * Returns a default {@code DatastoreOptions} instance. + */ + public static DatastoreOptions getDefaultInstance() { + return builder().build(); + } + private static String defaultNamespace() { try { Class clazz = Class.forName("com.google.appengine.api.NamespaceManager"); diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageOptions.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageOptions.java index 16c17c3e8d98..4b295fc97b29 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageOptions.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageOptions.java @@ -111,6 +111,13 @@ public String pathDelimiter() { return pathDelimiter; } + /** + * Returns a default {@code StorageOptions} instance. + */ + public static StorageOptions getDefaultInstance() { + return builder().build(); + } + @Override public Builder toBuilder() { return new Builder(this); From d7845b86bcc38abc5a444fd8f08ec98a0d73d0c5 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 11 Nov 2015 21:39:44 +0100 Subject: [PATCH 41/48] Rename getDefaultInstance to defaultInstance and update READMEs --- README.md | 2 +- gcloud-java-datastore/README.md | 2 +- .../main/java/com/google/gcloud/datastore/DatastoreOptions.java | 2 +- .../src/main/java/com/google/gcloud/storage/StorageOptions.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0fd576a6a127..5ed44e91adfd 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ import com.google.gcloud.datastore.Entity; import com.google.gcloud.datastore.Key; import com.google.gcloud.datastore.KeyFactory; -Datastore datastore = DatastoreOptions.getDefaultInstance().service(); +Datastore datastore = DatastoreOptions.defaultInstance().service(); KeyFactory keyFactory = datastore.newKeyFactory().kind(KIND); Key key = keyFactory.newKey(keyName); Entity entity = datastore.get(key); diff --git a/gcloud-java-datastore/README.md b/gcloud-java-datastore/README.md index 67483fae2b6e..6d9fc0e8c4d6 100644 --- a/gcloud-java-datastore/README.md +++ b/gcloud-java-datastore/README.md @@ -66,7 +66,7 @@ import com.google.gcloud.datastore.Entity; import com.google.gcloud.datastore.Key; import com.google.gcloud.datastore.KeyFactory; -Datastore datastore = DatastoreOptions.getDefaultInstance().service(); +Datastore datastore = DatastoreOptions.defaultInstance().service(); KeyFactory keyFactory = datastore.newKeyFactory().kind(KIND); Key key = keyFactory.newKey(keyName); Entity entity = datastore.get(key); diff --git a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreOptions.java b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreOptions.java index 58c361229f07..ee15393a8048 100644 --- a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreOptions.java +++ b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/DatastoreOptions.java @@ -174,7 +174,7 @@ public String namespace() { /** * Returns a default {@code DatastoreOptions} instance. */ - public static DatastoreOptions getDefaultInstance() { + public static DatastoreOptions defaultInstance() { return builder().build(); } diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageOptions.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageOptions.java index 4b295fc97b29..2ad0950aa6aa 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageOptions.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageOptions.java @@ -114,7 +114,7 @@ public String pathDelimiter() { /** * Returns a default {@code StorageOptions} instance. */ - public static StorageOptions getDefaultInstance() { + public static StorageOptions defaultInstance() { return builder().build(); } From d0265406392a9c30f96903c5647874e82f92117b Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 11 Nov 2015 21:50:51 +0100 Subject: [PATCH 42/48] Make RetryParams conform with our code style --- .../java/com/google/gcloud/RetryHelper.java | 14 ++++---- .../java/com/google/gcloud/RetryParams.java | 30 ++++++++-------- .../com/google/gcloud/RetryHelperTest.java | 2 +- .../com/google/gcloud/RetryParamsTest.java | 34 +++++++++---------- .../gcloud/datastore/DatastoreTest.java | 6 ++-- .../gcloud/datastore/SerializationTest.java | 2 +- .../gcloud/examples/StorageExample.java | 3 +- .../gcloud/storage/RemoteGcsHelperTest.java | 10 +++--- .../gcloud/storage/SerializationTest.java | 6 ++-- .../gcloud/storage/StorageImplTest.java | 6 ++-- 10 files changed, 56 insertions(+), 57 deletions(-) diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/RetryHelper.java b/gcloud-java-core/src/main/java/com/google/gcloud/RetryHelper.java index 7b47209cd3ff..90f403758e45 100644 --- a/gcloud-java-core/src/main/java/com/google/gcloud/RetryHelper.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/RetryHelper.java @@ -194,9 +194,9 @@ private V doRetry() throws RetryHelperException { } exception = e; } - if (attemptNumber >= params.getRetryMaxAttempts() - || attemptNumber >= params.getRetryMinAttempts() - && stopwatch.elapsed(MILLISECONDS) >= params.getTotalRetryPeriodMillis()) { + if (attemptNumber >= params.retryMaxAttempts() + || attemptNumber >= params.retryMinAttempts() + && stopwatch.elapsed(MILLISECONDS) >= params.totalRetryPeriodMillis()) { throw new RetriesExhaustedException(this + ": Too many failures, giving up", exception); } long sleepDurationMillis = getSleepDuration(params, attemptNumber); @@ -215,9 +215,9 @@ private V doRetry() throws RetryHelperException { @VisibleForTesting static long getSleepDuration(RetryParams retryParams, int attemptsSoFar) { - long initialDelay = retryParams.getInitialRetryDelayMillis(); - double backoffFactor = retryParams.getRetryDelayBackoffFactor(); - long maxDelay = retryParams.getMaxRetryDelayMillis(); + long initialDelay = retryParams.initialRetryDelayMillis(); + double backoffFactor = retryParams.retryDelayBackoffFactor(); + long maxDelay = retryParams.maxRetryDelayMillis(); long retryDelay = getExponentialValue(initialDelay, backoffFactor, maxDelay, attemptsSoFar); return (long) ((random() / 2.0 + .75) * retryDelay); } @@ -228,7 +228,7 @@ private static long getExponentialValue(long initialDelay, double backoffFactor, } public static V runWithRetries(Callable callable) throws RetryHelperException { - return runWithRetries(callable, RetryParams.getDefaultInstance(), + return runWithRetries(callable, RetryParams.defaultInstance(), ExceptionHandler.getDefaultInstance()); } diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/RetryParams.java b/gcloud-java-core/src/main/java/com/google/gcloud/RetryParams.java index 461dbac77ff2..ab3644c6d747 100644 --- a/gcloud-java-core/src/main/java/com/google/gcloud/RetryParams.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/RetryParams.java @@ -38,8 +38,8 @@ * {@code RetryParams}, first create a {@link RetryParams.Builder}. The builder is mutable and each * of the parameters can be set (any unset parameters will fallback to the defaults). The * {@code Builder} can be then used to create an immutable {@code RetryParams} object. For default - * {@code RetryParams} use {@link #getDefaultInstance}. Default settings are subject to change - * release to release. If you require specific settings, explicitly create an instance of + * {@code RetryParams} use {@link #defaultInstance}. Default settings are subject to change release + * to release. If you require specific settings, explicitly create an instance of * {@code RetryParams} with all the required settings. * * @see RetryHelper @@ -91,12 +91,12 @@ private Builder() { retryDelayBackoffFactor = DEFAULT_RETRY_DELAY_BACKOFF_FACTOR; totalRetryPeriodMillis = DEFAULT_TOTAL_RETRY_PERIOD_MILLIS; } else { - retryMinAttempts = retryParams.getRetryMinAttempts(); - retryMaxAttempts = retryParams.getRetryMaxAttempts(); - initialRetryDelayMillis = retryParams.getInitialRetryDelayMillis(); - maxRetryDelayMillis = retryParams.getMaxRetryDelayMillis(); - retryDelayBackoffFactor = retryParams.getRetryDelayBackoffFactor(); - totalRetryPeriodMillis = retryParams.getTotalRetryPeriodMillis(); + retryMinAttempts = retryParams.retryMinAttempts(); + retryMaxAttempts = retryParams.retryMaxAttempts(); + initialRetryDelayMillis = retryParams.initialRetryDelayMillis(); + maxRetryDelayMillis = retryParams.maxRetryDelayMillis(); + retryDelayBackoffFactor = retryParams.retryDelayBackoffFactor(); + totalRetryPeriodMillis = retryParams.totalRetryPeriodMillis(); } } @@ -201,7 +201,7 @@ private RetryParams(Builder builder) { /** * Returns an instance with the default parameters. */ - public static RetryParams getDefaultInstance() { + public static RetryParams defaultInstance() { return DEFAULT_INSTANCE; } @@ -216,14 +216,14 @@ public static RetryParams noRetries() { /** * Returns the retryMinAttempts. Default value is {@value #DEFAULT_RETRY_MIN_ATTEMPTS}. */ - public int getRetryMinAttempts() { + public int retryMinAttempts() { return retryMinAttempts; } /** * Returns the retryMaxAttempts. Default value is {@value #DEFAULT_RETRY_MAX_ATTEMPTS}. */ - public int getRetryMaxAttempts() { + public int retryMaxAttempts() { return retryMaxAttempts; } @@ -231,14 +231,14 @@ public int getRetryMaxAttempts() { * Returns the initialRetryDelayMillis. Default value is * {@value #DEFAULT_INITIAL_RETRY_DELAY_MILLIS}. */ - public long getInitialRetryDelayMillis() { + public long initialRetryDelayMillis() { return initialRetryDelayMillis; } /** * Returns the maxRetryDelayMillis. Default values is {@value #DEFAULT_MAX_RETRY_DELAY_MILLIS}. */ - public long getMaxRetryDelayMillis() { + public long maxRetryDelayMillis() { return maxRetryDelayMillis; } @@ -246,7 +246,7 @@ public long getMaxRetryDelayMillis() { * Returns the maxRetryDelayBackoffFactor. Default values is * {@value #DEFAULT_RETRY_DELAY_BACKOFF_FACTOR}. */ - public double getRetryDelayBackoffFactor() { + public double retryDelayBackoffFactor() { return retryDelayBackoffFactor; } @@ -254,7 +254,7 @@ public double getRetryDelayBackoffFactor() { * Returns the totalRetryPeriodMillis. Default value is * {@value #DEFAULT_TOTAL_RETRY_PERIOD_MILLIS}. */ - public long getTotalRetryPeriodMillis() { + public long totalRetryPeriodMillis() { return totalRetryPeriodMillis; } diff --git a/gcloud-java-core/src/test/java/com/google/gcloud/RetryHelperTest.java b/gcloud-java-core/src/test/java/com/google/gcloud/RetryHelperTest.java index dfd933bcae46..bf11e744dbbf 100644 --- a/gcloud-java-core/src/test/java/com/google/gcloud/RetryHelperTest.java +++ b/gcloud-java-core/src/test/java/com/google/gcloud/RetryHelperTest.java @@ -118,7 +118,7 @@ public void testTriesAtLeastMinTimes() { @Override public Integer call() throws IOException { timesCalled++; assertEquals(timesCalled, RetryHelper.getContext().getAttemptNumber()); - assertEquals(10, RetryHelper.getContext().getRetryParams().getRetryMaxAttempts()); + assertEquals(10, RetryHelper.getContext().getRetryParams().retryMaxAttempts()); if (timesCalled <= timesToFail) { throw new IOException(); } diff --git a/gcloud-java-core/src/test/java/com/google/gcloud/RetryParamsTest.java b/gcloud-java-core/src/test/java/com/google/gcloud/RetryParamsTest.java index d1d5e3c076d8..eae44693929b 100644 --- a/gcloud-java-core/src/test/java/com/google/gcloud/RetryParamsTest.java +++ b/gcloud-java-core/src/test/java/com/google/gcloud/RetryParamsTest.java @@ -41,15 +41,15 @@ public class RetryParamsTest { @Test public void testDefaults() { - RetryParams params1 = RetryParams.getDefaultInstance(); + RetryParams params1 = RetryParams.defaultInstance(); RetryParams params2 = RetryParams.builder().build(); for (RetryParams params : Arrays.asList(params1, params2)) { - assertEquals(DEFAULT_INITIAL_RETRY_DELAY_MILLIS, params.getInitialRetryDelayMillis()); - assertEquals(DEFAULT_MAX_RETRY_DELAY_MILLIS, params.getMaxRetryDelayMillis()); - assertEquals(DEFAULT_RETRY_DELAY_BACKOFF_FACTOR, params.getRetryDelayBackoffFactor(), 0); - assertEquals(DEFAULT_RETRY_MAX_ATTEMPTS, params.getRetryMaxAttempts()); - assertEquals(DEFAULT_RETRY_MIN_ATTEMPTS, params.getRetryMinAttempts()); - assertEquals(DEFAULT_TOTAL_RETRY_PERIOD_MILLIS, params.getTotalRetryPeriodMillis()); + assertEquals(DEFAULT_INITIAL_RETRY_DELAY_MILLIS, params.initialRetryDelayMillis()); + assertEquals(DEFAULT_MAX_RETRY_DELAY_MILLIS, params.maxRetryDelayMillis()); + assertEquals(DEFAULT_RETRY_DELAY_BACKOFF_FACTOR, params.retryDelayBackoffFactor(), 0); + assertEquals(DEFAULT_RETRY_MAX_ATTEMPTS, params.retryMaxAttempts()); + assertEquals(DEFAULT_RETRY_MIN_ATTEMPTS, params.retryMinAttempts()); + assertEquals(DEFAULT_TOTAL_RETRY_PERIOD_MILLIS, params.totalRetryPeriodMillis()); } } @@ -65,12 +65,12 @@ public void testSetAndCopy() { RetryParams params1 = builder.build(); RetryParams params2 = new RetryParams.Builder(params1).build(); for (RetryParams params : Arrays.asList(params1, params2)) { - assertEquals(101, params.getInitialRetryDelayMillis()); - assertEquals(102, params.getMaxRetryDelayMillis()); - assertEquals(103, params.getRetryDelayBackoffFactor(), 0); - assertEquals(107, params.getRetryMinAttempts()); - assertEquals(108, params.getRetryMaxAttempts()); - assertEquals(109, params.getTotalRetryPeriodMillis()); + assertEquals(101, params.initialRetryDelayMillis()); + assertEquals(102, params.maxRetryDelayMillis()); + assertEquals(103, params.retryDelayBackoffFactor(), 0); + assertEquals(107, params.retryMinAttempts()); + assertEquals(108, params.retryMaxAttempts()); + assertEquals(109, params.totalRetryPeriodMillis()); } } @@ -79,19 +79,19 @@ public void testBadSettings() { RetryParams.Builder builder = RetryParams.builder(); builder.initialRetryDelayMillis(-1); builder = assertFailure(builder); - builder.maxRetryDelayMillis(RetryParams.getDefaultInstance().getInitialRetryDelayMillis() - 1); + builder.maxRetryDelayMillis(RetryParams.defaultInstance().initialRetryDelayMillis() - 1); builder = assertFailure(builder); builder.retryDelayBackoffFactor(-1); builder = assertFailure(builder); builder.retryMinAttempts(-1); builder = assertFailure(builder); - builder.retryMaxAttempts(RetryParams.getDefaultInstance().getRetryMinAttempts() - 1); + builder.retryMaxAttempts(RetryParams.defaultInstance().retryMinAttempts() - 1); builder = assertFailure(builder); builder.totalRetryPeriodMillis(-1); builder = assertFailure(builder); // verify that it is OK for min and max to be equal - builder.retryMaxAttempts(RetryParams.getDefaultInstance().getRetryMinAttempts()); - builder.maxRetryDelayMillis(RetryParams.getDefaultInstance().getInitialRetryDelayMillis()); + builder.retryMaxAttempts(RetryParams.defaultInstance().retryMinAttempts()); + builder.maxRetryDelayMillis(RetryParams.defaultInstance().initialRetryDelayMillis()); builder.build(); } diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java index 6afd40927264..162104c0dd84 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java @@ -625,7 +625,7 @@ private Datastore createDatastoreForDeferredLookup() throws DatastoreRpcExceptio EasyMock.replay(rpcFactoryMock, rpcMock); DatastoreOptions options = this.options.toBuilder() - .retryParams(RetryParams.getDefaultInstance()) + .retryParams(RetryParams.defaultInstance()) .serviceRpcFactory(rpcFactoryMock) .build(); return options.service(); @@ -738,7 +738,7 @@ public void testRetryableException() throws Exception { .andReturn(responsePb); EasyMock.replay(rpcFactoryMock, rpcMock); DatastoreOptions options = this.options.toBuilder() - .retryParams(RetryParams.getDefaultInstance()) + .retryParams(RetryParams.defaultInstance()) .serviceRpcFactory(rpcFactoryMock) .build(); Datastore datastore = options.service(); @@ -784,7 +784,7 @@ public void testRuntimeException() throws Exception { .andThrow(new RuntimeException(exceptionMessage)); EasyMock.replay(rpcFactoryMock, rpcMock); DatastoreOptions options = this.options.toBuilder() - .retryParams(RetryParams.getDefaultInstance()) + .retryParams(RetryParams.defaultInstance()) .serviceRpcFactory(rpcFactoryMock) .build(); Datastore datastore = options.service(); diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/SerializationTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/SerializationTest.java index 1ad690938ef5..32e14fb47ea0 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/SerializationTest.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/SerializationTest.java @@ -143,7 +143,7 @@ public void testServiceOptions() throws Exception { options = options.toBuilder() .namespace("ns1") - .retryParams(RetryParams.getDefaultInstance()) + .retryParams(RetryParams.defaultInstance()) .authCredentials(AuthCredentials.noCredentials()) .force(true) .build(); diff --git a/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java index b7a36de7589e..0e7d6bbbf3ea 100644 --- a/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java +++ b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java @@ -18,7 +18,6 @@ import com.google.gcloud.AuthCredentials; import com.google.gcloud.AuthCredentials.ServiceAccountAuthCredentials; -import com.google.gcloud.Page; import com.google.gcloud.RetryParams; import com.google.gcloud.spi.StorageRpc.Tuple; import com.google.gcloud.storage.Blob; @@ -546,7 +545,7 @@ public static void main(String... args) throws Exception { return; } StorageOptions.Builder optionsBuilder = - StorageOptions.builder().retryParams(RetryParams.getDefaultInstance()); + StorageOptions.builder().retryParams(RetryParams.defaultInstance()); StorageAction action; String actionName; if (args.length >= 2 && !ACTIONS.containsKey(args[0])) { diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java index 1da45fae466e..3c3d1aebb3df 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java @@ -159,11 +159,11 @@ public void testCreateFromStream() { assertEquals(PROJECT_ID, options.projectId()); assertEquals(60000, options.connectTimeout()); assertEquals(60000, options.readTimeout()); - assertEquals(10, options.retryParams().getRetryMaxAttempts()); - assertEquals(6, options.retryParams().getRetryMinAttempts()); - assertEquals(30000, options.retryParams().getMaxRetryDelayMillis()); - assertEquals(120000, options.retryParams().getTotalRetryPeriodMillis()); - assertEquals(250, options.retryParams().getInitialRetryDelayMillis()); + assertEquals(10, options.retryParams().retryMaxAttempts()); + assertEquals(6, options.retryParams().retryMinAttempts()); + assertEquals(30000, options.retryParams().maxRetryDelayMillis()); + assertEquals(120000, options.retryParams().totalRetryPeriodMillis()); + assertEquals(250, options.retryParams().initialRetryDelayMillis()); } @Test diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java index a125a64df6d6..2d80191aeb2d 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java @@ -82,7 +82,7 @@ public void testServiceOptions() throws Exception { options = options.toBuilder() .projectId("p2") - .retryParams(RetryParams.getDefaultInstance()) + .retryParams(RetryParams.defaultInstance()) .authCredentials(AuthCredentials.noCredentials()) .pathDelimiter(":") .build(); @@ -110,7 +110,7 @@ public void testModelAndRequests() throws Exception { public void testReadChannelState() throws IOException, ClassNotFoundException { StorageOptions options = StorageOptions.builder() .projectId("p2") - .retryParams(RetryParams.getDefaultInstance()) + .retryParams(RetryParams.defaultInstance()) .authCredentials(AuthCredentials.noCredentials()) .build(); BlobReadChannel reader = @@ -126,7 +126,7 @@ public void testReadChannelState() throws IOException, ClassNotFoundException { public void testWriteChannelState() throws IOException, ClassNotFoundException { StorageOptions options = StorageOptions.builder() .projectId("p2") - .retryParams(RetryParams.getDefaultInstance()) + .retryParams(RetryParams.defaultInstance()) .authCredentials(AuthCredentials.noCredentials()) .build(); BlobWriteChannelImpl writer = new BlobWriteChannelImpl( diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java index d5e2f8de7397..f07c7000813e 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java @@ -1202,7 +1202,7 @@ public void testRetryableException() { .andThrow(new StorageException(500, "InternalError", true)) .andReturn(BLOB_INFO1.toPb()); EasyMock.replay(storageRpcMock); - storage = options.toBuilder().retryParams(RetryParams.getDefaultInstance()).build().service(); + storage = options.toBuilder().retryParams(RetryParams.defaultInstance()).build().service(); BlobInfo readBlob = storage.get(blob); assertEquals(BLOB_INFO1, readBlob); } @@ -1214,7 +1214,7 @@ public void testNonRetryableException() { EasyMock.expect(storageRpcMock.get(blob.toPb(), EMPTY_RPC_OPTIONS)) .andThrow(new StorageException(501, exceptionMessage, false)); EasyMock.replay(storageRpcMock); - storage = options.toBuilder().retryParams(RetryParams.getDefaultInstance()).build().service(); + storage = options.toBuilder().retryParams(RetryParams.defaultInstance()).build().service(); thrown.expect(StorageException.class); thrown.expectMessage(exceptionMessage); storage.get(blob); @@ -1227,7 +1227,7 @@ public void testRuntimeException() { EasyMock.expect(storageRpcMock.get(blob.toPb(), EMPTY_RPC_OPTIONS)) .andThrow(new RuntimeException(exceptionMessage)); EasyMock.replay(storageRpcMock); - storage = options.toBuilder().retryParams(RetryParams.getDefaultInstance()).build().service(); + storage = options.toBuilder().retryParams(RetryParams.defaultInstance()).build().service(); thrown.expect(StorageException.class); thrown.expectMessage(exceptionMessage); storage.get(blob); From b28b3079539e2c1635da8a2e795055c05f2f5a07 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 11 Nov 2015 21:55:39 +0100 Subject: [PATCH 43/48] Make ExceptionHandler conform with our code style --- .../src/main/java/com/google/gcloud/ExceptionHandler.java | 6 +++--- .../src/main/java/com/google/gcloud/RetryHelper.java | 2 +- .../test/java/com/google/gcloud/ExceptionHandlerTest.java | 2 +- .../src/test/java/com/google/gcloud/RetryHelperTest.java | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/ExceptionHandler.java b/gcloud-java-core/src/main/java/com/google/gcloud/ExceptionHandler.java index a0fab3dca566..c1f068594443 100644 --- a/gcloud-java-core/src/main/java/com/google/gcloud/ExceptionHandler.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/ExceptionHandler.java @@ -231,11 +231,11 @@ void verifyCaller(Callable callable) { } } - public Set> getRetriableExceptions() { + public Set> retriableExceptions() { return retriableExceptions; } - public Set> getNonRetriableExceptions() { + public Set> nonRetriableExceptions() { return nonRetriableExceptions; } @@ -262,7 +262,7 @@ boolean shouldRetry(Exception ex) { /** * Returns an instance which retry any checked exception and abort on any runtime exception. */ - public static ExceptionHandler getDefaultInstance() { + public static ExceptionHandler defaultInstance() { return DEFAULT_INSTANCE; } diff --git a/gcloud-java-core/src/main/java/com/google/gcloud/RetryHelper.java b/gcloud-java-core/src/main/java/com/google/gcloud/RetryHelper.java index 90f403758e45..9b9c1f6a3124 100644 --- a/gcloud-java-core/src/main/java/com/google/gcloud/RetryHelper.java +++ b/gcloud-java-core/src/main/java/com/google/gcloud/RetryHelper.java @@ -229,7 +229,7 @@ private static long getExponentialValue(long initialDelay, double backoffFactor, public static V runWithRetries(Callable callable) throws RetryHelperException { return runWithRetries(callable, RetryParams.defaultInstance(), - ExceptionHandler.getDefaultInstance()); + ExceptionHandler.defaultInstance()); } public static V runWithRetries(Callable callable, RetryParams params, diff --git a/gcloud-java-core/src/test/java/com/google/gcloud/ExceptionHandlerTest.java b/gcloud-java-core/src/test/java/com/google/gcloud/ExceptionHandlerTest.java index c182515dbb16..cedc995ddbd0 100644 --- a/gcloud-java-core/src/test/java/com/google/gcloud/ExceptionHandlerTest.java +++ b/gcloud-java-core/src/test/java/com/google/gcloud/ExceptionHandlerTest.java @@ -82,7 +82,7 @@ public Object call() throws Error { } // using default exception handler (retry upon any non-runtime exceptions) - ExceptionHandler handler = ExceptionHandler.getDefaultInstance(); + ExceptionHandler handler = ExceptionHandler.defaultInstance(); assertValidCallable(new A(), handler); assertValidCallable(new B(), handler); assertValidCallable(new C(), handler); diff --git a/gcloud-java-core/src/test/java/com/google/gcloud/RetryHelperTest.java b/gcloud-java-core/src/test/java/com/google/gcloud/RetryHelperTest.java index bf11e744dbbf..9a7cc2104f4a 100644 --- a/gcloud-java-core/src/test/java/com/google/gcloud/RetryHelperTest.java +++ b/gcloud-java-core/src/test/java/com/google/gcloud/RetryHelperTest.java @@ -124,7 +124,7 @@ public void testTriesAtLeastMinTimes() { } return timesCalled; } - }, params, ExceptionHandler.getDefaultInstance()); + }, params, ExceptionHandler.defaultInstance()); assertEquals(timesToFail + 1, attempted); assertNull(RetryHelper.getContext()); } From abc11cea3aedd69e47ae88fa50fd5ad96d16823e Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 11 Nov 2015 23:06:01 +0100 Subject: [PATCH 44/48] Use DatastoreOptions.defaultInstance in site example --- src/site/resources/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/site/resources/index.html b/src/site/resources/index.html index 25c769db2fbf..3ed496b5bbb3 100644 --- a/src/site/resources/index.html +++ b/src/site/resources/index.html @@ -143,7 +143,7 @@

Example: Retrieve Datastore Entries

// Authentication is automatic inside Google Compute Engine // and Google App Engine. -DatastoreOptions options = DatastoreOptions.builder().build(); +DatastoreOptions options = DatastoreOptions.defaultInstance(); Datastore datastore = options.service(); KeyFactory keyFactory = datastore.newKeyFactory().kind(KIND); Key key = keyFactory.newKey(keyName); From 7193d0d02a252f9c8cb0ece901fc6e16e59f5413 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Thu, 12 Nov 2015 07:58:35 +0100 Subject: [PATCH 45/48] More detailed javadoc for BlobInfo --- .../com/google/gcloud/storage/BlobInfo.java | 67 +++++++++++++++---- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobInfo.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobInfo.java index 9662635160e8..65b87498b6cc 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobInfo.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobInfo.java @@ -138,6 +138,8 @@ Builder id(String id) { /** * Sets the blob's data content type. + * + * @see Content-Type */ public Builder contentType(String contentType) { this.contentType = firstNonNull(contentType, Data.nullOf(String.class)); @@ -146,6 +148,8 @@ public Builder contentType(String contentType) { /** * Sets the blob's data content disposition. + * + * @see Content-Disposition */ public Builder contentDisposition(String contentDisposition) { this.contentDisposition = firstNonNull(contentDisposition, Data.nullOf(String.class)); @@ -154,6 +158,8 @@ public Builder contentDisposition(String contentDisposition) { /** * Sets the blob's data content language. + * + * @see Content-Language */ public Builder contentLanguage(String contentLanguage) { this.contentLanguage = firstNonNull(contentLanguage, Data.nullOf(String.class)); @@ -162,6 +168,8 @@ public Builder contentLanguage(String contentLanguage) { /** * Sets the blob's data content encoding. + * + * @see Content-Encoding */ public Builder contentEncoding(String contentEncoding) { this.contentEncoding = firstNonNull(contentEncoding, Data.nullOf(String.class)); @@ -175,6 +183,8 @@ Builder componentCount(Integer componentCount) { /** * Sets the blob's data cache control. + * + * @see Cache-Control */ public Builder cacheControl(String cacheControl) { this.cacheControl = firstNonNull(cacheControl, Data.nullOf(String.class)); @@ -214,6 +224,9 @@ Builder selfLink(String selfLink) { /** * Sets the MD5 hash of blob's data. MD5 value must be encoded in base64. + * + * @see + * Hashes and ETags: Best Practices */ public Builder md5(String md5) { this.md5 = firstNonNull(md5, Data.nullOf(String.class)); @@ -221,8 +234,12 @@ public Builder md5(String md5) { } /** - * Sets the CRC32C checksum of blob's data. CRC32C value must be encoded in base64 in big-endian - * order. + * Sets the CRC32C checksum of blob's data as described in + * RFC 4960, Appendix B; encoded in + * base64 in big-endian order. + * + * @see + * Hashes and ETags: Best Practices */ public Builder crc32c(String crc32c) { this.crc32c = firstNonNull(crc32c, Data.nullOf(String.class)); @@ -235,7 +252,7 @@ Builder mediaLink(String mediaLink) { } /** - * Sets the blob's metadata. + * Sets the blob's user provided metadata. */ public Builder metadata(Map metadata) { this.metadata = metadata != null @@ -326,6 +343,8 @@ public String name() { /** * Returns the blob's data cache control. + * + * @see Cache-Control */ public String cacheControl() { return Data.isNull(cacheControl) ? null : cacheControl; @@ -342,14 +361,16 @@ public List acl() { } /** - * Returns the blob's owner. + * Returns the blob's owner. This will always be the uploader of the blob. */ public Acl.Entity owner() { return owner; } /** - * Returns the blob's data size in bytes. + * Returns the content length of the data in bytes. + * + * @see Content-Length */ public Long size() { return size; @@ -357,6 +378,8 @@ public Long size() { /** * Returns the blob's data content type. + * + * @see Content-Type */ public String contentType() { return Data.isNull(contentType) ? null : contentType; @@ -364,6 +387,8 @@ public String contentType() { /** * Returns the blob's data content encoding. + * + * @see Content-Encoding */ public String contentEncoding() { return Data.isNull(contentEncoding) ? null : contentEncoding; @@ -371,6 +396,8 @@ public String contentEncoding() { /** * Returns the blob's data content disposition. + * + * @see Content-Disposition */ public String contentDisposition() { return Data.isNull(contentDisposition) ? null : contentDisposition; @@ -378,14 +405,18 @@ public String contentDisposition() { /** * Returns the blob's data content language. + * + * @see Content-Language */ public String contentLanguage() { return Data.isNull(contentLanguage) ? null : contentLanguage; } /** - * Returns the number of components that make up this object. Components are accumulated through - * the {@link Storage#compose(Storage.ComposeRequest)} operation. + * Returns the number of components that make up this blob. Components are accumulated through + * the {@link Storage#compose(Storage.ComposeRequest)} operation and are limited to a count of + * 1024, counting 1 for each non-composite component blob and componentCount for each composite + * component blob. This value is set only for composite blobs. * * @see Component Count * Property @@ -395,7 +426,9 @@ public Integer componentCount() { } /** - * Returns blob resource's entity tag. + * Returns HTTP 1.1 Entity tag for the blob. + * + * @see Entity Tags */ public String etag() { return etag; @@ -410,13 +443,21 @@ public String selfLink() { /** * Returns the MD5 hash of blob's data encoded in base64. + * + * @see + * Hashes and ETags: Best Practices */ public String md5() { return Data.isNull(md5) ? null : md5; } /** - * Returns the CRC32C checksum of blob's data encoded in base64 in big-endian order. + * Returns the CRC32C checksum of blob's data as described in + * RFC 4960, Appendix B; encoded in + * base64 in big-endian order. + * + * @see + * Hashes and ETags: Best Practices */ public String crc32c() { return Data.isNull(crc32c) ? null : crc32c; @@ -430,21 +471,23 @@ public String mediaLink() { } /** - * Returns blob's metadata. + * Returns blob's user provided metadata. */ public Map metadata() { return metadata == null || Data.isNull(metadata) ? null : Collections.unmodifiableMap(metadata); } /** - * Returns blob's data generation. + * Returns blob's data generation. Used for blob versioning. */ public Long generation() { return generation; } /** - * Returns blob's metageneration. + * Returns blob's metageneration. Used for preconditions and for detecting changes in metadata. + * A metageneration number is only meaningful in the context of a particular generation of a + * particular blob. */ public Long metageneration() { return metageneration; From 5f9eaa4cab417c161b436bb5c5da4046b056b3e6 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Thu, 12 Nov 2015 07:59:38 +0100 Subject: [PATCH 46/48] Better javadoc for (Bucket/Blob)ListOptions.prefix --- .../src/main/java/com/google/gcloud/storage/Storage.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java index 128099b7eab3..2e95e69aa445 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java @@ -594,7 +594,8 @@ public static BucketListOption startPageToken(String pageToken) { } /** - * Returns an option to set a prefix for listed buckets names. + * Returns an option to set a prefix to filter results to buckets whose names begin with this + * prefix. */ public static BucketListOption prefix(String prefix) { return new BucketListOption(StorageRpc.Option.PREFIX, prefix); @@ -639,7 +640,8 @@ public static BlobListOption startPageToken(String pageToken) { } /** - * Returns an option to set a prefix for listed blobs names. + * Returns an option to set a prefix to filter results to blobs whose names begin with this + * prefix. */ public static BlobListOption prefix(String prefix) { return new BlobListOption(StorageRpc.Option.PREFIX, prefix); From b8defb8e585468e0b95142080248a9f00be87c18 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Thu, 12 Nov 2015 07:30:55 +0100 Subject: [PATCH 47/48] Better javadoc for BucketInfo --- .../com/google/gcloud/storage/BucketInfo.java | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BucketInfo.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BucketInfo.java index 3f21f74dcd66..b40e023cc47e 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BucketInfo.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BucketInfo.java @@ -300,7 +300,7 @@ public static class IsLiveDeleteRule extends DeleteRule { * Creates an {@code IsLiveDeleteRule} object. * * @param isLive if set to {@code true} live blobs meet the delete condition. If set to - * {@code false} delete condition is met by archived objects. + * {@code false} delete condition is met by archived blobs. */ public IsLiveDeleteRule(boolean isLive) { super(Type.IS_LIVE); @@ -362,7 +362,8 @@ Builder selfLink(String selfLink) { } /** - * Sets whether blob versioning should be enabled or not for the bucket. + * Sets whether versioning should be enabled for this bucket. When set to true, versioning is + * fully enabled. */ public Builder versioningEnabled(Boolean enable) { this.versioningEnabled = firstNonNull(enable, Data.nullOf(Boolean.class)); @@ -370,7 +371,8 @@ public Builder versioningEnabled(Boolean enable) { } /** - * Sets the bucket's website index page. + * Sets the bucket's website index page. Behaves as the bucket's directory index where missing + * blobs are treated as potential directories. */ public Builder indexPage(String indexPage) { this.indexPage = indexPage; @@ -378,7 +380,7 @@ public Builder indexPage(String indexPage) { } /** - * Sets the bucket's website page to return when a resource is not found. + * Sets the custom object to return when a requested resource is not found. */ public Builder notFoundPage(String notFoundPage) { this.notFoundPage = notFoundPage; @@ -386,7 +388,7 @@ public Builder notFoundPage(String notFoundPage) { } /** - * Sets bucket's delete rules. + * Sets the bucket's lifecycle configuration as a number of delete rules. * * @see Lifecycle Management */ @@ -396,10 +398,9 @@ public Builder deleteRules(Iterable rules) { } /** - * Sets the bucket's storage class. A list of supported values is available - * here. - * - * @see Storage Classes + * Sets the bucket's storage class. This defines how blobs in the bucket are stored and + * determines the SLA and the cost of storage. A list of supported values is available + * here. */ public Builder storageClass(String storageClass) { this.storageClass = storageClass; @@ -407,7 +408,8 @@ public Builder storageClass(String storageClass) { } /** - * Sets the bucket's location. A list of supported values is available + * Sets the bucket's location. Data for blobs in the bucket resides in physical storage within + * this region. A list of supported values is available * here. */ public Builder location(String location) { @@ -507,7 +509,7 @@ public String name() { } /** - * Returns the bucket's owner. + * Returns the bucket's owner. This is always the project team's owner group. */ public Entity owner() { return owner; @@ -521,35 +523,40 @@ public String selfLink() { } /** - * Returns {@code true} if blob versioning is enabled for this bucket, {@code false} otherwise. + * Returns {@code true} if versioning is fully enabled for this bucket, {@code false} otherwise. */ public Boolean versioningEnabled() { return Data.isNull(versioningEnabled) ? null : versioningEnabled; } /** - * Returns bucket's website index page. + * Returns bucket's website index page. Behaves as the bucket's directory index where missing + * blobs are treated as potential directories. */ public String indexPage() { return indexPage; } /** - * Returns bucket's website not found page, used we a resource could not be found. + * Returns the custom object to return when a requested resource is not found. */ public String notFoundPage() { return notFoundPage; } /** - * Returns bucket's delete rules. + * Returns bucket's lifecycle configuration as a number of delete rules. + * + * @see Lifecycle Management */ public List deleteRules() { return deleteRules; } /** - * Returns bucket resource's entity tag. + * Returns HTTP 1.1 Entity tag for the bucket. + * + * @see Entity Tags */ public String etag() { return etag; @@ -570,7 +577,8 @@ public Long metageneration() { } /** - * Returns the bucket's location. + * Returns the bucket's location. Data for blobs in the bucket resides in physical storage within + * this region. * * @see Bucket Locations */ @@ -579,7 +587,8 @@ public String location() { } /** - * Returns the bucket's storage class. + * Returns the bucket's storage class. This defines how blobs in the bucket are stored and + * determines the SLA and the cost of storage. * * @see Storage Classes */ @@ -589,6 +598,9 @@ public String storageClass() { /** * Returns the bucket's Cross-Origin Resource Sharing (CORS) configuration. + * + * @see + * Cross-Origin Resource Sharing (CORS) */ public List cors() { return cors; From da0ea589ff5362b261e92d1b755a16699abacd42 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Thu, 12 Nov 2015 07:34:54 +0100 Subject: [PATCH 48/48] Removed unused import from BucketInfo --- .../src/main/java/com/google/gcloud/storage/BucketInfo.java | 1 - 1 file changed, 1 deletion(-) diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BucketInfo.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BucketInfo.java index b40e023cc47e..d5a382446709 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BucketInfo.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/BucketInfo.java @@ -33,7 +33,6 @@ import com.google.common.base.Function; import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.google.gcloud.storage.Acl.Entity; import java.io.IOException;