You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by an...@apache.org on 2014/10/07 00:31:01 UTC
[24/52] [abbrv] git commit: JCLOUDS-40 remove all implementations of
AsyncBlobStore except Submission in preparation for complete removal.
JCLOUDS-40 remove all implementations of AsyncBlobStore except Submission in preparation for complete removal.
Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/dfb583b6
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/dfb583b6
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/dfb583b6
Branch: refs/heads/use-agentproxy-008
Commit: dfb583b67aba421f9aa48e97ebfbc5303420d3b7
Parents: 8c520d3
Author: Adrian Cole <ac...@twitter.com>
Authored: Sat Oct 4 22:35:32 2014 -0700
Committer: Adrian Cole <ad...@gmail.com>
Committed: Sun Oct 5 08:49:38 2014 -0700
----------------------------------------------------------------------
.../config/AtmosBlobStoreContextModule.java | 3 -
.../FilesystemBlobStoreContextModule.java | 8 -
.../config/S3BlobStoreContextModule.java | 3 -
.../config/SwiftBlobStoreContextModule.java | 3 -
.../org/jclouds/blobstore/AsyncBlobStore.java | 3 +
.../jclouds/blobstore/LocalAsyncBlobStore.java | 558 ------------------
.../blobstore/config/LocalBlobStore.java | 562 ++++++++++++++++++-
.../config/TransientBlobStoreContextModule.java | 10 -
.../blobstore/internal/BaseAsyncBlobStore.java | 310 ----------
.../TransientBlobRequestSignerTest.java | 3 +-
.../config/AzureBlobStoreContextModule.java | 3 -
...loudObjectStorageBlobStoreContextModule.java | 4 -
12 files changed, 566 insertions(+), 904 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds/blob/dfb583b6/apis/atmos/src/main/java/org/jclouds/atmos/blobstore/config/AtmosBlobStoreContextModule.java
----------------------------------------------------------------------
diff --git a/apis/atmos/src/main/java/org/jclouds/atmos/blobstore/config/AtmosBlobStoreContextModule.java b/apis/atmos/src/main/java/org/jclouds/atmos/blobstore/config/AtmosBlobStoreContextModule.java
index a562ed6..c83dbf3 100644
--- a/apis/atmos/src/main/java/org/jclouds/atmos/blobstore/config/AtmosBlobStoreContextModule.java
+++ b/apis/atmos/src/main/java/org/jclouds/atmos/blobstore/config/AtmosBlobStoreContextModule.java
@@ -23,11 +23,9 @@ import javax.inject.Singleton;
import org.jclouds.atmos.AtmosClient;
import org.jclouds.atmos.blobstore.AtmosBlobRequestSigner;
import org.jclouds.atmos.blobstore.AtmosBlobStore;
-import org.jclouds.blobstore.AsyncBlobStore;
import org.jclouds.blobstore.BlobRequestSigner;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.attr.ConsistencyModel;
-import org.jclouds.blobstore.internal.SubmissionAsyncBlobStore;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
@@ -41,7 +39,6 @@ public class AtmosBlobStoreContextModule extends AbstractModule {
@Override
protected void configure() {
bind(ConsistencyModel.class).toInstance(ConsistencyModel.EVENTUAL);
- bind(AsyncBlobStore.class).to(SubmissionAsyncBlobStore.class).in(Scopes.SINGLETON);
bind(BlobStore.class).to(AtmosBlobStore.class).in(Scopes.SINGLETON);
bind(BlobRequestSigner.class).to(AtmosBlobRequestSigner.class);
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/dfb583b6/apis/filesystem/src/main/java/org/jclouds/filesystem/config/FilesystemBlobStoreContextModule.java
----------------------------------------------------------------------
diff --git a/apis/filesystem/src/main/java/org/jclouds/filesystem/config/FilesystemBlobStoreContextModule.java b/apis/filesystem/src/main/java/org/jclouds/filesystem/config/FilesystemBlobStoreContextModule.java
index 972abe9..9294450 100644
--- a/apis/filesystem/src/main/java/org/jclouds/filesystem/config/FilesystemBlobStoreContextModule.java
+++ b/apis/filesystem/src/main/java/org/jclouds/filesystem/config/FilesystemBlobStoreContextModule.java
@@ -16,12 +16,8 @@
*/
package org.jclouds.filesystem.config;
-import static org.jclouds.rest.config.BinderUtils.bindSyncToAsyncApi;
-
-import org.jclouds.blobstore.AsyncBlobStore;
import org.jclouds.blobstore.BlobRequestSigner;
import org.jclouds.blobstore.BlobStore;
-import org.jclouds.blobstore.LocalAsyncBlobStore;
import org.jclouds.blobstore.LocalBlobRequestSigner;
import org.jclouds.blobstore.LocalStorageStrategy;
import org.jclouds.blobstore.attr.ConsistencyModel;
@@ -41,11 +37,7 @@ public class FilesystemBlobStoreContextModule extends AbstractModule {
@Override
protected void configure() {
- bind(AsyncBlobStore.class).to(LocalAsyncBlobStore.class).asEagerSingleton();
- // forward all requests from TransientBlobStore to TransientAsyncBlobStore. needs above binding as cannot proxy a class
- bindSyncToAsyncApi(binder(), LocalBlobStore.class, AsyncBlobStore.class);
bind(BlobStore.class).to(LocalBlobStore.class);
-
install(new BlobStoreObjectModule());
bind(ConsistencyModel.class).toInstance(ConsistencyModel.STRICT);
bind(LocalStorageStrategy.class).to(FilesystemStorageStrategyImpl.class);
http://git-wip-us.apache.org/repos/asf/jclouds/blob/dfb583b6/apis/s3/src/main/java/org/jclouds/s3/blobstore/config/S3BlobStoreContextModule.java
----------------------------------------------------------------------
diff --git a/apis/s3/src/main/java/org/jclouds/s3/blobstore/config/S3BlobStoreContextModule.java b/apis/s3/src/main/java/org/jclouds/s3/blobstore/config/S3BlobStoreContextModule.java
index 525f9bd..f820308 100644
--- a/apis/s3/src/main/java/org/jclouds/s3/blobstore/config/S3BlobStoreContextModule.java
+++ b/apis/s3/src/main/java/org/jclouds/s3/blobstore/config/S3BlobStoreContextModule.java
@@ -22,11 +22,9 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Singleton;
-import org.jclouds.blobstore.AsyncBlobStore;
import org.jclouds.blobstore.BlobRequestSigner;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.attr.ConsistencyModel;
-import org.jclouds.blobstore.internal.SubmissionAsyncBlobStore;
import org.jclouds.domain.Location;
import org.jclouds.s3.S3Client;
import org.jclouds.s3.blobstore.S3BlobRequestSigner;
@@ -47,7 +45,6 @@ public class S3BlobStoreContextModule extends AbstractModule {
@Override
protected void configure() {
bind(ConsistencyModel.class).toInstance(ConsistencyModel.EVENTUAL);
- bind(AsyncBlobStore.class).to(SubmissionAsyncBlobStore.class).in(SINGLETON);
bind(BlobStore.class).to(S3BlobStore.class).in(SINGLETON);
bind(new TypeLiteral<Function<String, Location>>() {
}).to(LocationFromBucketName.class);
http://git-wip-us.apache.org/repos/asf/jclouds/blob/dfb583b6/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/SwiftBlobStoreContextModule.java
----------------------------------------------------------------------
diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/SwiftBlobStoreContextModule.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/SwiftBlobStoreContextModule.java
index 5387b8a..2ecdc88 100644
--- a/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/SwiftBlobStoreContextModule.java
+++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/SwiftBlobStoreContextModule.java
@@ -16,10 +16,8 @@
*/
package org.jclouds.openstack.swift.blobstore.config;
-import org.jclouds.blobstore.AsyncBlobStore;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.attr.ConsistencyModel;
-import org.jclouds.blobstore.internal.SubmissionAsyncBlobStore;
import org.jclouds.openstack.swift.blobstore.SwiftBlobStore;
import com.google.inject.AbstractModule;
@@ -30,7 +28,6 @@ public class SwiftBlobStoreContextModule extends AbstractModule {
@Override
protected void configure() {
bind(ConsistencyModel.class).toInstance(ConsistencyModel.EVENTUAL);
- bind(AsyncBlobStore.class).to(SubmissionAsyncBlobStore.class).in(Scopes.SINGLETON);
bind(BlobStore.class).to(SwiftBlobStore.class).in(Scopes.SINGLETON);
}
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/dfb583b6/blobstore/src/main/java/org/jclouds/blobstore/AsyncBlobStore.java
----------------------------------------------------------------------
diff --git a/blobstore/src/main/java/org/jclouds/blobstore/AsyncBlobStore.java b/blobstore/src/main/java/org/jclouds/blobstore/AsyncBlobStore.java
index 22feebd..a121455 100644
--- a/blobstore/src/main/java/org/jclouds/blobstore/AsyncBlobStore.java
+++ b/blobstore/src/main/java/org/jclouds/blobstore/AsyncBlobStore.java
@@ -23,6 +23,7 @@ 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.internal.SubmissionAsyncBlobStore;
import org.jclouds.blobstore.options.CreateContainerOptions;
import org.jclouds.blobstore.options.GetOptions;
import org.jclouds.blobstore.options.ListContainerOptions;
@@ -31,6 +32,7 @@ import org.jclouds.domain.Location;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.util.concurrent.ListenableFuture;
+import com.google.inject.ImplementedBy;
/**
* Provides hooks needed to run a blob store asynchronously
@@ -40,6 +42,7 @@ import com.google.common.util.concurrent.ListenableFuture;
* supported. Please use {@link org.jclouds.blobstore.BlobStore}
*/
@Deprecated
+@ImplementedBy(SubmissionAsyncBlobStore.class)
public interface AsyncBlobStore {
/**
* @see BlobStore#getContext
http://git-wip-us.apache.org/repos/asf/jclouds/blob/dfb583b6/blobstore/src/main/java/org/jclouds/blobstore/LocalAsyncBlobStore.java
----------------------------------------------------------------------
diff --git a/blobstore/src/main/java/org/jclouds/blobstore/LocalAsyncBlobStore.java b/blobstore/src/main/java/org/jclouds/blobstore/LocalAsyncBlobStore.java
deleted file mode 100644
index 42e4124..0000000
--- a/blobstore/src/main/java/org/jclouds/blobstore/LocalAsyncBlobStore.java
+++ /dev/null
@@ -1,558 +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.blobstore;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.base.Throwables.getCausalChain;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.find;
-import static com.google.common.collect.Iterables.size;
-import static com.google.common.collect.Iterables.transform;
-import static com.google.common.collect.Sets.filter;
-import static com.google.common.collect.Sets.newTreeSet;
-import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
-import static com.google.common.util.concurrent.Futures.immediateFuture;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Date;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.regex.Pattern;
-
-import javax.annotation.Resource;
-import javax.inject.Inject;
-import javax.inject.Named;
-
-import org.jclouds.Constants;
-import org.jclouds.blobstore.domain.Blob;
-import org.jclouds.blobstore.domain.Blob.Factory;
-import org.jclouds.blobstore.domain.BlobMetadata;
-import org.jclouds.blobstore.domain.MutableBlobMetadata;
-import org.jclouds.blobstore.domain.MutableStorageMetadata;
-import org.jclouds.blobstore.domain.PageSet;
-import org.jclouds.blobstore.domain.StorageMetadata;
-import org.jclouds.blobstore.domain.StorageType;
-import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl;
-import org.jclouds.blobstore.domain.internal.PageSetImpl;
-import org.jclouds.blobstore.domain.internal.StorageMetadataImpl;
-import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
-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.blobstore.strategy.IfDirectoryReturnNameStrategy;
-import org.jclouds.blobstore.util.BlobStoreUtils;
-import org.jclouds.blobstore.util.BlobUtils;
-import org.jclouds.collect.Memoized;
-import org.jclouds.domain.Location;
-import org.jclouds.http.HttpCommand;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.http.HttpResponseException;
-import org.jclouds.http.HttpUtils;
-import org.jclouds.io.ByteStreams2;
-import org.jclouds.io.ContentMetadata;
-import org.jclouds.io.ContentMetadataCodec;
-import org.jclouds.io.Payload;
-import org.jclouds.logging.Logger;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-
-/**
- * Implementation of {@link BaseAsyncBlobStore} which uses a pluggable
- * LocalStorageStrategy.
- *
- * @deprecated will be removed in jclouds 1.7, as async interfaces are no longer
- * supported. Please create and use {@link LocalBlobStore}
- */
-@Deprecated
-public class LocalAsyncBlobStore extends BaseAsyncBlobStore {
-
- @Resource
- protected Logger logger = Logger.NULL;
-
- protected final ContentMetadataCodec contentMetadataCodec;
- protected final IfDirectoryReturnNameStrategy ifDirectoryReturnName;
- protected final Factory blobFactory;
- protected final LocalStorageStrategy storageStrategy;
-
- @Inject
- protected LocalAsyncBlobStore(BlobStoreContext context,
- BlobUtils blobUtils,
- @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
- Supplier<Location> defaultLocation,
- @Memoized Supplier<Set<? extends Location>> locations,
- ContentMetadataCodec contentMetadataCodec,
- IfDirectoryReturnNameStrategy ifDirectoryReturnName,
- Factory blobFactory, LocalStorageStrategy storageStrategy) {
- super(context, blobUtils, userExecutor, defaultLocation, locations);
- this.blobFactory = blobFactory;
- this.contentMetadataCodec = contentMetadataCodec;
- this.ifDirectoryReturnName = ifDirectoryReturnName;
- this.storageStrategy = storageStrategy;
- }
-
- /**
- * default maxResults is 1000
- */
- @Override
- public ListenableFuture<PageSet<? extends StorageMetadata>> list(final String container, ListContainerOptions options) {
-
- // Check if the container exists
- if (!storageStrategy.containerExists(container))
- return immediateFailedFuture(cnfe(container));
-
- // Loading blobs from container
- Iterable<String> blobBelongingToContainer = null;
- try {
- blobBelongingToContainer = storageStrategy.getBlobKeysInsideContainer(container);
- } catch (IOException e) {
- logger.error(e, "An error occurred loading blobs contained into container %s", container);
- Throwables.propagate(e);
- }
-
- SortedSet<StorageMetadata> contents = newTreeSet(transform(blobBelongingToContainer,
- new Function<String, StorageMetadata>() {
- public StorageMetadata apply(String key) {
- if (!storageStrategy.blobExists(container, key)) {
- // handle directory
- return new StorageMetadataImpl(StorageType.FOLDER, /*id=*/ null, key,
- /*location=*/ null, /*uri=*/ null, /*eTag=*/ null, /*creationDate=*/ null,
- /*lastModified=*/ null, ImmutableMap.<String, String>of());
- }
- Blob oldBlob = loadBlob(container, key);
- checkState(oldBlob != null, "blob " + key + " is not present although it was in the list of "
- + container);
- checkState(oldBlob.getMetadata() != null, "blob " + container + "/" + key + " has no metadata");
- MutableBlobMetadata md = BlobStoreUtils.copy(oldBlob.getMetadata());
- String directoryName = ifDirectoryReturnName.execute(md);
- if (directoryName != null) {
- md.setName(directoryName);
- md.setType(StorageType.RELATIVE_PATH);
- }
- return md;
- }
- }));
-
- String marker = null;
- if (options != null) {
- if (options.getMarker() != null) {
- final String finalMarker = options.getMarker();
- StorageMetadata lastMarkerMetadata = find(contents, new Predicate<StorageMetadata>() {
- public boolean apply(StorageMetadata metadata) {
- return metadata.getName().compareTo(finalMarker) > 0;
- }
- });
- contents = contents.tailSet(lastMarkerMetadata);
- }
-
- final String prefix = options.getDir();
- if (prefix != null) {
- contents = newTreeSet(filter(contents, new Predicate<StorageMetadata>() {
- public boolean apply(StorageMetadata o) {
- return o != null && o.getName().startsWith(prefix) && !o.getName().equals(prefix);
- }
- }));
- }
-
- int maxResults = options.getMaxResults() != null ? options.getMaxResults() : 1000;
- if (!contents.isEmpty()) {
- StorageMetadata lastElement = contents.last();
- contents = newTreeSet(Iterables.limit(contents, maxResults));
- if (!contents.contains(lastElement)) {
- // Partial listing
- marker = contents.last().getName();
- }
- }
-
- if (!options.isRecursive()) {
- String delimiter = storageStrategy.getSeparator();
- SortedSet<String> commonPrefixes = newTreeSet(
- transform(contents, new CommonPrefixes(prefix, delimiter)));
- commonPrefixes.remove(CommonPrefixes.NO_PREFIX);
-
- contents = newTreeSet(filter(contents, new DelimiterFilter(prefix, delimiter)));
-
- for (String o : commonPrefixes) {
- MutableStorageMetadata md = new MutableStorageMetadataImpl();
- md.setType(StorageType.RELATIVE_PATH);
- md.setName(o);
- contents.add(md);
- }
- }
-
- // trim metadata, if the response isn't supposed to be detailed.
- if (!options.isDetailed()) {
- for (StorageMetadata md : contents) {
- md.getUserMetadata().clear();
- }
- }
- }
-
- return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(contents,
- marker));
-
- }
-
- private ContainerNotFoundException cnfe(final String name) {
- return new ContainerNotFoundException(name, String.format(
- "container %s not in %s", name,
- storageStrategy.getAllContainerNames()));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ListenableFuture<Void> removeBlob(final String container, final String key) {
- if (!storageStrategy.containerExists(container)) {
- return Futures.immediateFailedFuture(cnfe(container));
- }
- storageStrategy.removeBlob(container, key);
- return immediateFuture(null);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ListenableFuture<Void> clearContainer(final String container) {
- storageStrategy.clearContainer(container);
- return immediateFuture(null);
- }
-
- /**
- * Override parent method because it uses strange futures and listenables
- * that creates problem in the test if more than one test that deletes the
- * container is executed
- *
- * @param container
- * @return
- */
- @Override
- public ListenableFuture<Void> deleteContainer(final String container) {
- deleteAndVerifyContainerGone(container);
- return immediateFuture(null);
- }
-
- @Override
- public ListenableFuture<Boolean> deleteContainerIfEmpty(final String container) {
- Boolean returnVal = true;
- if (storageStrategy.containerExists(container)) {
- try {
- if (Iterables.isEmpty(storageStrategy.getBlobKeysInsideContainer(container)))
- storageStrategy.deleteContainer(container);
- else
- returnVal = false;
- } catch (IOException e) {
- logger.error(e, "An error occurred loading blobs contained into container %s", container);
- Throwables.propagate(e);
- }
- }
- return immediateFuture(returnVal);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ListenableFuture<Boolean> containerExists(final String containerName) {
- return immediateFuture(storageStrategy.containerExists(containerName));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
- Iterable<String> containers = storageStrategy.getAllContainerNames();
-
- return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(transform(
- containers, new Function<String, StorageMetadata>() {
- public StorageMetadata apply(String name) {
- MutableStorageMetadata cmd = create();
- cmd.setName(name);
- cmd.setType(StorageType.CONTAINER);
- cmd.setLocation(storageStrategy.getLocation(name));
- return cmd;
- }
- }), null));
- }
-
- protected MutableStorageMetadata create() {
- return new MutableStorageMetadataImpl();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ListenableFuture<Boolean> createContainerInLocation(final Location location,
- final String name) {
- boolean result = storageStrategy.createContainerInLocation(name, location);
- return immediateFuture(result);
- }
-
- private Blob loadBlob(final String container, final String key) {
- logger.debug("Opening blob in container: %s - %s", container, key);
- return storageStrategy.getBlob(container, key);
- }
-
- protected static class DelimiterFilter implements Predicate<StorageMetadata> {
- private final String prefix;
- private final String delimiter;
-
- public DelimiterFilter(String prefix, String delimiter) {
- this.prefix = prefix;
- this.delimiter = delimiter;
- }
-
- public boolean apply(StorageMetadata metadata) {
- if (prefix == null)
- return metadata.getName().indexOf(delimiter) == -1;
- // ensure we don't accidentally append twice
- String toMatch = prefix.endsWith("/") ? prefix : prefix + delimiter;
- if (metadata.getName().startsWith(toMatch)) {
- String unprefixedName = metadata.getName().replaceFirst(Pattern.quote(toMatch), "");
- if (unprefixedName.equals("")) {
- // we are the prefix in this case, return false
- return false;
- }
- return unprefixedName.indexOf(delimiter) == -1;
- }
- return false;
- }
- }
-
- protected static class CommonPrefixes implements Function<StorageMetadata, String> {
- private final String prefix;
- private final String delimiter;
- public static final String NO_PREFIX = "NO_PREFIX";
-
- public CommonPrefixes(String prefix, String delimiter) {
- this.prefix = prefix;
- this.delimiter = delimiter;
- }
-
- public String apply(StorageMetadata metadata) {
- String working = metadata.getName();
- if (prefix != null) {
- // ensure we don't accidentally append twice
- String toMatch = prefix.endsWith("/") ? prefix : prefix + delimiter;
- if (working.startsWith(toMatch)) {
- working = working.replaceFirst(Pattern.quote(toMatch), "");
- }
- }
- if (working.contains(delimiter)) {
- return working.substring(0, working.indexOf(delimiter));
- }
- return NO_PREFIX;
- }
- }
-
- public static HttpResponseException returnResponseException(int code) {
- HttpResponse response = HttpResponse.builder().statusCode(code).build();
- return new HttpResponseException(new HttpCommand(HttpRequest.builder().method("GET").endpoint("http://stub")
- .build()), response);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ListenableFuture<String> putBlob(String containerName, Blob blob) {
- checkNotNull(containerName, "containerName must be set");
- checkNotNull(blob, "blob must be set");
- String blobKey = blob.getMetadata().getName();
-
- logger.debug("Put blob with key [%s] to container [%s]", blobKey, containerName);
- if (!storageStrategy.containerExists(containerName)) {
- return Futures.immediateFailedFuture(cnfe(containerName));
- }
-
- try {
- return immediateFuture(storageStrategy.putBlob(containerName, blob));
- } catch (IOException e) {
- String message = e.getMessage();
- if (message != null && message.startsWith("MD5 hash code mismatch")) {
- HttpResponseException exception = returnResponseException(400);
- exception.initCause(e);
- throw exception;
- }
- logger.error(e, "An error occurred storing the new blob with name [%s] to container [%s].", blobKey,
- containerName);
- throw Throwables.propagate(e);
- }
- }
-
- private void copyPayloadHeadersToBlob(Payload payload, Blob blob) {
- blob.getAllHeaders().putAll(contentMetadataCodec.toHeaders(payload.getContentMetadata()));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ListenableFuture<Boolean> blobExists(final String containerName, final String key) {
- if (!storageStrategy.containerExists(containerName))
- return immediateFailedFuture(cnfe(containerName));
- return immediateFuture(storageStrategy.blobExists(containerName, key));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ListenableFuture<Blob> getBlob(final String containerName, final String key, GetOptions options) {
- logger.debug("Retrieving blob with key %s from container %s", key, containerName);
- // If the container doesn't exist, an exception is thrown
- if (!storageStrategy.containerExists(containerName)) {
- logger.debug("Container %s does not exist", containerName);
- return immediateFailedFuture(cnfe(containerName));
- }
- // If the blob doesn't exist, a null object is returned
- if (!storageStrategy.blobExists(containerName, key)) {
- logger.debug("Item %s does not exist in container %s", key, containerName);
- return immediateFuture(null);
- }
-
- Blob blob = loadBlob(containerName, key);
-
- if (options != null) {
- if (options.getIfMatch() != null) {
- if (!blob.getMetadata().getETag().equals(options.getIfMatch()))
- return immediateFailedFuture(returnResponseException(412));
- }
- if (options.getIfNoneMatch() != null) {
- if (blob.getMetadata().getETag().equals(options.getIfNoneMatch()))
- return immediateFailedFuture(returnResponseException(304));
- }
- if (options.getIfModifiedSince() != null) {
- Date modifiedSince = options.getIfModifiedSince();
- if (blob.getMetadata().getLastModified().before(modifiedSince)) {
- HttpResponse response = HttpResponse.builder().statusCode(304).build();
- return immediateFailedFuture(new HttpResponseException(String.format("%1$s is before %2$s", blob
- .getMetadata().getLastModified(), modifiedSince), null, response));
- }
-
- }
- if (options.getIfUnmodifiedSince() != null) {
- Date unmodifiedSince = options.getIfUnmodifiedSince();
- if (blob.getMetadata().getLastModified().after(unmodifiedSince)) {
- HttpResponse response = HttpResponse.builder().statusCode(412).build();
- return immediateFailedFuture(new HttpResponseException(String.format("%1$s is after %2$s", blob
- .getMetadata().getLastModified(), unmodifiedSince), null, response));
- }
- }
- blob = copyBlob(blob);
-
- if (options.getRanges() != null && !options.getRanges().isEmpty()) {
- byte[] data;
- try {
- data = ByteStreams2.toByteArrayAndClose(blob.getPayload().openStream());
- } catch (IOException e) {
- return immediateFailedFuture(new RuntimeException(e));
- }
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- for (String s : options.getRanges()) {
- // HTTP uses a closed interval while Java array indexing uses a
- // half-open interval.
- int offset = 0;
- int last = data.length - 1;
- if (s.startsWith("-")) {
- offset = last - Integer.parseInt(s.substring(1)) + 1;
- } else if (s.endsWith("-")) {
- offset = Integer.parseInt(s.substring(0, s.length() - 1));
- } else if (s.contains("-")) {
- String[] firstLast = s.split("\\-");
- offset = Integer.parseInt(firstLast[0]);
- last = Integer.parseInt(firstLast[1]);
- } else {
- return immediateFailedFuture(new IllegalArgumentException("illegal range: " + s));
- }
-
- if (offset > last) {
- return immediateFailedFuture(new IllegalArgumentException("illegal range: " + s));
- }
- if (last + 1 > data.length) {
- last = data.length - 1;
- }
- out.write(data, offset, last - offset + 1);
- }
- ContentMetadata cmd = blob.getPayload().getContentMetadata();
- byte[] byteArray = out.toByteArray();
- blob.setPayload(byteArray);
- HttpUtils.copy(cmd, blob.getPayload().getContentMetadata());
- blob.getPayload().getContentMetadata().setContentLength(Long.valueOf(byteArray.length));
- }
- }
- checkNotNull(blob.getPayload(), "payload " + blob);
- return immediateFuture(blob);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ListenableFuture<BlobMetadata> blobMetadata(final String container, final String key) {
- try {
- Blob blob = getBlob(container, key).get();
- return immediateFuture(blob != null ? (BlobMetadata) BlobStoreUtils.copy(blob.getMetadata()) : null);
- } catch (Exception e) {
- if (size(filter(getCausalChain(e), KeyNotFoundException.class)) >= 1)
- return immediateFuture(null);
- return immediateFailedFuture(e);
- }
- }
-
- private Blob copyBlob(Blob blob) {
- Blob returnVal = blobFactory.create(BlobStoreUtils.copy(blob.getMetadata()));
- returnVal.setPayload(blob.getPayload());
- copyPayloadHeadersToBlob(blob.getPayload(), returnVal);
- return returnVal;
- }
-
- @Override
- protected boolean deleteAndVerifyContainerGone(final String container) {
- storageStrategy.deleteContainer(container);
- return storageStrategy.containerExists(container);
- }
-
- @Override
- public ListenableFuture<String> putBlob(String container, Blob blob, PutOptions options) {
- // TODO implement options
- return putBlob(container, blob);
- }
-
- @Override
- public ListenableFuture<Boolean> createContainerInLocation(Location location, String container,
- CreateContainerOptions options) {
- if (options.isPublicRead())
- throw new UnsupportedOperationException("publicRead");
- return createContainerInLocation(location, container);
- }
-}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/dfb583b6/blobstore/src/main/java/org/jclouds/blobstore/config/LocalBlobStore.java
----------------------------------------------------------------------
diff --git a/blobstore/src/main/java/org/jclouds/blobstore/config/LocalBlobStore.java b/blobstore/src/main/java/org/jclouds/blobstore/config/LocalBlobStore.java
index 5245db6..8af40e9 100644
--- a/blobstore/src/main/java/org/jclouds/blobstore/config/LocalBlobStore.java
+++ b/blobstore/src/main/java/org/jclouds/blobstore/config/LocalBlobStore.java
@@ -16,8 +16,568 @@
*/
package org.jclouds.blobstore.config;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Throwables.getCausalChain;
+import static com.google.common.base.Throwables.propagate;
+import static com.google.common.collect.Iterables.find;
+import static com.google.common.collect.Iterables.size;
+import static com.google.common.collect.Iterables.transform;
+import static com.google.common.collect.Sets.filter;
+import static com.google.common.collect.Sets.newTreeSet;
+import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Date;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.regex.Pattern;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
import org.jclouds.blobstore.BlobStore;
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.blobstore.ContainerNotFoundException;
+import org.jclouds.blobstore.KeyNotFoundException;
+import org.jclouds.blobstore.LocalStorageStrategy;
+import org.jclouds.blobstore.domain.Blob;
+import org.jclouds.blobstore.domain.BlobBuilder;
+import org.jclouds.blobstore.domain.BlobMetadata;
+import org.jclouds.blobstore.domain.MutableBlobMetadata;
+import org.jclouds.blobstore.domain.MutableStorageMetadata;
+import org.jclouds.blobstore.domain.PageSet;
+import org.jclouds.blobstore.domain.StorageMetadata;
+import org.jclouds.blobstore.domain.StorageType;
+import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl;
+import org.jclouds.blobstore.domain.internal.PageSetImpl;
+import org.jclouds.blobstore.domain.internal.StorageMetadataImpl;
+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.blobstore.strategy.IfDirectoryReturnNameStrategy;
+import org.jclouds.blobstore.util.BlobStoreUtils;
+import org.jclouds.blobstore.util.BlobUtils;
+import org.jclouds.collect.Memoized;
+import org.jclouds.domain.Location;
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.HttpResponseException;
+import org.jclouds.http.HttpUtils;
+import org.jclouds.io.ByteStreams2;
+import org.jclouds.io.ContentMetadata;
+import org.jclouds.io.ContentMetadataCodec;
+import org.jclouds.io.Payload;
+import org.jclouds.logging.Logger;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+@Singleton
+public final class LocalBlobStore implements BlobStore {
+
+ @Resource
+ private Logger logger = Logger.NULL;
+
+ private final BlobStoreContext context;
+ private final BlobUtils blobUtils;
+ private final Supplier<Set<? extends Location>> locations;
+ private final ContentMetadataCodec contentMetadataCodec;
+ private final IfDirectoryReturnNameStrategy ifDirectoryReturnName;
+ private final Blob.Factory blobFactory;
+ private final LocalStorageStrategy storageStrategy;
+
+ @Inject
+ LocalBlobStore(BlobStoreContext context,
+ BlobUtils blobUtils,
+ @Memoized Supplier<Set<? extends Location>> locations,
+ ContentMetadataCodec contentMetadataCodec,
+ IfDirectoryReturnNameStrategy ifDirectoryReturnName,
+ Blob.Factory blobFactory, LocalStorageStrategy storageStrategy) {
+ this.context = checkNotNull(context, "context");
+ this.blobUtils = checkNotNull(blobUtils, "blobUtils");
+ this.locations = checkNotNull(locations, "locations");
+ this.blobFactory = blobFactory;
+ this.contentMetadataCodec = contentMetadataCodec;
+ this.ifDirectoryReturnName = ifDirectoryReturnName;
+ this.storageStrategy = storageStrategy;
+ }
+
+ @Override
+ public BlobStoreContext getContext() {
+ return context;
+ }
+
+ @Override
+ public BlobBuilder blobBuilder(String name) {
+ return blobUtils.blobBuilder().name(name);
+ }
+
+ /** This implementation invokes {@link #list(String, ListContainerOptions)} */
+ @Override
+ public PageSet<? extends StorageMetadata> list(String containerName) {
+ return this.list(containerName, ListContainerOptions.NONE);
+ }
+
+ /**
+ * This implementation invokes {@link #countBlobs} with the
+ * {@link ListContainerOptions#recursive} option.
+ */
+ @Override
+ public long countBlobs(String containerName) {
+ return countBlobs(containerName, recursive());
+ }
+
+ /**
+ * This implementation invokes {@link BlobUtils#countBlobs}
+ */
+ @Override
+ public long countBlobs(final String containerName, final ListContainerOptions options) {
+ return blobUtils.countBlobs(containerName, options);
+ }
+
+ /**
+ * This implementation invokes {@link #clearContainer} with the
+ * {@link ListContainerOptions#recursive} option.
+ */
+ @Override
+ public void clearContainer(String containerName) {
+ clearContainer(containerName, recursive());
+ }
+
+ @Override
+ public void clearContainer(String containerName, ListContainerOptions options) {
+ blobUtils.clearContainer(containerName, options);
+ }
+
+ @Override
+ public void deleteDirectory(final String containerName, final String directory) {
+ blobUtils.deleteDirectory(containerName, directory);
+ }
+
+ @Override
+ public boolean directoryExists(String containerName, String directory) {
+ return blobUtils.directoryExists(containerName, directory);
+ }
+
+ @Override
+ public void createDirectory(String containerName, String directory) {
+ if (!blobUtils.directoryExists(containerName, directory)) {
+ blobUtils.createDirectory(containerName, directory);
+ }
+ }
+
+ /**
+ * This implementation invokes {@link #getBlob(String,String, GetOptions)}
+ */
+ @Override
+ public Blob getBlob(String containerName, String key) {
+ return getBlob(containerName, key, GetOptions.NONE);
+ }
+
+ /**
+ * This implementation invokes {@link #deleteAndVerifyContainerGone}
+ */
+ @Override
+ public void deleteContainer(String containerName) {
+ deleteAndVerifyContainerGone(containerName);
+ }
+
+ @Override
+ public Set<? extends Location> listAssignableLocations() {
+ return locations.get();
+ }
+
+ /**
+ * default maxResults is 1000
+ */
+ @Override
+ public PageSet<? extends StorageMetadata> list(final String containerName, ListContainerOptions options) {
+
+ // Check if the container exists
+ if (!storageStrategy.containerExists(containerName))
+ throw cnfe(containerName);
+
+ // Loading blobs from container
+ Iterable<String> blobBelongingToContainer = null;
+ try {
+ blobBelongingToContainer = storageStrategy.getBlobKeysInsideContainer(containerName);
+ } catch (IOException e) {
+ logger.error(e, "An error occurred loading blobs contained into container %s", containerName);
+ propagate(e);
+ }
+
+ SortedSet<StorageMetadata> contents = newTreeSet(transform(blobBelongingToContainer,
+ new Function<String, StorageMetadata>() {
+ public StorageMetadata apply(String key) {
+ if (!storageStrategy.blobExists(containerName, key)) {
+ // handle directory
+ return new StorageMetadataImpl(StorageType.FOLDER, /*id=*/ null, key,
+ /*location=*/ null, /*uri=*/ null, /*eTag=*/ null, /*creationDate=*/ null,
+ /*lastModified=*/ null, ImmutableMap.<String, String>of());
+ }
+ Blob oldBlob = loadBlob(containerName, key);
+ checkState(oldBlob != null, "blob " + key + " is not present although it was in the list of "
+ + containerName);
+ checkState(oldBlob.getMetadata() != null, "blob " + containerName + "/" + key + " has no metadata");
+ MutableBlobMetadata md = BlobStoreUtils.copy(oldBlob.getMetadata());
+ String directoryName = ifDirectoryReturnName.execute(md);
+ if (directoryName != null) {
+ md.setName(directoryName);
+ md.setType(StorageType.RELATIVE_PATH);
+ }
+ return md;
+ }
+ }));
+
+ String marker = null;
+ if (options != null) {
+ if (options.getMarker() != null) {
+ final String finalMarker = options.getMarker();
+ StorageMetadata lastMarkerMetadata = find(contents, new Predicate<StorageMetadata>() {
+ public boolean apply(StorageMetadata metadata) {
+ return metadata.getName().compareTo(finalMarker) > 0;
+ }
+ });
+ contents = contents.tailSet(lastMarkerMetadata);
+ }
+
+ final String prefix = options.getDir();
+ if (prefix != null) {
+ contents = newTreeSet(filter(contents, new Predicate<StorageMetadata>() {
+ public boolean apply(StorageMetadata o) {
+ return o != null && o.getName().startsWith(prefix) && !o.getName().equals(prefix);
+ }
+ }));
+ }
+
+ int maxResults = options.getMaxResults() != null ? options.getMaxResults() : 1000;
+ if (!contents.isEmpty()) {
+ StorageMetadata lastElement = contents.last();
+ contents = newTreeSet(Iterables.limit(contents, maxResults));
+ if (!contents.contains(lastElement)) {
+ // Partial listing
+ marker = contents.last().getName();
+ }
+ }
+
+ if (!options.isRecursive()) {
+ String delimiter = storageStrategy.getSeparator();
+ SortedSet<String> commonPrefixes = newTreeSet(
+ transform(contents, new CommonPrefixes(prefix, delimiter)));
+ commonPrefixes.remove(CommonPrefixes.NO_PREFIX);
+
+ contents = newTreeSet(filter(contents, new DelimiterFilter(prefix, delimiter)));
+
+ for (String o : commonPrefixes) {
+ MutableStorageMetadata md = new MutableStorageMetadataImpl();
+ md.setType(StorageType.RELATIVE_PATH);
+ md.setName(o);
+ contents.add(md);
+ }
+ }
+
+ // trim metadata, if the response isn't supposed to be detailed.
+ if (!options.isDetailed()) {
+ for (StorageMetadata md : contents) {
+ md.getUserMetadata().clear();
+ }
+ }
+ }
+
+ return new PageSetImpl<StorageMetadata>(contents, marker);
+ }
+
+ private ContainerNotFoundException cnfe(final String name) {
+ return new ContainerNotFoundException(name, String.format(
+ "container %s not in %s", name,
+ storageStrategy.getAllContainerNames()));
+ }
+
+ @Override
+ public void removeBlob(String containerName, final String key) {
+ if (!storageStrategy.containerExists(containerName)) {
+ throw cnfe(containerName);
+ }
+ storageStrategy.removeBlob(containerName, key);
+ }
+
+ @Override
+ public boolean deleteContainerIfEmpty(String containerName) {
+ boolean returnVal = true;
+ if (storageStrategy.containerExists(containerName)) {
+ try {
+ if (Iterables.isEmpty(storageStrategy.getBlobKeysInsideContainer(containerName)))
+ storageStrategy.deleteContainer(containerName);
+ else
+ returnVal = false;
+ } catch (IOException e) {
+ logger.error(e, "An error occurred loading blobs contained into container %s", containerName);
+ throw propagate(e);
+ }
+ }
+ return returnVal;
+ }
+
+ @Override
+ public boolean containerExists(String containerName) {
+ return storageStrategy.containerExists(containerName);
+ }
+
+ @Override
+ public PageSet<? extends StorageMetadata> list() {
+ Iterable<String> containers = storageStrategy.getAllContainerNames();
+
+ return new PageSetImpl<StorageMetadata>(transform(
+ containers, new Function<String, StorageMetadata>() {
+ public StorageMetadata apply(String name) {
+ MutableStorageMetadata cmd = create();
+ cmd.setName(name);
+ cmd.setType(StorageType.CONTAINER);
+ cmd.setLocation(storageStrategy.getLocation(name));
+ return cmd;
+ }
+ }), null);
+ }
+
+ private MutableStorageMetadata create() {
+ return new MutableStorageMetadataImpl();
+ }
+
+ @Override
+ public boolean createContainerInLocation(Location location, String name) {
+ return storageStrategy.createContainerInLocation(name, location);
+ }
+
+ private Blob loadBlob(final String container, final String key) {
+ logger.debug("Opening blob in container: %s - %s", container, key);
+ return storageStrategy.getBlob(container, key);
+ }
+
+ private static class DelimiterFilter implements Predicate<StorageMetadata> {
+ private final String prefix;
+ private final String delimiter;
+
+ public DelimiterFilter(String prefix, String delimiter) {
+ this.prefix = prefix;
+ this.delimiter = delimiter;
+ }
+
+ public boolean apply(StorageMetadata metadata) {
+ if (prefix == null)
+ return metadata.getName().indexOf(delimiter) == -1;
+ // ensure we don't accidentally append twice
+ String toMatch = prefix.endsWith("/") ? prefix : prefix + delimiter;
+ if (metadata.getName().startsWith(toMatch)) {
+ String unprefixedName = metadata.getName().replaceFirst(Pattern.quote(toMatch), "");
+ if (unprefixedName.equals("")) {
+ // we are the prefix in this case, return false
+ return false;
+ }
+ return unprefixedName.indexOf(delimiter) == -1;
+ }
+ return false;
+ }
+ }
+
+ private static class CommonPrefixes implements Function<StorageMetadata, String> {
+ private final String prefix;
+ private final String delimiter;
+ public static final String NO_PREFIX = "NO_PREFIX";
+
+ public CommonPrefixes(String prefix, String delimiter) {
+ this.prefix = prefix;
+ this.delimiter = delimiter;
+ }
+
+ public String apply(StorageMetadata metadata) {
+ String working = metadata.getName();
+ if (prefix != null) {
+ // ensure we don't accidentally append twice
+ String toMatch = prefix.endsWith("/") ? prefix : prefix + delimiter;
+ if (working.startsWith(toMatch)) {
+ working = working.replaceFirst(Pattern.quote(toMatch), "");
+ }
+ }
+ if (working.contains(delimiter)) {
+ return working.substring(0, working.indexOf(delimiter));
+ }
+ return NO_PREFIX;
+ }
+ }
+
+ private static HttpResponseException returnResponseException(int code) {
+ HttpResponse response = HttpResponse.builder().statusCode(code).build();
+ return new HttpResponseException(new HttpCommand(HttpRequest.builder().method("GET").endpoint("http://stub")
+ .build()), response);
+ }
+
+ @Override
+ public String putBlob(String containerName, Blob blob) {
+ checkNotNull(containerName, "containerName must be set");
+ checkNotNull(blob, "blob must be set");
+ String blobKey = blob.getMetadata().getName();
+
+ logger.debug("Put blob with key [%s] to container [%s]", blobKey, containerName);
+ if (!storageStrategy.containerExists(containerName)) {
+ throw cnfe(containerName);
+ }
+
+ try {
+ return storageStrategy.putBlob(containerName, blob);
+ } catch (IOException e) {
+ String message = e.getMessage();
+ if (message != null && message.startsWith("MD5 hash code mismatch")) {
+ HttpResponseException exception = returnResponseException(400);
+ exception.initCause(e);
+ throw exception;
+ }
+ logger.error(e, "An error occurred storing the new blob with name [%s] to container [%s].", blobKey,
+ containerName);
+ throw propagate(e);
+ }
+ }
+
+ private void copyPayloadHeadersToBlob(Payload payload, Blob blob) {
+ blob.getAllHeaders().putAll(contentMetadataCodec.toHeaders(payload.getContentMetadata()));
+ }
+
+ @Override
+ public boolean blobExists(String containerName, String key) {
+ if (!storageStrategy.containerExists(containerName))
+ throw cnfe(containerName);
+ return storageStrategy.blobExists(containerName, key);
+ }
+
+ @Override
+ public Blob getBlob(String containerName, String key, GetOptions options) {
+ logger.debug("Retrieving blob with key %s from container %s", key, containerName);
+ // If the container doesn't exist, an exception is thrown
+ if (!storageStrategy.containerExists(containerName)) {
+ logger.debug("Container %s does not exist", containerName);
+ throw cnfe(containerName);
+ }
+ // If the blob doesn't exist, a null object is returned
+ if (!storageStrategy.blobExists(containerName, key)) {
+ logger.debug("Item %s does not exist in container %s", key, containerName);
+ return null;
+ }
+
+ Blob blob = loadBlob(containerName, key);
+
+ if (options != null) {
+ if (options.getIfMatch() != null) {
+ if (!blob.getMetadata().getETag().equals(options.getIfMatch()))
+ throw returnResponseException(412);
+ }
+ if (options.getIfNoneMatch() != null) {
+ if (blob.getMetadata().getETag().equals(options.getIfNoneMatch()))
+ throw returnResponseException(304);
+ }
+ if (options.getIfModifiedSince() != null) {
+ Date modifiedSince = options.getIfModifiedSince();
+ if (blob.getMetadata().getLastModified().before(modifiedSince)) {
+ HttpResponse response = HttpResponse.builder().statusCode(304).build();
+ throw new HttpResponseException(String.format("%1$s is before %2$s", blob
+ .getMetadata().getLastModified(), modifiedSince), null, response);
+ }
+
+ }
+ if (options.getIfUnmodifiedSince() != null) {
+ Date unmodifiedSince = options.getIfUnmodifiedSince();
+ if (blob.getMetadata().getLastModified().after(unmodifiedSince)) {
+ HttpResponse response = HttpResponse.builder().statusCode(412).build();
+ throw new HttpResponseException(String.format("%1$s is after %2$s", blob
+ .getMetadata().getLastModified(), unmodifiedSince), null, response);
+ }
+ }
+ blob = copyBlob(blob);
+
+ if (options.getRanges() != null && !options.getRanges().isEmpty()) {
+ byte[] data;
+ try {
+ data = ByteStreams2.toByteArrayAndClose(blob.getPayload().openStream());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ for (String s : options.getRanges()) {
+ // HTTP uses a closed interval while Java array indexing uses a
+ // half-open interval.
+ int offset = 0;
+ int last = data.length - 1;
+ if (s.startsWith("-")) {
+ offset = last - Integer.parseInt(s.substring(1)) + 1;
+ } else if (s.endsWith("-")) {
+ offset = Integer.parseInt(s.substring(0, s.length() - 1));
+ } else if (s.contains("-")) {
+ String[] firstLast = s.split("\\-");
+ offset = Integer.parseInt(firstLast[0]);
+ last = Integer.parseInt(firstLast[1]);
+ } else {
+ throw new IllegalArgumentException("illegal range: " + s);
+ }
+
+ if (offset > last) {
+ throw new IllegalArgumentException("illegal range: " + s);
+ }
+ if (last + 1 > data.length) {
+ last = data.length - 1;
+ }
+ out.write(data, offset, last - offset + 1);
+ }
+ ContentMetadata cmd = blob.getPayload().getContentMetadata();
+ byte[] byteArray = out.toByteArray();
+ blob.setPayload(byteArray);
+ HttpUtils.copy(cmd, blob.getPayload().getContentMetadata());
+ blob.getPayload().getContentMetadata().setContentLength(Long.valueOf(byteArray.length));
+ }
+ }
+ checkNotNull(blob.getPayload(), "payload " + blob);
+ return blob;
+ }
+
+ @Override
+ public BlobMetadata blobMetadata(String containerName, String key) {
+ try {
+ Blob blob = getBlob(containerName, key);
+ return blob != null ? (BlobMetadata) BlobStoreUtils.copy(blob.getMetadata()) : null;
+ } catch (Exception e) {
+ if (size(Iterables.filter(getCausalChain(e), KeyNotFoundException.class)) >= 1)
+ return null;
+ throw e;
+ }
+ }
+
+ private Blob copyBlob(Blob blob) {
+ Blob returnVal = blobFactory.create(BlobStoreUtils.copy(blob.getMetadata()));
+ returnVal.setPayload(blob.getPayload());
+ copyPayloadHeadersToBlob(blob.getPayload(), returnVal);
+ return returnVal;
+ }
+
+ private boolean deleteAndVerifyContainerGone(final String container) {
+ storageStrategy.deleteContainer(container);
+ return storageStrategy.containerExists(container);
+ }
-public interface LocalBlobStore extends BlobStore {
+ @Override
+ public String putBlob(String containerName, Blob blob, PutOptions options) {
+ // TODO implement options
+ return putBlob(containerName, blob);
+ }
+ @Override
+ public boolean createContainerInLocation(Location location, String container, CreateContainerOptions options) {
+ if (options.isPublicRead())
+ throw new UnsupportedOperationException("publicRead");
+ return createContainerInLocation(location, container);
+ }
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/dfb583b6/blobstore/src/main/java/org/jclouds/blobstore/config/TransientBlobStoreContextModule.java
----------------------------------------------------------------------
diff --git a/blobstore/src/main/java/org/jclouds/blobstore/config/TransientBlobStoreContextModule.java b/blobstore/src/main/java/org/jclouds/blobstore/config/TransientBlobStoreContextModule.java
index 2f73741..7df30b5 100644
--- a/blobstore/src/main/java/org/jclouds/blobstore/config/TransientBlobStoreContextModule.java
+++ b/blobstore/src/main/java/org/jclouds/blobstore/config/TransientBlobStoreContextModule.java
@@ -16,12 +16,8 @@
*/
package org.jclouds.blobstore.config;
-import static org.jclouds.rest.config.BinderUtils.bindSyncToAsyncApi;
-
-import org.jclouds.blobstore.AsyncBlobStore;
import org.jclouds.blobstore.BlobRequestSigner;
import org.jclouds.blobstore.BlobStore;
-import org.jclouds.blobstore.LocalAsyncBlobStore;
import org.jclouds.blobstore.LocalBlobRequestSigner;
import org.jclouds.blobstore.LocalStorageStrategy;
import org.jclouds.blobstore.TransientStorageStrategy;
@@ -29,15 +25,9 @@ import org.jclouds.blobstore.attr.ConsistencyModel;
import com.google.inject.AbstractModule;
-/**
- * Configures the {@link TransientBlobStoreContext}; requires {@link TransientAsyncBlobStore} bound.
- */
public class TransientBlobStoreContextModule extends AbstractModule {
@Override
protected void configure() {
- bind(AsyncBlobStore.class).to(LocalAsyncBlobStore.class).asEagerSingleton();
- // forward all requests from TransientBlobStore to TransientAsyncBlobStore. needs above binding as cannot proxy a class
- bindSyncToAsyncApi(binder(), LocalBlobStore.class, AsyncBlobStore.class);
install(new BlobStoreObjectModule());
bind(BlobStore.class).to(LocalBlobStore.class);
bind(ConsistencyModel.class).toInstance(ConsistencyModel.STRICT);
http://git-wip-us.apache.org/repos/asf/jclouds/blob/dfb583b6/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseAsyncBlobStore.java
----------------------------------------------------------------------
diff --git a/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseAsyncBlobStore.java b/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseAsyncBlobStore.java
deleted file mode 100644
index 8bddf7f..0000000
--- a/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseAsyncBlobStore.java
+++ /dev/null
@@ -1,310 +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.blobstore.internal;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
-import static org.jclouds.util.Predicates2.retry;
-
-import java.util.Set;
-import java.util.concurrent.Callable;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-
-import org.jclouds.Constants;
-import org.jclouds.blobstore.AsyncBlobStore;
-import org.jclouds.blobstore.BlobStoreContext;
-import org.jclouds.blobstore.ContainerNotFoundException;
-import org.jclouds.blobstore.domain.Blob;
-import org.jclouds.blobstore.domain.BlobBuilder;
-import org.jclouds.blobstore.domain.PageSet;
-import org.jclouds.blobstore.domain.StorageMetadata;
-import org.jclouds.blobstore.options.ListContainerOptions;
-import org.jclouds.blobstore.util.BlobUtils;
-import org.jclouds.collect.Memoized;
-import org.jclouds.domain.Location;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-
-/**
- *
- * @deprecated will be removed in jclouds 1.7, as async interfaces are no longer
- * supported. Please use {@link org.jclouds.blobstore.BlobStore}
- */
-@Deprecated
-public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
-
- protected final BlobStoreContext context;
- protected final BlobUtils blobUtils;
- protected final ListeningExecutorService userExecutor;
- protected final Supplier<Location> defaultLocation;
- protected final Supplier<Set<? extends Location>> locations;
-
- @Inject
- protected BaseAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
- @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, Supplier<Location> defaultLocation,
- @Memoized Supplier<Set<? extends Location>> locations) {
- this.context = checkNotNull(context, "context");
- this.blobUtils = checkNotNull(blobUtils, "blobUtils");
- this.userExecutor = checkNotNull(userExecutor, "userExecutor");
- this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation");
- this.locations = checkNotNull(locations, "locations");
- }
-
- @Override
- public BlobStoreContext getContext() {
- return context;
- }
-
- /**
- * invokes {@link BlobUtilsImpl#blobBuilder }
- */
- @Override
- public BlobBuilder blobBuilder(String name) {
- return blobUtils.blobBuilder().name(name);
- }
-
- /**
- * This implementation invokes
- * {@link #list(String,org.jclouds.blobstore.options.ListContainerOptions)}
- *
- * @param container
- * container name
- */
- @Override
- public ListenableFuture<PageSet<? extends StorageMetadata>> list(String container) {
- return this.list(container, org.jclouds.blobstore.options.ListContainerOptions.NONE);
- }
-
- /**
- * This implementation invokes {@link #countBlobs} with the
- * {@link ListContainerOptions#recursive} option.
- *
- * @param container
- * container name
- */
- @Override
- public ListenableFuture<Long> countBlobs(String container) {
- return countBlobs(container, recursive());
- }
-
- /**
- * This implementation invokes {@link BlobUtilsImpl#countBlobs}
- *
- * @param container
- * container name
- */
- @Override
- public ListenableFuture<Long> countBlobs(final String containerName, final ListContainerOptions options) {
- return userExecutor.submit(new Callable<Long>() {
- public Long call() throws Exception {
- return blobUtils.countBlobs(containerName, options);
- }
-
- @Override
- public String toString() {
- return "countBlobs(" + containerName + ")";
- }
- });
- }
-
- /**
- * This implementation invokes {@link #clearContainer} with the
- * {@link ListContainerOptions#recursive} option.
- *
- * @param container
- * container name
- */
- @Override
- public ListenableFuture<Void> clearContainer(final String container) {
- return clearContainer(container, recursive());
- }
-
- /**
- * This implementation invokes {@link BlobUtilsImpl#clearContainer}
- *
- * @param container
- * container name
- */
- @Override
- public ListenableFuture<Void> clearContainer(final String containerName, final ListContainerOptions options) {
- return userExecutor.submit(new Callable<Void>() {
-
- public Void call() throws Exception {
- blobUtils.clearContainer(containerName, options);
- return null;
- }
-
- @Override
- public String toString() {
- return "clearContainer(" + containerName + ")";
- }
- });
- }
-
- /**
- * This implementation invokes {@link BlobUtilsImpl#deleteDirectory}.
- *
- * @param container
- * container name
- */
- @Override
- public ListenableFuture<Void> deleteDirectory(final String containerName, final String directory) {
- return userExecutor.submit(new Callable<Void>() {
-
- public Void call() throws Exception {
- blobUtils.deleteDirectory(containerName, directory);
- return null;
- }
-
- @Override
- public String toString() {
- return "deleteDirectory(" + containerName + "," + directory + ")";
- }
- });
- }
-
- /**
- * This implementation invokes {@link BlobUtilsImpl#directoryExists}
- *
- * @param container
- * container name
- * @param directory
- * virtual path
- */
- public ListenableFuture<Boolean> directoryExists(final String containerName, final String directory) {
- return userExecutor.submit(new Callable<Boolean>() {
-
- public Boolean call() throws Exception {
- return blobUtils.directoryExists(containerName, directory);
- }
-
- @Override
- public String toString() {
- return "directoryExists(" + containerName + "," + directory + ")";
- }
- });
- }
-
- /**
- * This implementation invokes {@link BlobUtilsImpl#createDirectory}
- *
- * @param container
- * container name
- * @param directory
- * virtual path
- */
-
- public ListenableFuture<Void> createDirectory(final String containerName, final String directory) {
- return blobUtils.directoryExists(containerName, directory) ? Futures.immediateFuture((Void) null)
- : userExecutor.submit(new Callable<Void>() {
- public Void call() throws Exception {
- blobUtils.createDirectory(containerName, directory);
- return null;
- }
-
- @Override
- public String toString() {
- return "createDirectory(" + containerName + "," + directory + ")";
- }
- });
- }
-
- /**
- * This implementation invokes
- * {@link #getBlob(String,String,org.jclouds.blobstore.options.GetOptions)}
- *
- * @param container
- * container name
- * @param key
- * blob key
- */
- @Override
- public ListenableFuture<Blob> getBlob(String container, String key) {
- return getBlob(container, key, org.jclouds.blobstore.options.GetOptions.NONE);
- }
-
- /**
- * This implementation invokes {@link #deleteAndEnsurePathGone}
- *
- * @param container
- * bucket name
- */
- @Override
- public ListenableFuture<Void> deleteContainer(final String container) {
- return userExecutor.submit(new Callable<Void>() {
-
- public Void call() throws Exception {
- deletePathAndEnsureGone(container);
- return null;
- }
-
- @Override
- public String toString() {
- return "deleteContainer(" + container + ")";
- }
- });
- }
-
- @Override
- public ListenableFuture<Boolean> deleteContainerIfEmpty(final String container) {
- return userExecutor.submit(new Callable<Boolean>() {
-
- public Boolean call() throws Exception {
- return deleteAndVerifyContainerGone(container);
- }
-
- @Override
- public String toString() {
- return "deleteContainerIfEmpty(" + container + ")";
- }
- });
- }
-
- protected void deletePathAndEnsureGone(String path) {
- checkState(retry(new Predicate<String>() {
- public boolean apply(String in) {
- try {
- blobUtils.clearContainer(in, recursive());
- return deleteAndVerifyContainerGone(in);
- } catch (ContainerNotFoundException e) {
- return true;
- }
- }
- }, 30000).apply(path), "%s still exists after deleting!", path);
- }
-
- @Override
- public ListenableFuture<Set<? extends Location>> listAssignableLocations() {
- return Futures.<Set<? extends Location>> immediateFuture(locations.get());
- }
-
- /**
- * Delete a container if it is empty.
- *
- * @param container what to delete
- * @return true if the container was deleted or does not exist
- */
- protected abstract boolean deleteAndVerifyContainerGone(String container);
-
-}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/dfb583b6/blobstore/src/test/java/org/jclouds/blobstore/TransientBlobRequestSignerTest.java
----------------------------------------------------------------------
diff --git a/blobstore/src/test/java/org/jclouds/blobstore/TransientBlobRequestSignerTest.java b/blobstore/src/test/java/org/jclouds/blobstore/TransientBlobRequestSignerTest.java
index ff833ab..fb1e89b 100644
--- a/blobstore/src/test/java/org/jclouds/blobstore/TransientBlobRequestSignerTest.java
+++ b/blobstore/src/test/java/org/jclouds/blobstore/TransientBlobRequestSignerTest.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import javax.inject.Provider;
import org.jclouds.apis.ApiMetadata;
+import org.jclouds.blobstore.config.LocalBlobStore;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobBuilder;
import org.jclouds.http.HttpRequest;
@@ -40,7 +41,7 @@ import com.google.common.io.ByteSource;
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "TransientBlobRequestSignerTest")
-public class TransientBlobRequestSignerTest extends BaseAsyncClientTest<LocalAsyncBlobStore> {
+public class TransientBlobRequestSignerTest extends BaseAsyncClientTest<LocalBlobStore> {
private BlobRequestSigner signer;
private Provider<BlobBuilder> blobFactory;
http://git-wip-us.apache.org/repos/asf/jclouds/blob/dfb583b6/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/config/AzureBlobStoreContextModule.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/config/AzureBlobStoreContextModule.java b/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/config/AzureBlobStoreContextModule.java
index aef156d..9721617 100644
--- a/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/config/AzureBlobStoreContextModule.java
+++ b/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/config/AzureBlobStoreContextModule.java
@@ -24,11 +24,9 @@ import org.jclouds.azureblob.AzureBlobClient;
import org.jclouds.azureblob.blobstore.AzureBlobRequestSigner;
import org.jclouds.azureblob.blobstore.AzureBlobStore;
import org.jclouds.azureblob.domain.PublicAccess;
-import org.jclouds.blobstore.AsyncBlobStore;
import org.jclouds.blobstore.BlobRequestSigner;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.attr.ConsistencyModel;
-import org.jclouds.blobstore.internal.SubmissionAsyncBlobStore;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
@@ -42,7 +40,6 @@ public class AzureBlobStoreContextModule extends AbstractModule {
@Override
protected void configure() {
bind(ConsistencyModel.class).toInstance(ConsistencyModel.STRICT);
- bind(AsyncBlobStore.class).to(SubmissionAsyncBlobStore.class).in(Scopes.SINGLETON);
bind(BlobStore.class).to(AzureBlobStore.class).in(Scopes.SINGLETON);
bind(BlobRequestSigner.class).to(AzureBlobRequestSigner.class);
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/dfb583b6/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/config/HPCloudObjectStorageBlobStoreContextModule.java
----------------------------------------------------------------------
diff --git a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/config/HPCloudObjectStorageBlobStoreContextModule.java b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/config/HPCloudObjectStorageBlobStoreContextModule.java
index e33788e..a636b4d 100644
--- a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/config/HPCloudObjectStorageBlobStoreContextModule.java
+++ b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/config/HPCloudObjectStorageBlobStoreContextModule.java
@@ -26,10 +26,8 @@ import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
-import org.jclouds.blobstore.AsyncBlobStore;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.attr.ConsistencyModel;
-import org.jclouds.blobstore.internal.SubmissionAsyncBlobStore;
import org.jclouds.hpcloud.objectstorage.HPCloudObjectStorageApi;
import org.jclouds.hpcloud.objectstorage.blobstore.HPCloudObjectStorageBlobStore;
import org.jclouds.hpcloud.objectstorage.blobstore.functions.HPCloudObjectStorageObjectToBlobMetadata;
@@ -46,7 +44,6 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.inject.Provides;
-import com.google.inject.Scopes;
public class HPCloudObjectStorageBlobStoreContextModule extends SwiftBlobStoreContextModule {
@@ -96,7 +93,6 @@ public class HPCloudObjectStorageBlobStoreContextModule extends SwiftBlobStoreCo
protected void configure() {
bind(ConsistencyModel.class).toInstance(ConsistencyModel.EVENTUAL);
bind(BlobStore.class).to(HPCloudObjectStorageBlobStore.class);
- bind(AsyncBlobStore.class).to(SubmissionAsyncBlobStore.class).in(Scopes.SINGLETON);
bind(ObjectToBlobMetadata.class).to(HPCloudObjectStorageObjectToBlobMetadata.class);
}
}