JCLOUDS-458: Added Blobstore Abstraction
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/commit/ccc2d243 Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/tree/ccc2d243 Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/diff/ccc2d243 Branch: refs/heads/1.8.x Commit: ccc2d243a17648fedd724e27725cd9cf58db7883 Parents: d97a0c4 Author: hsbhathiya <[email protected]> Authored: Tue Sep 2 01:46:54 2014 +0530 Committer: Andrew Gaul <[email protected]> Committed: Wed Sep 10 15:04:42 2014 -0700 ---------------------------------------------------------------------- .../GoogleCloudStorageApiMetadata.java | 27 +- .../blobstore/GCSAsyncBlobStore.java | 289 +++++++++++++++++++ .../blobstore/GCSBlobStore.java | 273 ++++++++++++++++++ .../config/GCSBlobStoreContextModule.java | 35 +++ .../functions/BlobMetadataToObjectTemplate.java | 57 ++++ ...ListContainerOptionsToListObjectOptions.java | 50 ++++ .../functions/BucketToStorageMetadata.java | 47 +++ .../functions/ObjectListToStorageMetadata.java | 65 +++++ .../functions/ObjectToBlobMetadata.java | 79 +++++ .../internal/MultipartNamingStrategy.java | 30 ++ .../strategy/internal/MultipartUpload.java | 36 +++ .../MultipartUploadSlicingAlgorithm.java | 138 +++++++++ .../internal/MultipartUploadStrategy.java | 26 ++ .../SequentialMultipartUploadStrategy.java | 106 +++++++ .../config/GoogleCloudStorageHttpApiModule.java | 41 +++ .../googlecloudstorage/config/UserProject.java | 33 +++ .../googlecloudstorage/domain/Bucket.java | 4 +- .../domain/BucketAccessControls.java | 2 +- .../domain/DefaultObjectAccessControls.java | 2 +- .../domain/DomainResourceReferences.java | 105 +++++++ .../domain/DomainResourceRefferences.java | 105 ------- .../googlecloudstorage/domain/GCSObject.java | 17 +- .../domain/ObjectAccessControls.java | 2 +- .../domain/templates/BucketTemplate.java | 4 +- .../DefaultObjectAccessControlsTemplate.java | 2 +- .../templates/ObjectAccessControlsTemplate.java | 2 +- .../domain/templates/ObjectTemplate.java | 14 +- .../fallback/GCSFallbacks.java | 39 +++ .../googlecloudstorage/features/BucketApi.java | 30 +- .../DefaultObjectAccessControlsApi.java | 2 +- .../googlecloudstorage/features/ObjectApi.java | 4 + .../options/ComposeObjectOptions.java | 2 +- .../options/CopyObjectOptions.java | 4 +- .../options/DeleteObjectOptions.java | 2 +- .../options/GetBucketOptions.java | 2 +- .../options/GetObjectOptions.java | 2 +- .../options/InsertBucketOptions.java | 4 +- .../options/InsertObjectOptions.java | 4 +- .../options/ListObjectOptions.java | 2 +- .../googlecloudstorage/options/ListOptions.java | 2 +- .../options/UpdateBucketOptions.java | 4 +- .../options/UpdateObjectOptions.java | 4 +- .../reference/GoogleCloudStorageConstants.java | 7 + .../integration/GCSBlobIntegrationLiveTest.java | 260 +++++++++++++++++ .../blobstore/integration/GCSBlobLiveTest.java | 108 +++++++ .../GCSContainerIntegrationLiveTest.java | 97 +++++++ .../integration/GCSContainerLiveTest.java | 28 ++ .../BucketAccessControlsApiExpectTest.java | 2 +- .../BucketAccessControlsApiLiveTest.java | 2 +- .../features/BucketApiExpectTest.java | 4 +- .../features/BucketApiLiveTest.java | 25 +- ...efaultObjectAccessControlsApiExpectTest.java | 2 +- .../DefaultObjectAccessControlsApiLiveTest.java | 2 +- .../ObjectAccessControlsApiExpectTest.java | 2 +- .../features/ObjectApiLiveTest.java | 6 +- .../features/ResumableUploadApiLiveTest.java | 2 +- .../parse/BucketAclGetTest.java | 2 +- .../parse/BucketAclInsertTest.java | 2 +- .../parse/BucketAclListTest.java | 2 +- .../parse/BucketAclUpdateTest.java | 2 +- .../parse/BucketUpdateTest.java | 4 +- .../parse/DefaultObjectAclGetTest.java | 2 +- .../parse/DefaultObjectAclInsertTest.java | 2 +- .../parse/DefaultObjectAclListTest.java | 2 +- .../parse/FullBucketGetTest.java | 8 +- .../parse/NoAclBucketListTest.java | 4 +- .../parse/NoAclBucketTest.java | 4 +- .../parse/ObjectAclGetTest.java | 2 +- .../parse/ObjectAclInsertTest.java | 2 +- .../parse/ObjectAclListTest.java | 2 +- .../parse/ObjectAclUpdateTest.java | 2 +- 71 files changed, 2086 insertions(+), 201 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadata.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadata.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadata.java index 741088c..f88541c 100644 --- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadata.java +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadata.java @@ -26,7 +26,9 @@ import static org.jclouds.reflect.Reflection2.typeToken; import java.net.URI; import java.util.Properties; + import org.jclouds.blobstore.BlobStoreContext; +import org.jclouds.googlecloudstorage.blobstore.config.GCSBlobStoreContextModule; import org.jclouds.googlecloudstorage.config.GoogleCloudStorageHttpApiModule; import org.jclouds.googlecloudstorage.config.GoogleCloudStorageParserModule; import org.jclouds.googlecloudstorage.config.OAuthModuleWithoutTypeAdapters; @@ -65,18 +67,19 @@ public class GoogleCloudStorageApiMetadata extends BaseHttpApiMetadata<GoogleClo public static class Builder extends BaseHttpApiMetadata.Builder<GoogleCloudStorageApi, Builder> { protected Builder() { id(GCS_PROVIDER_NAME) - .name("Google Cloud Storage Api ") - .identityName("Email associated with the Google API client_id") - .credentialName("Private key literal associated with the Google API client_id") - .documentation(URI.create("https://developers.google.com/storage/docs/json_api")) - .version("v1") - .defaultEndpoint("https://www.googleapis.com") - .defaultProperties(GoogleCloudStorageApiMetadata.defaultProperties()) - .view(typeToken(BlobStoreContext.class)) - .defaultModules( - ImmutableSet.<Class<? extends Module>> builder().add(GoogleCloudStorageParserModule.class) - .add(OAuthAuthenticationModule.class).add(OAuthModuleWithoutTypeAdapters.class) - .add(GoogleCloudStorageHttpApiModule.class).build()); + .name("Google Cloud Storage Api ") + .identityName("Email associated with the Google API client_id") + .credentialName("Private key literal associated with the Google API client_id") + .documentation(URI.create("https://developers.google.com/storage/docs/json_api")) + .version("v1") + .defaultEndpoint("https://www.googleapis.com") + .defaultProperties(GoogleCloudStorageApiMetadata.defaultProperties()) + .view(typeToken(BlobStoreContext.class)) + .defaultModules( + ImmutableSet.<Class<? extends Module>> of(GoogleCloudStorageParserModule.class, + OAuthAuthenticationModule.class, OAuthModuleWithoutTypeAdapters.class, + GoogleCloudStorageHttpApiModule.class, GCSBlobStoreContextModule.class)); + } @Override http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GCSAsyncBlobStore.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GCSAsyncBlobStore.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GCSAsyncBlobStore.java new file mode 100644 index 0000000..955cf9b --- /dev/null +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GCSAsyncBlobStore.java @@ -0,0 +1,289 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.blobstore; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.Constants.PROPERTY_USER_THREADS; + +import java.util.Set; +import java.util.concurrent.Callable; + +import javax.inject.Singleton; + +import org.jclouds.blobstore.AsyncBlobStore; +import org.jclouds.blobstore.BlobStore; +import org.jclouds.blobstore.BlobStoreContext; +import org.jclouds.blobstore.domain.Blob; +import org.jclouds.blobstore.domain.BlobBuilder; +import org.jclouds.blobstore.domain.BlobMetadata; +import org.jclouds.blobstore.domain.PageSet; +import org.jclouds.blobstore.domain.StorageMetadata; +import org.jclouds.blobstore.options.CreateContainerOptions; +import org.jclouds.blobstore.options.GetOptions; +import org.jclouds.blobstore.options.ListContainerOptions; +import org.jclouds.blobstore.options.PutOptions; +import org.jclouds.domain.Location; + +import com.google.common.collect.ForwardingObject; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.inject.Inject; +import com.google.inject.name.Named; + +@SuppressWarnings("deprecation") +@Singleton +public class GCSAsyncBlobStore extends ForwardingObject implements AsyncBlobStore { + private final BlobStore blobstore; + private final ListeningExecutorService executor; + + @Inject + public GCSAsyncBlobStore(BlobStore blobstore, @Named(PROPERTY_USER_THREADS) ListeningExecutorService executor) { + this.blobstore = checkNotNull(blobstore, "blobstore"); + this.executor = checkNotNull(executor, "executor"); + } + + @Override + public BlobStoreContext getContext() { + return delegate().getContext(); + } + + @Override + public BlobBuilder blobBuilder(String name) { + return delegate().blobBuilder(name); + } + + @Override + public ListenableFuture<Set<? extends Location>> listAssignableLocations() { + return executor.submit(new Callable<Set<? extends Location>>() { + public Set<? extends Location> call() { + return delegate().listAssignableLocations(); + } + }); + } + + @Override + public ListenableFuture<PageSet<? extends StorageMetadata>> list() { + return executor.submit(new Callable<PageSet<? extends StorageMetadata>>() { + public PageSet<? extends StorageMetadata> call() { + return delegate().list(); + } + }); + } + + @Override + public ListenableFuture<Boolean> containerExists(final String container) { + return executor.submit(new Callable<Boolean>() { + public Boolean call() { + return delegate().containerExists(container); + } + }); + } + + @Override + public ListenableFuture<Boolean> createContainerInLocation(final Location location, final String container) { + return executor.submit(new Callable<Boolean>() { + public Boolean call() { + return delegate().createContainerInLocation(location, container); + } + }); + } + + @Override + public ListenableFuture<Boolean> createContainerInLocation(final Location location, final String container, + final CreateContainerOptions options) { + return executor.submit(new Callable<Boolean>() { + public Boolean call() { + return delegate().createContainerInLocation(location, container, options); + } + }); + } + + @Override + public ListenableFuture<PageSet<? extends StorageMetadata>> list(final String container) { + return executor.submit(new Callable<PageSet<? extends StorageMetadata>>() { + public PageSet<? extends StorageMetadata> call() { + return delegate().list(container); + } + }); + + } + + @Override + public ListenableFuture<PageSet<? extends StorageMetadata>> list(final String container, + final ListContainerOptions options) { + return executor.submit(new Callable<PageSet<? extends StorageMetadata>>() { + public PageSet<? extends StorageMetadata> call() { + return delegate().list(container, options); + } + }); + } + + @Override + public ListenableFuture<Void> clearContainer(final String container) { + return executor.submit(new Callable<Void>() { + public Void call() { + delegate().clearContainer(container); + return null; + } + }); + } + + @Override + public ListenableFuture<Void> clearContainer(final String container, final ListContainerOptions options) { + return executor.submit(new Callable<Void>() { + public Void call() { + delegate().clearContainer(container, options); + return null; + } + }); + } + + @Override + public ListenableFuture<Void> deleteContainer(final String container) { + return executor.submit(new Callable<Void>() { + public Void call() { + delegate().deleteContainer(container); + return null; + } + }); + } + + @Override + public ListenableFuture<Boolean> deleteContainerIfEmpty(final String container) { + return executor.submit(new Callable<Boolean>() { + public Boolean call() { + return delegate().deleteContainerIfEmpty(container); + } + }); + } + + @Override + public ListenableFuture<Boolean> directoryExists(final String container, final String directory) { + return executor.submit(new Callable<Boolean>() { + public Boolean call() { + return delegate().directoryExists(container, directory); + } + }); + } + + @Override + public ListenableFuture<Void> createDirectory(final String container, final String directory) { + return executor.submit(new Callable<Void>() { + public Void call() { + delegate().createDirectory(container, directory); + return null; + } + }); + } + + @Override + public ListenableFuture<Void> deleteDirectory(final String containerName, final String name) { + return executor.submit(new Callable<Void>() { + public Void call() { + delegate().deleteDirectory(containerName, name); + return null; + } + }); + } + + @Override + public ListenableFuture<Boolean> blobExists(final String container, final String name) { + return executor.submit(new Callable<Boolean>() { + public Boolean call() { + return delegate().blobExists(container, name); + } + }); + } + + @Override + public ListenableFuture<String> putBlob(final String container, final Blob blob) { + return executor.submit(new Callable<String>() { + public String call() { + return delegate().putBlob(container, blob); + } + }); + } + + @Override + public ListenableFuture<String> putBlob(final String container, final Blob blob, final PutOptions options) { + return executor.submit(new Callable<String>() { + public String call() { + return delegate().putBlob(container, blob, options); + } + }); + } + + @Override + public ListenableFuture<BlobMetadata> blobMetadata(final String container, final String key) { + return executor.submit(new Callable<BlobMetadata>() { + public BlobMetadata call() { + return delegate().blobMetadata(container, key); + } + }); + } + + @Override + public ListenableFuture<Blob> getBlob(final String container, final String key) { + return executor.submit(new Callable<Blob>() { + public Blob call() { + return delegate().getBlob(container, key); + } + }); + } + + @Override + public ListenableFuture<Blob> getBlob(final String container, final String key, final GetOptions options) { + return executor.submit(new Callable<Blob>() { + public Blob call() { + return delegate().getBlob(container, key, options); + } + }); + } + + @Override + public ListenableFuture<Void> removeBlob(final String container, final String key) { + return executor.submit(new Callable<Void>() { + public Void call() { + delegate().removeBlob(container, key); + return null; + } + }); + } + + @Override + public ListenableFuture<Long> countBlobs(final String container) { + return executor.submit(new Callable<Long>() { + public Long call() { + return delegate().countBlobs(container); + } + }); + } + + @Override + public ListenableFuture<Long> countBlobs(final String container, final ListContainerOptions options) { + return executor.submit(new Callable<Long>() { + public Long call() { + return delegate().countBlobs(container, options); + } + }); + } + + @Override + protected BlobStore delegate() { + return blobstore; + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GCSBlobStore.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GCSBlobStore.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GCSBlobStore.java new file mode 100644 index 0000000..e0d433c --- /dev/null +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GCSBlobStore.java @@ -0,0 +1,273 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.blobstore; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Set; + +import javax.inject.Singleton; + +import org.jclouds.blobstore.BlobStoreContext; +import org.jclouds.blobstore.domain.Blob; +import org.jclouds.blobstore.domain.BlobMetadata; +import org.jclouds.blobstore.domain.PageSet; +import org.jclouds.blobstore.domain.StorageMetadata; +import org.jclouds.blobstore.domain.internal.BlobBuilderImpl; +import org.jclouds.blobstore.domain.internal.PageSetImpl; +import org.jclouds.blobstore.internal.BaseBlobStore; +import org.jclouds.blobstore.options.CreateContainerOptions; +import org.jclouds.blobstore.options.ListContainerOptions; +import org.jclouds.blobstore.options.PutOptions; +import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata; +import org.jclouds.blobstore.util.BlobUtils; +import org.jclouds.collect.Memoized; +import org.jclouds.domain.Location; +import org.jclouds.googlecloudstorage.GoogleCloudStorageApi; +import org.jclouds.googlecloudstorage.blobstore.functions.BlobMetadataToObjectTemplate; +import org.jclouds.googlecloudstorage.blobstore.functions.BlobStoreListContainerOptionsToListObjectOptions; +import org.jclouds.googlecloudstorage.blobstore.functions.BucketToStorageMetadata; +import org.jclouds.googlecloudstorage.blobstore.functions.ObjectListToStorageMetadata; +import org.jclouds.googlecloudstorage.blobstore.functions.ObjectToBlobMetadata; +import org.jclouds.googlecloudstorage.blobstore.strategy.internal.MultipartUploadStrategy; +import org.jclouds.googlecloudstorage.config.UserProject; +import org.jclouds.googlecloudstorage.domain.Bucket; +import org.jclouds.googlecloudstorage.domain.DomainResourceReferences.ObjectRole; +import org.jclouds.googlecloudstorage.domain.GCSObject; +import org.jclouds.googlecloudstorage.domain.ListPage; +import org.jclouds.googlecloudstorage.domain.templates.BucketTemplate; +import org.jclouds.googlecloudstorage.domain.templates.DefaultObjectAccessControlsTemplate; +import org.jclouds.googlecloudstorage.domain.templates.ObjectTemplate; +import org.jclouds.googlecloudstorage.options.ListObjectOptions; +import org.jclouds.http.HttpResponseException; +import org.jclouds.http.internal.PayloadEnclosingImpl; + +import com.google.common.base.Charsets; +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import com.google.common.collect.Iterables; +import com.google.common.hash.HashCode; +import com.google.inject.Inject; +import com.google.inject.Provider; + +@Singleton +public class GCSBlobStore extends BaseBlobStore { + + GoogleCloudStorageApi api; + BucketToStorageMetadata bucketToStorageMetadata; + ObjectToBlobMetadata objectToBlobMetadata; + ObjectListToStorageMetadata objectListToStorageMetadata; + Provider<FetchBlobMetadata> fetchBlobMetadataProvider; + BlobMetadataToObjectTemplate blobMetadataToObjectTemplate; + BlobStoreListContainerOptionsToListObjectOptions listContainerOptionsToListObjectOptions; + MultipartUploadStrategy multipartUploadStrategy; + Supplier<String> projectId; + + @Inject + protected GCSBlobStore(BlobStoreContext context, BlobUtils blobUtils, Supplier<Location> defaultLocation, + @Memoized Supplier<Set<? extends Location>> locations, GoogleCloudStorageApi api, + BucketToStorageMetadata bucketToStorageMetadata, ObjectToBlobMetadata objectToBlobMetadata, + ObjectListToStorageMetadata objectListToStorageMetadata, + Provider<FetchBlobMetadata> fetchBlobMetadataProvider, + BlobMetadataToObjectTemplate blobMetadataToObjectTemplate, + BlobStoreListContainerOptionsToListObjectOptions listContainerOptionsToListObjectOptions, + MultipartUploadStrategy multipartUploadStrategy, @UserProject Supplier<String> projectId) { + super(context, blobUtils, defaultLocation, locations); + this.api = api; + this.bucketToStorageMetadata = bucketToStorageMetadata; + this.objectToBlobMetadata = objectToBlobMetadata; + this.objectListToStorageMetadata = objectListToStorageMetadata; + this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider, "fetchBlobMetadataProvider"); + this.blobMetadataToObjectTemplate = blobMetadataToObjectTemplate; + this.listContainerOptionsToListObjectOptions = listContainerOptionsToListObjectOptions; + this.projectId = projectId; + this.multipartUploadStrategy = multipartUploadStrategy; + } + + @Override + public PageSet<? extends StorageMetadata> list() { + return new Function<ListPage<Bucket>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() { + public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(ListPage<Bucket> from) { + return new PageSetImpl<StorageMetadata>(Iterables.transform(from, bucketToStorageMetadata), null); + } + }.apply(api.getBucketApi().listBucket(projectId.get())); + } + + @Override + public boolean containerExists(String container) { + return api.getBucketApi().bucketExist(container); + } + + @Override + public boolean createContainerInLocation(Location location, String container) { + BucketTemplate template = new BucketTemplate().name(container); + if (location != null) { + org.jclouds.googlecloudstorage.domain.DomainResourceReferences.Location gcsLocation = org.jclouds.googlecloudstorage.domain.DomainResourceReferences.Location + .fromValue(location.getId()); + template = template.location(gcsLocation); + } + return api.getBucketApi().createBucket(projectId.get(), template) != null; + } + + @Override + public boolean createContainerInLocation(Location location, String container, CreateContainerOptions options) { + BucketTemplate template = new BucketTemplate().name(container); + if (location != null) { + org.jclouds.googlecloudstorage.domain.DomainResourceReferences.Location gcsLocation = org.jclouds.googlecloudstorage.domain.DomainResourceReferences.Location + .fromValue(location.getId()); + template = template.location(gcsLocation); + } + Bucket bucket = api.getBucketApi().createBucket(projectId.get(), template); + if (options.isPublicRead()) { + try { + DefaultObjectAccessControlsTemplate doAclTemplate = new DefaultObjectAccessControlsTemplate().entity( + "allUsers").role(ObjectRole.READER); + api.getDefaultObjectAccessControlsApi().createDefaultObjectAccessControls(container, doAclTemplate); + } catch (HttpResponseException e) { + // If DefaultObjectAccessControls operation fail, Reverse create operation the operation. + api.getBucketApi().deleteBucket(container); + return false; + } + } + + return bucket != null; + } + + /** Returns list of of all the objects */ + @Override + public PageSet<? extends StorageMetadata> list(String container) { + ListPage<GCSObject> gcsList = api.getObjectApi().listObjects(container); + PageSet<? extends StorageMetadata> list = objectListToStorageMetadata.apply(gcsList); + return list; + } + + @Override + public PageSet<? extends StorageMetadata> list(String container, ListContainerOptions options) { + + if (options != null && options != ListContainerOptions.NONE) { + ListObjectOptions listOptions = listContainerOptionsToListObjectOptions.apply(options); + ListPage<GCSObject> gcsList = api.getObjectApi().listObjects(container, listOptions); + PageSet<? extends StorageMetadata> list = objectListToStorageMetadata.apply(gcsList); + return options.isDetailed() ? fetchBlobMetadataProvider.get().setContainerName(container).apply(list) : list; + } else { + return list(container); + } + } + + /** + * Checks whether an accessible object is available. Google cloud storage does not support directly support + * BucketExist or ObjectExist operations + */ + @Override + public boolean blobExists(String container, String name) { + try { + String urlName = name.contains("/") ? URLEncoder.encode(name, Charsets.UTF_8.toString()) : name; + return api.getObjectApi().objectExist(container, urlName); + } catch (UnsupportedEncodingException e) { + throw Throwables.propagate(e); + } + } + + /** + * This supports multipart/related upload which has exactly 2 parts, media-part and metadata-part + */ + @Override + public String putBlob(String container, Blob blob) { + checkNotNull(blob.getPayload().getContentMetadata().getContentLength()); + HashCode md5 = blob.getMetadata().getContentMetadata().getContentMD5AsHashCode(); + + ObjectTemplate template = blobMetadataToObjectTemplate.apply(blob.getMetadata()); + + if (md5 != null) { + template.md5Hash(md5); + } + return api.getObjectApi().multipartUpload(container, template, blob.getPayload()).getEtag(); + } + + @Override + public String putBlob(String container, Blob blob, PutOptions options) { + if (options.multipart().isMultipart()) { + return multipartUploadStrategy.execute(container, blob); + } else { + return putBlob(container, blob); + } + } + + @Override + public BlobMetadata blobMetadata(String container, String name) { + return objectToBlobMetadata.apply(api.getObjectApi().getObject(container, name)); + } + + @Override + public Blob getBlob(String container, String name, org.jclouds.blobstore.options.GetOptions options) { + PayloadEnclosingImpl impl = api.getObjectApi().download(container, name); + + GCSObject gcsObject = api.getObjectApi().getObject(container, name); + if (gcsObject == null) { + return null; + } + Blob blob = new BlobBuilderImpl().payload(impl.getPayload()).payload(impl.getPayload()) + .contentType(gcsObject.getContentType()).contentDisposition(gcsObject.getContentDisposition()) + .contentEncoding(gcsObject.getContentEncoding()).contentLanguage(gcsObject.getContentLanguage()) + .contentLength(gcsObject.getSize()).contentMD5(gcsObject.getMd5HashCode()).name(gcsObject.getName()) + .userMetadata(gcsObject.getAllMetadata()).build(); + blob.getMetadata().setContainer(container); + blob.getMetadata().setLastModified(gcsObject.getUpdated()); + blob.getMetadata().setETag(gcsObject.getEtag()); + blob.getMetadata().setPublicUri(gcsObject.getMediaLink()); + blob.getMetadata().setUserMetadata(gcsObject.getAllMetadata()); + blob.getMetadata().setUri(gcsObject.getSelfLink()); + blob.getMetadata().setId(gcsObject.getId()); + return blob; + } + + @Override + public void removeBlob(String container, String name) { + String urlName; + try { + urlName = name.contains("/") ? URLEncoder.encode(name, Charsets.UTF_8.toString()) : name; + } catch (UnsupportedEncodingException uee) { + throw Throwables.propagate(uee); + } + api.getObjectApi().deleteObject(container, urlName); + } + + @Override + protected boolean deleteAndVerifyContainerGone(String container) { + ListPage<GCSObject> list = api.getObjectApi().listObjects(container); + if (list == null) { + return api.getBucketApi().deleteBucket(container); + } + if (!list.iterator().hasNext() && list.getPrefixes().isEmpty()) + return api.getBucketApi().deleteBucket(container); + + return false; + } + + public Set<String> listPrefixes(String container, ListContainerOptions options) { + ListObjectOptions gcsOptions = listContainerOptionsToListObjectOptions.apply(options); + Set<String> prefixes = api.getObjectApi().listObjects(container, gcsOptions).getPrefixes(); + return prefixes; + } + + public Set<String> listPrefixes(String container) { + return listPrefixes(container, ListContainerOptions.NONE); + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/config/GCSBlobStoreContextModule.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/config/GCSBlobStoreContextModule.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/config/GCSBlobStoreContextModule.java new file mode 100644 index 0000000..f10cadc --- /dev/null +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/config/GCSBlobStoreContextModule.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.blobstore.config; + +import org.jclouds.blobstore.AsyncBlobStore; +import org.jclouds.blobstore.BlobStore; +import org.jclouds.blobstore.attr.ConsistencyModel; +import org.jclouds.googlecloudstorage.blobstore.GCSAsyncBlobStore; +import org.jclouds.googlecloudstorage.blobstore.GCSBlobStore; +import com.google.inject.AbstractModule; +import com.google.inject.Scopes; + +public class GCSBlobStoreContextModule extends AbstractModule { + + @Override + protected void configure() { + bind(ConsistencyModel.class).toInstance(ConsistencyModel.EVENTUAL); + bind(BlobStore.class).to(GCSBlobStore.class).in(Scopes.SINGLETON); + bind(AsyncBlobStore.class).to(GCSAsyncBlobStore.class).in(Scopes.SINGLETON); + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/BlobMetadataToObjectTemplate.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/BlobMetadataToObjectTemplate.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/BlobMetadataToObjectTemplate.java new file mode 100644 index 0000000..d604f7c --- /dev/null +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/BlobMetadataToObjectTemplate.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.blobstore.functions; + +import java.util.Map; + +import javax.inject.Singleton; + +import org.jclouds.blobstore.domain.BlobMetadata; +import org.jclouds.googlecloudstorage.domain.templates.ObjectTemplate; +import org.jclouds.io.ContentMetadata; + +import com.google.common.base.Function; +import com.google.common.hash.HashCode; + +@Singleton +public class BlobMetadataToObjectTemplate implements Function<BlobMetadata, ObjectTemplate> { + + public ObjectTemplate apply(BlobMetadata from) { + if (from == null) + return null; + + String name = from.getName(); + Map<String, String> userMeta = from.getUserMetadata(); + + ContentMetadata metadata = from.getContentMetadata(); + String contentDisposition = metadata.getContentDisposition(); + String contentEncoding = metadata.getContentEncoding(); + String contentLanguage = metadata.getContentLanguage(); + String contentType = metadata.getContentType(); + Long contentLength = metadata.getContentLength(); + + HashCode md5 = metadata.getContentMD5AsHashCode(); + + ObjectTemplate template = new ObjectTemplate().contentType(contentType).size(contentLength) + .contentEncoding(contentEncoding).contentLanguage(contentLanguage) + .contentDisposition(contentDisposition).name(name).customMetadata(userMeta); + if (md5 != null) { + template.md5Hash(md5); + } + return template; + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/BlobStoreListContainerOptionsToListObjectOptions.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/BlobStoreListContainerOptionsToListObjectOptions.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/BlobStoreListContainerOptionsToListObjectOptions.java new file mode 100644 index 0000000..d4f8ef1 --- /dev/null +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/BlobStoreListContainerOptionsToListObjectOptions.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.blobstore.functions; + +import org.jclouds.blobstore.options.ListContainerOptions; +import org.jclouds.googlecloudstorage.options.ListObjectOptions; + +import com.google.common.base.Function; +import com.google.inject.Singleton; +import static com.google.common.base.Preconditions.checkNotNull; + +@Singleton +public class BlobStoreListContainerOptionsToListObjectOptions implements + Function<ListContainerOptions, ListObjectOptions> { + public ListObjectOptions apply(ListContainerOptions from) { + checkNotNull(from, "set options to instance NONE instead of passing null"); + ListObjectOptions httpOptions = new ListObjectOptions(); + + if (!from.isRecursive()) { + httpOptions = httpOptions.delimiter("/"); + } + if (from.getDir() != null) { + String path = from.getDir(); + if (!path.endsWith("/")) + path += "/"; + httpOptions = httpOptions.prefix(path); + } + if (from.getMarker() != null) { + httpOptions = httpOptions.pageToken(from.getMarker()); + } + if (from.getMaxResults() != null) { + httpOptions = httpOptions.maxResults(from.getMaxResults()); + } + return httpOptions; + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/BucketToStorageMetadata.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/BucketToStorageMetadata.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/BucketToStorageMetadata.java new file mode 100644 index 0000000..e402c6b --- /dev/null +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/BucketToStorageMetadata.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.blobstore.functions; + +import org.jclouds.blobstore.domain.MutableStorageMetadata; +import org.jclouds.blobstore.domain.StorageMetadata; +import org.jclouds.blobstore.domain.StorageType; +import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl; +import org.jclouds.domain.Location; +import org.jclouds.googlecloudstorage.domain.Bucket; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.inject.Inject; +import com.google.inject.Singleton; + +@Singleton +public class BucketToStorageMetadata implements Function<Bucket, StorageMetadata> { + private Supplier<Location> defaultLocation; + + @Inject + BucketToStorageMetadata(Supplier<Location> defaultLocation) { + this.defaultLocation = defaultLocation; + } + + public StorageMetadata apply(Bucket from) { + MutableStorageMetadata to = new MutableStorageMetadataImpl(); + to.setName(from.getName()); + to.setLocation(defaultLocation.get()); + to.setType(StorageType.CONTAINER); + return to; + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/ObjectListToStorageMetadata.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/ObjectListToStorageMetadata.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/ObjectListToStorageMetadata.java new file mode 100644 index 0000000..341e44e --- /dev/null +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/ObjectListToStorageMetadata.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.blobstore.functions; + +import java.util.Map; +import org.jclouds.blobstore.domain.BlobMetadata; +import org.jclouds.blobstore.domain.PageSet; +import org.jclouds.blobstore.domain.StorageMetadata; +import org.jclouds.blobstore.domain.StorageType; +import org.jclouds.blobstore.domain.internal.PageSetImpl; +import org.jclouds.blobstore.domain.internal.StorageMetadataImpl; +import org.jclouds.googlecloudstorage.domain.GCSObject; +import org.jclouds.googlecloudstorage.domain.ListPage; +import org.jclouds.googlecloudstorage.domain.Resource.Kind; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.inject.Inject; +import com.google.inject.Singleton; + +@Singleton +public class ObjectListToStorageMetadata implements Function<ListPage<GCSObject>, PageSet<? extends StorageMetadata>> { + private final ObjectToBlobMetadata object2blobMd; + + @Inject + public ObjectListToStorageMetadata(ObjectToBlobMetadata object2blobMd) { + this.object2blobMd = object2blobMd; + } + + public PageSet<? extends StorageMetadata> apply(ListPage<GCSObject> from) { + if (from == null) { + from = ListPage.<GCSObject> builder().kind(Kind.OBJECTS).build(); + } + + return new PageSetImpl<StorageMetadata>(Iterables.transform(Iterables.transform(from, object2blobMd), + new Function<BlobMetadata, StorageMetadata>() { + public StorageMetadata apply(BlobMetadata input) { + Map<String, String> userMetaData = (input != null && input.getUserMetadata() != null) ? input + .getUserMetadata() : ImmutableMap.<String, String> of(); + if (input.getContentMetadata().getContentType().equals("application/directory")) { + return new StorageMetadataImpl(StorageType.RELATIVE_PATH, input.getProviderId(), input + .getName(), input.getLocation(), input.getUri(), input.getETag(), input + .getCreationDate(), input.getLastModified(), userMetaData); + } + return input; + } + }), from.getNextPageToken()); + + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/ObjectToBlobMetadata.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/ObjectToBlobMetadata.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/ObjectToBlobMetadata.java new file mode 100644 index 0000000..ced893a --- /dev/null +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/functions/ObjectToBlobMetadata.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.blobstore.functions; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.blobstore.domain.MutableBlobMetadata; +import org.jclouds.blobstore.domain.StorageType; +import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl; +import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy; +import org.jclouds.googlecloudstorage.domain.GCSObject; +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; + +@Singleton +public class ObjectToBlobMetadata implements Function<GCSObject, MutableBlobMetadata> { + private final IfDirectoryReturnNameStrategy ifDirectoryReturnName; + + @Inject + public ObjectToBlobMetadata(IfDirectoryReturnNameStrategy ifDirectoryReturnName) { + this.ifDirectoryReturnName = ifDirectoryReturnName; + } + + public MutableBlobMetadata apply(GCSObject from) { + if (from == null) + return null; + MutableBlobMetadata to = new MutableBlobMetadataImpl(); + + if (from.getMd5HashCode() != null) + to.getContentMetadata().setContentMD5(from.getMd5HashCode()); + if (from.getContentType() != null) + to.getContentMetadata().setContentType(from.getContentType()); + if (from.getContentDisposition() != null) + to.getContentMetadata().setContentDisposition(from.getContentDisposition()); + if (from.getContentEncoding() != null) + to.getContentMetadata().setContentEncoding(from.getContentEncoding()); + if (from.getContentLanguage() != null) + to.getContentMetadata().setContentLanguage(from.getContentLanguage()); + if (from.getSize() != null) + to.getContentMetadata().setContentLength(from.getSize()); + if (from.getUpdated() != null) + to.setLastModified(from.getUpdated()); + to.setContainer(from.getBucket()); + Map<String, String> userMeta = from.getAllMetadata() == null ? ImmutableMap.<String, String> of() : from + .getAllMetadata(); + to.setUserMetadata(userMeta); + to.setETag(from.getEtag()); + to.setName(from.getName()); + to.setUri(from.getSelfLink()); + to.setId(from.getId()); + to.setPublicUri(from.getMediaLink()); + + String directoryName = ifDirectoryReturnName.execute(to); + if (directoryName != null) { + to.setName(directoryName); + to.setType(StorageType.RELATIVE_PATH); + } else { + to.setType(StorageType.BLOB); + } + return to; + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartNamingStrategy.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartNamingStrategy.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartNamingStrategy.java new file mode 100644 index 0000000..89e76a3 --- /dev/null +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartNamingStrategy.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.blobstore.strategy.internal; + +import javax.inject.Singleton; + +@Singleton +public class MultipartNamingStrategy { + + private static final String PART_SEPARATOR = "_"; + + protected String getPartName(String key, int partNumber, int totalParts) { + int base = (int) Math.log10(totalParts) + 1; + return String.format("%s%s%0" + base + "d", key, PART_SEPARATOR, partNumber); + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUpload.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUpload.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUpload.java new file mode 100644 index 0000000..2edc6c5 --- /dev/null +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUpload.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.blobstore.strategy.internal; + +public final class MultipartUpload { + + private MultipartUpload() { + } + + /* Maximum number of parts per upload */ + public static final int MAX_NUMBER_OF_PARTS = 10000; + /* Maximum number of parts returned for a list parts request */ + public static final int MAX_LIST_PARTS_RETURNED = 1000; + /* Maximum number of multipart uploads returned in a list multipart uploads request */ + public static final int MAX_LIST_MPU_RETURNED = 1000; + + /** + * part size 5 MB to 5 GB, last part can be < 5 MB + */ + public static final long MIN_PART_SIZE = 5L * 1024L * 1024L; + public static final long MAX_PART_SIZE = 5L * 1024L * 1024L * 1024L; +} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUploadSlicingAlgorithm.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUploadSlicingAlgorithm.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUploadSlicingAlgorithm.java new file mode 100644 index 0000000..44c0b8b --- /dev/null +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUploadSlicingAlgorithm.java @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.blobstore.strategy.internal; + +import com.google.common.annotations.VisibleForTesting; +import com.google.inject.Inject; +import org.jclouds.blobstore.reference.BlobStoreConstants; +import org.jclouds.logging.Logger; + +import javax.annotation.Resource; +import javax.inject.Named; + +public class MultipartUploadSlicingAlgorithm { + + @Resource + @Named(BlobStoreConstants.BLOBSTORE_LOGGER) + protected Logger logger = Logger.NULL; + + @VisibleForTesting + static final long DEFAULT_PART_SIZE = 32 * 1024 * 1024; + + @VisibleForTesting + static final int DEFAULT_MAGNITUDE_BASE = 100; + + @Inject(optional = true) + @Named("jclouds.mpu.parts.size") + @VisibleForTesting + long defaultPartSize = DEFAULT_PART_SIZE; + + @Inject(optional = true) + @Named("jclouds.mpu.parts.magnitude") + @VisibleForTesting + int magnitudeBase = DEFAULT_MAGNITUDE_BASE; + + // calculated only once, but not from the constructor + private volatile int parts; // required number of parts with chunkSize + private volatile long chunkSize; + private volatile long remaining; // number of bytes remained for the last part + + // sequentially updated values + private volatile int part; + private volatile long chunkOffset; + private volatile long copied; + + @VisibleForTesting + protected long calculateChunkSize(long length) { + long unitPartSize = defaultPartSize; // first try with default part size + int parts = (int) (length / unitPartSize); + long partSize = unitPartSize; + int magnitude = parts / magnitudeBase; + if (magnitude > 0) { + partSize = magnitude * unitPartSize; + if (partSize > MultipartUpload.MAX_PART_SIZE) { + partSize = MultipartUpload.MAX_PART_SIZE; + unitPartSize = MultipartUpload.MAX_PART_SIZE; + } + parts = (int) (length / partSize); + if (parts * partSize < length) { + partSize = (magnitude + 1) * unitPartSize; + if (partSize > MultipartUpload.MAX_PART_SIZE) { + partSize = MultipartUpload.MAX_PART_SIZE; + unitPartSize = MultipartUpload.MAX_PART_SIZE; + } + parts = (int) (length / partSize); + } + } + if (parts > MultipartUpload.MAX_NUMBER_OF_PARTS) { // if splits in too many parts or + // cannot be split + unitPartSize = MultipartUpload.MIN_PART_SIZE; // take the minimum part size + parts = (int) (length / unitPartSize); + } + if (parts > MultipartUpload.MAX_NUMBER_OF_PARTS) { // if still splits in too many parts + parts = MultipartUpload.MAX_NUMBER_OF_PARTS - 1; // limit them. do not care about not + // covering + } + long remainder = length % unitPartSize; + if (remainder == 0 && parts > 0) { + parts -= 1; + } + this.chunkSize = partSize; + this.parts = parts; + this.remaining = length - partSize * parts; + logger.debug(" %d bytes partitioned in %d parts of part size: %d, remaining: %d%s", length, parts, chunkSize, + remaining, remaining > MultipartUpload.MAX_PART_SIZE ? " overflow!" : ""); + return this.chunkSize; + } + + public long getCopied() { + return copied; + } + + public void setCopied(long copied) { + this.copied = copied; + } + + @VisibleForTesting + protected int getParts() { + return parts; + } + + protected int getNextPart() { + return ++part; + } + + protected void addCopied(long copied) { + this.copied += copied; + } + + protected long getNextChunkOffset() { + long next = chunkOffset; + chunkOffset += getChunkSize(); + return next; + } + + @VisibleForTesting + protected long getChunkSize() { + return chunkSize; + } + + @VisibleForTesting + protected long getRemaining() { + return remaining; + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUploadStrategy.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUploadStrategy.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUploadStrategy.java new file mode 100644 index 0000000..89c4879 --- /dev/null +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/MultipartUploadStrategy.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.blobstore.strategy.internal; + +import org.jclouds.blobstore.domain.Blob; + +import com.google.inject.ImplementedBy; + +@ImplementedBy(SequentialMultipartUploadStrategy.class) +public abstract class MultipartUploadStrategy { + public abstract String execute(String container, Blob blob); +} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/SequentialMultipartUploadStrategy.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/SequentialMultipartUploadStrategy.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/SequentialMultipartUploadStrategy.java new file mode 100644 index 0000000..d6522b5 --- /dev/null +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/strategy/internal/SequentialMultipartUploadStrategy.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.blobstore.strategy.internal; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + +import javax.annotation.Resource; +import javax.inject.Named; +import javax.inject.Provider; + +import org.jclouds.blobstore.domain.Blob; +import org.jclouds.blobstore.domain.BlobBuilder; +import org.jclouds.blobstore.reference.BlobStoreConstants; +import org.jclouds.googlecloudstorage.GoogleCloudStorageApi; +import org.jclouds.googlecloudstorage.blobstore.functions.BlobMetadataToObjectTemplate; +import org.jclouds.googlecloudstorage.domain.GCSObject; +import org.jclouds.googlecloudstorage.domain.templates.ComposeObjectTemplate; +import org.jclouds.googlecloudstorage.domain.templates.ObjectTemplate; +import org.jclouds.io.Payload; +import org.jclouds.io.PayloadSlicer; +import org.jclouds.logging.Logger; + +import com.google.common.collect.Sets; +import com.google.inject.Inject; + +public class SequentialMultipartUploadStrategy extends MultipartUploadStrategy { + + @Resource + @Named(BlobStoreConstants.BLOBSTORE_LOGGER) + private Logger logger = Logger.NULL; + + private final GoogleCloudStorageApi api; + private final Provider<BlobBuilder> blobBuilders; + private final BlobMetadataToObjectTemplate blob2ObjectTemplate; + private final MultipartUploadSlicingAlgorithm algorithm; + private final PayloadSlicer slicer; + private final MultipartNamingStrategy namingStrategy; + + @Inject + public SequentialMultipartUploadStrategy(GoogleCloudStorageApi api, Provider<BlobBuilder> blobBuilders, + BlobMetadataToObjectTemplate blob2ObjectTemplate, MultipartUploadSlicingAlgorithm algorithm, + PayloadSlicer slicer, MultipartNamingStrategy namingStrategy) { + this.api = checkNotNull(api, "api"); + this.blobBuilders = checkNotNull(blobBuilders, "blobBuilders"); + this.blob2ObjectTemplate = checkNotNull(blob2ObjectTemplate, "blob2Object"); + this.algorithm = checkNotNull(algorithm, "algorithm"); + this.slicer = checkNotNull(slicer, "slicer"); + this.namingStrategy = checkNotNull(namingStrategy, "namingStrategy"); + } + + @Override + public String execute(String container, Blob blob) { + + ObjectTemplate destination = blob2ObjectTemplate.apply(blob.getMetadata()); + ComposeObjectTemplate template = new ComposeObjectTemplate().destination(destination); + + Set<GCSObject> sourceList = Sets.newHashSet(); + + String key = blob.getMetadata().getName(); + Payload payload = blob.getPayload(); + Long length = payload.getContentMetadata().getContentLength(); + if (length == null) { + length = blob.getMetadata().getContentMetadata().getContentLength(); + payload.getContentMetadata().setContentLength(length); + } + checkNotNull(length, + "please invoke payload.getContentMetadata().setContentLength(length) prior to multipart upload"); + long chunkSize = algorithm.calculateChunkSize(length); + int partCount = algorithm.getParts(); + if (partCount > 0) { + for (Payload part : slicer.slice(payload, chunkSize)) { + int partNum = algorithm.getNextPart(); + String partName = namingStrategy.getPartName(key, partNum, partCount); + long partSize = ((partCount + 1) == partNum) ? algorithm.getRemaining() : algorithm.getChunkSize(); + Blob blobPart = blobBuilders.get().name(partName).payload(part).contentDisposition(partName) + .contentLength(partSize).contentType(blob.getMetadata().getContentMetadata().getContentType()) + .build(); + GCSObject object = api.getObjectApi().multipartUpload(container, + blob2ObjectTemplate.apply(blobPart.getMetadata()), blobPart.getPayload()); + sourceList.add(object); + } + template = template.sourceObjects(sourceList); + return api.getObjectApi().composeObjects(container, key, template).getEtag(); + } else { + return api.getObjectApi() + .multipartUpload(container, blob2ObjectTemplate.apply(blob.getMetadata()), blob.getPayload()) + .getEtag(); + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageHttpApiModule.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageHttpApiModule.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageHttpApiModule.java index a8c0bdb..56f6ac6 100644 --- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageHttpApiModule.java +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageHttpApiModule.java @@ -16,14 +16,33 @@ */ package org.jclouds.googlecloudstorage.config; +import static com.google.common.base.Suppliers.compose; +import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.domain.Credentials; import org.jclouds.googlecloudstorage.GoogleCloudStorageApi; import org.jclouds.googlecloudstorage.handlers.GoogleCloudStorageErrorHandler; import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.ServerError; +import org.jclouds.location.Provider; +import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.ConfiguresHttpApi; import org.jclouds.rest.config.HttpApiModule; +import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier; + +import com.google.common.base.Function; +import com.google.common.base.Splitter; +import com.google.common.base.Supplier; +import com.google.common.collect.Iterables; +import com.google.inject.Provides; /** * Configures the GoogleCloud connection. @@ -40,4 +59,26 @@ public class GoogleCloudStorageHttpApiModule extends HttpApiModule<GoogleCloudSt bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(GoogleCloudStorageErrorHandler.class); } + @Provides + @Singleton + @UserProject + public Supplier<String> supplyProject(@Provider final Supplier<Credentials> creds, final GoogleCloudStorageApi api, + AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds) { + return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, + compose(new Function<Credentials, String>() { + public String apply(Credentials in) { + // ID should be of the form [email protected] + // OR (increasingly often) [email protected] + String projectName = in.identity; + if (projectName.indexOf("@") != -1) { + projectName = Iterables.get(Splitter.on("@").split(projectName), 0); + if (projectName.indexOf("-") != -1) { + // if ID is of the form [email protected] + projectName = Iterables.get(Splitter.on("-").split(projectName), 0); + } + } + return projectName; + } + }, creds), seconds, TimeUnit.SECONDS); + } } http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/UserProject.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/UserProject.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/UserProject.java new file mode 100644 index 0000000..ae59af0 --- /dev/null +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/UserProject.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.config; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.inject.Qualifier; + +/** + * Qualifies a property as the user's project id. + */ +@Retention(value = RetentionPolicy.RUNTIME) +@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) +@Qualifier +public @interface UserProject { +} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/Bucket.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/Bucket.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/Bucket.java index 2f47f7f..d80a99e 100644 --- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/Bucket.java +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/Bucket.java @@ -24,8 +24,8 @@ import java.net.URI; import java.util.Date; import java.util.Set; -import org.jclouds.googlecloudstorage.domain.DomainResourceRefferences.Location; -import org.jclouds.googlecloudstorage.domain.DomainResourceRefferences.StorageClass; +import org.jclouds.googlecloudstorage.domain.DomainResourceReferences.Location; +import org.jclouds.googlecloudstorage.domain.DomainResourceReferences.StorageClass; import org.jclouds.googlecloudstorage.domain.internal.BucketCors; import org.jclouds.googlecloudstorage.domain.internal.BucketLifeCycle; import org.jclouds.googlecloudstorage.domain.internal.Logging; http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/BucketAccessControls.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/BucketAccessControls.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/BucketAccessControls.java index 3bf4f28..6d0d0ed 100644 --- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/BucketAccessControls.java +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/BucketAccessControls.java @@ -21,7 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.net.URI; -import org.jclouds.googlecloudstorage.domain.DomainResourceRefferences.Role; +import org.jclouds.googlecloudstorage.domain.DomainResourceReferences.Role; import org.jclouds.googlecloudstorage.domain.internal.ProjectTeam; import org.jclouds.javax.annotation.Nullable; http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/DefaultObjectAccessControls.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/DefaultObjectAccessControls.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/DefaultObjectAccessControls.java index 7509735..aeddc41 100644 --- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/DefaultObjectAccessControls.java +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/DefaultObjectAccessControls.java @@ -21,7 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.net.URI; -import org.jclouds.googlecloudstorage.domain.DomainResourceRefferences.ObjectRole; +import org.jclouds.googlecloudstorage.domain.DomainResourceReferences.ObjectRole; import org.jclouds.googlecloudstorage.domain.internal.ProjectTeam; import org.jclouds.javax.annotation.Nullable; http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/DomainResourceReferences.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/DomainResourceReferences.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/DomainResourceReferences.java new file mode 100644 index 0000000..272074b --- /dev/null +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/DomainResourceReferences.java @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.domain; + +import com.google.common.base.CaseFormat; + +public final class DomainResourceReferences { + + private DomainResourceReferences() { + } + + public enum Role { + READER, WRITER, OWNER + } + + public enum ObjectRole { + READER, OWNER + } + + public enum Location { + ASIA, EU, US, ASIA_EAST1, US_CENTRAL1, US_CENTRAL2, US_EAST1, US_EAST2, US_EAST3, US_WEST1; + + public String value() { + return name().replace('_', '-'); + } + + @Override + public String toString() { + return value(); + } + + public static Location fromValue(String location) { + return valueOf(location.replace('-', '_')); + } + } + + public enum StorageClass { + STANDARD, DURABLE_REDUCED_AVAILABILITY; + } + + public enum Projection { + NO_ACL, FULL; + + public String value() { + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name()); + } + + @Override + public String toString() { + return value(); + } + + public static Projection fromValue(String projection) { + return valueOf(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, projection)); + } + } + + public enum PredefinedAcl { + AUTHENTICATED_READ, PRIVATE, PROJEECT_PRIVATE, PUBLIC_READ, PUBLIC_READ_WRITE; + + public String value() { + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name()); + } + + @Override + public String toString() { + return value(); + } + + public static PredefinedAcl fromValue(String predefinedAcl) { + return valueOf(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, predefinedAcl)); + } + } + + public enum DestinationPredefinedAcl { + AUTHENTICATED_READ, BUCKET_OWNER_FULLCONTROL, BUCKET_OWNER_READ, PRIVATE, PROJECT_PRIVATE, PUBLIC_READ; + + public String value() { + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name()); + } + + @Override + public String toString() { + return value(); + } + + public static DestinationPredefinedAcl fromValue(String destinationPredefinedAcl) { + return valueOf(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, destinationPredefinedAcl)); + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/DomainResourceRefferences.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/DomainResourceRefferences.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/DomainResourceRefferences.java deleted file mode 100644 index 82b3442..0000000 --- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/DomainResourceRefferences.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.domain; - -import com.google.common.base.CaseFormat; - -public final class DomainResourceRefferences { - - private DomainResourceRefferences() { - } - - public enum Role { - READER, WRITER, OWNER - } - - public enum ObjectRole { - READER, OWNER - } - - public enum Location { - ASIA, EU, US, ASIA_EAST1, US_CENTRAL1, US_CENTRAL2, US_EAST1, US_EAST2, US_EAST3, US_WEST1; - - public String value() { - return name().replace('_', '-'); - } - - @Override - public String toString() { - return value(); - } - - public static Location fromValue(String location) { - return valueOf(location.replace('-', '_')); - } - } - - public enum StorageClass { - STANDARD, DURABLE_REDUCED_AVAILABILITY; - } - - public enum Projection { - NO_ACL, FULL; - - public String value() { - return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name()); - } - - @Override - public String toString() { - return value(); - } - - public static Projection fromValue(String projection) { - return valueOf(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, projection)); - } - } - - public enum PredefinedAcl { - AUTHENTICATED_READ, PRIVATE, PROJEECT_PRIVATE, PUBLIC_READ, PUBLIC_READ_WRITE; - - public String value() { - return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name()); - } - - @Override - public String toString() { - return value(); - } - - public static PredefinedAcl fromValue(String predefinedAcl) { - return valueOf(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, predefinedAcl)); - } - } - - public enum DestinationPredefinedAcl { - AUTHENTICATED_READ, BUCKET_OWNER_FULLCONTROL, BUCKET_OWNER_READ, PRIVATE, PROJECT_PRIVATE, PUBLIC_READ; - - public String value() { - return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name()); - } - - @Override - public String toString() { - return value(); - } - - public static DestinationPredefinedAcl fromValue(String destinationPredefinedAcl) { - return valueOf(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, destinationPredefinedAcl)); - } - } -} http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/GCSObject.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/GCSObject.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/GCSObject.java index fdce717..50c1bca 100644 --- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/GCSObject.java +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/GCSObject.java @@ -24,7 +24,7 @@ import java.util.Date; import java.util.Map; import java.util.Set; -import org.jclouds.googlecloudstorage.domain.DomainResourceRefferences.StorageClass; +import org.jclouds.googlecloudstorage.domain.DomainResourceReferences.StorageClass; import org.jclouds.googlecloudstorage.domain.internal.Owner; import com.google.common.base.Objects; @@ -132,8 +132,11 @@ public class GCSObject extends Resource { } public HashCode getMd5HashCode() { - HashCode hc = HashCode.fromBytes(BaseEncoding.base64().decode(md5Hash)); - return hc; + if (md5Hash != null) { + HashCode hc = HashCode.fromBytes(BaseEncoding.base64().decode(md5Hash)); + return hc; + } + return null; } public URI getMediaLink() { @@ -173,8 +176,12 @@ public class GCSObject extends Resource { } public HashCode getCrc32cHashcode() { - HashCode hc = HashCode.fromBytes(DomainUtils.reverse(BaseEncoding.base64().decode(crc32c))); - return hc; + if (crc32c != null) { + HashCode hc = HashCode.fromBytes(DomainUtils.reverse(BaseEncoding.base64().decode(crc32c))); + return hc; + } + return null; + } public Integer getComponentCount() { http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ObjectAccessControls.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ObjectAccessControls.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ObjectAccessControls.java index 00e29c4..3cf559f 100644 --- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ObjectAccessControls.java +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ObjectAccessControls.java @@ -21,7 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.net.URI; -import org.jclouds.googlecloudstorage.domain.DomainResourceRefferences.ObjectRole; +import org.jclouds.googlecloudstorage.domain.DomainResourceReferences.ObjectRole; import org.jclouds.googlecloudstorage.domain.internal.ProjectTeam; import org.jclouds.javax.annotation.Nullable; http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ccc2d243/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/templates/BucketTemplate.java ---------------------------------------------------------------------- diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/templates/BucketTemplate.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/templates/BucketTemplate.java index b2ea6da..6858166 100644 --- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/templates/BucketTemplate.java +++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/templates/BucketTemplate.java @@ -21,8 +21,8 @@ import java.util.Set; import org.jclouds.googlecloudstorage.domain.BucketAccessControls; import org.jclouds.googlecloudstorage.domain.DefaultObjectAccessControls; -import org.jclouds.googlecloudstorage.domain.DomainResourceRefferences.Location; -import org.jclouds.googlecloudstorage.domain.DomainResourceRefferences.StorageClass; +import org.jclouds.googlecloudstorage.domain.DomainResourceReferences.Location; +import org.jclouds.googlecloudstorage.domain.DomainResourceReferences.StorageClass; import org.jclouds.googlecloudstorage.domain.internal.BucketCors; import org.jclouds.googlecloudstorage.domain.internal.BucketLifeCycle; import org.jclouds.googlecloudstorage.domain.internal.Logging;
