JCLOUDS-40 unasync atmos.

This commit is contained in:
Adrian Cole 2014-10-03 21:38:57 -07:00 committed by Adrian Cole
parent 9df0cd24c6
commit 9b71a9dcb8
13 changed files with 179 additions and 859 deletions

View File

@ -91,7 +91,6 @@
</goals>
<configuration>
<systemPropertyVariables>
<test.initializer>${test.initializer}</test.initializer>
<jclouds.blobstore.httpstream.url>${jclouds.blobstore.httpstream.url}</jclouds.blobstore.httpstream.url>
<jclouds.blobstore.httpstream.md5>${jclouds.blobstore.httpstream.md5}</jclouds.blobstore.httpstream.md5>
<test.atmos.endpoint>${test.atmos.endpoint}</test.atmos.endpoint>

View File

@ -15,6 +15,7 @@
* limitations under the License.
*/
package org.jclouds.atmos;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import static org.jclouds.reflect.Reflection2.typeToken;
@ -23,27 +24,15 @@ import java.net.URI;
import java.util.Properties;
import org.jclouds.atmos.blobstore.config.AtmosBlobStoreContextModule;
import org.jclouds.atmos.config.AtmosRestClientModule;
import org.jclouds.atmos.config.AtmosHttpApiModule;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.rest.internal.BaseHttpApiMetadata;
import org.jclouds.rest.internal.BaseRestApiMetadata;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
import com.google.inject.Module;
/**
* Implementation of {@link ApiMetadata} for EMC Atmos API
*/
public class AtmosApiMetadata extends BaseRestApiMetadata {
/**
* @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(AtmosClient.class)} as
* {@link AtmosAsyncClient} interface will be removed in jclouds 1.7.
*/
@Deprecated
public static final TypeToken<org.jclouds.rest.RestContext<AtmosClient, AtmosAsyncClient>> CONTEXT_TOKEN = new TypeToken<org.jclouds.rest.RestContext<AtmosClient, AtmosAsyncClient>>() {
private static final long serialVersionUID = 1L;
};
public class AtmosApiMetadata extends BaseHttpApiMetadata {
private static Builder builder() {
return new Builder();
@ -69,10 +58,9 @@ public class AtmosApiMetadata extends BaseRestApiMetadata {
return properties;
}
public static class Builder extends BaseRestApiMetadata.Builder<Builder> {
@SuppressWarnings("deprecation")
public static class Builder extends BaseHttpApiMetadata.Builder<AtmosClient, Builder> {
protected Builder() {
super(AtmosClient.class, AtmosAsyncClient.class);
super(AtmosClient.class);
id("atmos")
.name("EMC's Atmos API")
.identityName("Subtenant ID (UID)")
@ -82,7 +70,7 @@ public class AtmosApiMetadata extends BaseRestApiMetadata {
.defaultEndpoint("https://accesspoint.atmosonline.com")
.defaultProperties(AtmosApiMetadata.defaultProperties())
.view(typeToken(BlobStoreContext.class))
.defaultModules(ImmutableSet.<Class<? extends Module>>of(AtmosRestClientModule.class, AtmosBlobStoreContextModule.class));
.defaultModules(ImmutableSet.<Class<? extends Module>>of(AtmosHttpApiModule.class, AtmosBlobStoreContextModule.class));
}
@Override

View File

@ -1,230 +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.atmos;
import static com.google.common.net.HttpHeaders.EXPECT;
import java.io.Closeable;
import java.net.URI;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.atmos.binders.BindMetadataToHeaders;
import org.jclouds.atmos.domain.AtmosObject;
import org.jclouds.atmos.domain.BoundedSet;
import org.jclouds.atmos.domain.DirectoryEntry;
import org.jclouds.atmos.domain.SystemMetadata;
import org.jclouds.atmos.domain.UserMetadata;
import org.jclouds.atmos.fallbacks.TrueOn404FalseOnPathNotEmpty;
import org.jclouds.atmos.filters.SignRequest;
import org.jclouds.atmos.functions.AtmosObjectName;
import org.jclouds.atmos.functions.ParseDirectoryListFromContentAndHeaders;
import org.jclouds.atmos.functions.ParseNullableURIFromListOrLocationHeaderIf20x;
import org.jclouds.atmos.functions.ParseObjectFromHeadersAndHttpContent;
import org.jclouds.atmos.functions.ParseSystemMetadataFromHeaders;
import org.jclouds.atmos.functions.ParseUserMetadataFromHeaders;
import org.jclouds.atmos.functions.ReturnTrueIfGroupACLIsOtherRead;
import org.jclouds.atmos.options.ListOptions;
import org.jclouds.atmos.options.PutOptions;
import org.jclouds.blobstore.BlobStoreFallbacks.NullOnKeyAlreadyExists;
import org.jclouds.blobstore.BlobStoreFallbacks.ThrowContainerNotFoundOn404;
import org.jclouds.blobstore.BlobStoreFallbacks.ThrowKeyNotFoundOn404;
import org.jclouds.http.options.GetOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Provides;
/**
* Provides asynchronous access to EMC Atmos Online Storage resources via their REST API.
* <p/>
*
* @see AtmosClient
* @see <a href="https://community.emc.com/community/labs/atmos_online" />
*
* @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(AtmosClient.class)} as
* {@link AtmosAsyncClient} interface will be removed in jclouds 1.7.
*/
@Deprecated
@RequestFilters(SignRequest.class)
@Path("/rest/namespace")
public interface AtmosAsyncClient extends Closeable {
/**
* Creates a default implementation of AtmosObject
*/
@Provides
AtmosObject newObject();
/**
* @see AtmosClient#listDirectories
*/
@Named("ListDirectory")
@GET
@Path("/")
@ResponseParser(ParseDirectoryListFromContentAndHeaders.class)
@Consumes(MediaType.TEXT_XML)
ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectories(ListOptions... options);
/**
* @see AtmosClient#listDirectory
*/
@Named("ListDirectory")
@GET
@Path("/{directoryName}/")
@ResponseParser(ParseDirectoryListFromContentAndHeaders.class)
@Fallback(ThrowContainerNotFoundOn404.class)
@Consumes(MediaType.TEXT_XML)
ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectory(
@PathParam("directoryName") String directoryName, ListOptions... options);
/**
* @see AtmosClient#createDirectory
*/
@Named("CreateDirectory")
@POST
@Path("/{directoryName}/")
@Fallback(NullOnKeyAlreadyExists.class)
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Consumes(MediaType.WILDCARD)
ListenableFuture<URI> createDirectory(@PathParam("directoryName") String directoryName, PutOptions... options);
/**
* @see AtmosClient#createFile
*/
@Nullable
@Named("CreateObject")
@POST
@Path("/{parent}/{name}")
@Headers(keys = EXPECT, values = "100-continue")
@ResponseParser(ParseNullableURIFromListOrLocationHeaderIf20x.class)
@Consumes(MediaType.WILDCARD)
ListenableFuture<URI> createFile(
@PathParam("parent") String parent,
@PathParam("name") @ParamParser(AtmosObjectName.class) @BinderParam(BindMetadataToHeaders.class) AtmosObject object,
PutOptions... options);
/**
* @see AtmosClient#updateFile
*/
@Named("UpdateObject")
@PUT
@Path("/{parent}/{name}")
@Headers(keys = EXPECT, values = "100-continue")
@Fallback(ThrowKeyNotFoundOn404.class)
@Consumes(MediaType.WILDCARD)
ListenableFuture<Void> updateFile(
@PathParam("parent") String parent,
@PathParam("name") @ParamParser(AtmosObjectName.class) @BinderParam(BindMetadataToHeaders.class) AtmosObject object,
PutOptions... options);
/**
* @see AtmosClient#readFile
*/
@Named("ReadObject")
@GET
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
@Fallback(NullOnNotFoundOr404.class)
@Path("/{path}")
@Consumes(MediaType.WILDCARD)
ListenableFuture<AtmosObject> readFile(@PathParam("path") String path, GetOptions... options);
/**
* @see AtmosClient#headFile
*/
@Named("GetObjectMetadata")
@HEAD
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
@Fallback(NullOnNotFoundOr404.class)
@Path("/{path}")
@Consumes(MediaType.WILDCARD)
ListenableFuture<AtmosObject> headFile(@PathParam("path") String path);
/**
* @see AtmosClient#getSystemMetadata
*/
@Named("GetSystemMetadata")
@HEAD
@ResponseParser(ParseSystemMetadataFromHeaders.class)
@Fallback(NullOnNotFoundOr404.class)
// currently throws 403 errors @QueryParams(keys = "metadata/system")
@Path("/{path}")
@Consumes(MediaType.WILDCARD)
ListenableFuture<SystemMetadata> getSystemMetadata(@PathParam("path") String path);
/**
* @see AtmosClient#getUserMetadata
*/
@Named("GetUserMetadata")
@HEAD
@ResponseParser(ParseUserMetadataFromHeaders.class)
@Fallback(NullOnNotFoundOr404.class)
@Path("/{path}")
@QueryParams(keys = "metadata/user")
@Consumes(MediaType.WILDCARD)
ListenableFuture<UserMetadata> getUserMetadata(@PathParam("path") String path);
/**
* @see AtmosClient#deletePath
*/
@Named("DeleteObject")
@DELETE
@Fallback(TrueOn404FalseOnPathNotEmpty.class)
@Path("/{path}")
@Consumes(MediaType.WILDCARD)
ListenableFuture<Boolean> deletePath(@PathParam("path") String path);
/**
* @see AtmosClient#pathExists
*/
@Named("GetObjectMetadata")
@HEAD
@Fallback(FalseOnNotFoundOr404.class)
@Path("/{path}")
@Consumes(MediaType.WILDCARD)
ListenableFuture<Boolean> pathExists(@PathParam("path") String path);
/**
* @see AtmosClient#isPublic
*/
@Named("GetObjectMetadata")
@HEAD
@ResponseParser(ReturnTrueIfGroupACLIsOtherRead.class)
@Path("/{path}")
@Consumes(MediaType.WILDCARD)
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> isPublic(@PathParam("path") String path);
}

View File

@ -16,57 +16,162 @@
*/
package org.jclouds.atmos;
import static com.google.common.net.HttpHeaders.EXPECT;
import static org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import static org.jclouds.Fallbacks.NullOnNotFoundOr404;
import static org.jclouds.blobstore.BlobStoreFallbacks.NullOnKeyAlreadyExists;
import static org.jclouds.blobstore.BlobStoreFallbacks.ThrowContainerNotFoundOn404;
import static org.jclouds.blobstore.BlobStoreFallbacks.ThrowKeyNotFoundOn404;
import java.io.Closeable;
import java.net.URI;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.atmos.binders.BindMetadataToHeaders;
import org.jclouds.atmos.domain.AtmosObject;
import org.jclouds.atmos.domain.BoundedSet;
import org.jclouds.atmos.domain.DirectoryEntry;
import org.jclouds.atmos.domain.SystemMetadata;
import org.jclouds.atmos.domain.UserMetadata;
import org.jclouds.atmos.fallbacks.TrueOn404FalseOnPathNotEmpty;
import org.jclouds.atmos.filters.SignRequest;
import org.jclouds.atmos.functions.AtmosObjectName;
import org.jclouds.atmos.functions.ParseDirectoryListFromContentAndHeaders;
import org.jclouds.atmos.functions.ParseNullableURIFromListOrLocationHeaderIf20x;
import org.jclouds.atmos.functions.ParseObjectFromHeadersAndHttpContent;
import org.jclouds.atmos.functions.ParseSystemMetadataFromHeaders;
import org.jclouds.atmos.functions.ParseUserMetadataFromHeaders;
import org.jclouds.atmos.functions.ReturnTrueIfGroupACLIsOtherRead;
import org.jclouds.atmos.options.ListOptions;
import org.jclouds.atmos.options.PutOptions;
import org.jclouds.http.options.GetOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import com.google.inject.Provides;
/**
* Provides access to EMC Atmos Online Storage resources via their REST API.
* <p/>
*
* @see AtmosAsyncClient
* @see <a href="https://community.emc.com/community/labs/atmos_online" />
*/
/** Provides access to EMC Atmos Online Storage resources via their REST API. */
@RequestFilters(SignRequest.class)
@Path("/rest/namespace")
public interface AtmosClient extends Closeable {
/**
* Creates a default implementation of AtmosObject
*/
@Provides
AtmosObject newObject();
@Named("ListDirectory")
@GET
@Path("/")
@ResponseParser(ParseDirectoryListFromContentAndHeaders.class)
@Consumes(MediaType.TEXT_XML)
BoundedSet<? extends DirectoryEntry> listDirectories(ListOptions... options);
BoundedSet<? extends DirectoryEntry> listDirectory(String directoryName, ListOptions... options);
@Named("ListDirectory")
@GET
@Path("/{directoryName}/")
@ResponseParser(ParseDirectoryListFromContentAndHeaders.class)
@Fallback(ThrowContainerNotFoundOn404.class)
@Consumes(MediaType.TEXT_XML)
BoundedSet<? extends DirectoryEntry> listDirectory(
@PathParam("directoryName") String directoryName, ListOptions... options);
URI createDirectory(String directoryName, PutOptions... options);
@Named("CreateDirectory")
@POST
@Path("/{directoryName}/")
@Fallback(NullOnKeyAlreadyExists.class)
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Consumes(MediaType.WILDCARD)
URI createDirectory(@PathParam("directoryName") String directoryName, PutOptions... options);
@Nullable
URI createFile(String parent, AtmosObject object, PutOptions... options);
@Named("CreateObject")
@POST
@Path("/{parent}/{name}")
@Headers(keys = EXPECT, values = "100-continue")
@ResponseParser(ParseNullableURIFromListOrLocationHeaderIf20x.class)
@Consumes(MediaType.WILDCARD)
URI createFile(@PathParam("parent") String parent, @PathParam("name") @ParamParser(AtmosObjectName.class)
@BinderParam(BindMetadataToHeaders.class) AtmosObject object, PutOptions... options);
void updateFile(String parent, AtmosObject object, PutOptions... options);
@Named("UpdateObject")
@PUT
@Path("/{parent}/{name}")
@Headers(keys = EXPECT, values = "100-continue")
@Fallback(ThrowKeyNotFoundOn404.class)
@Consumes(MediaType.WILDCARD)
void updateFile(@PathParam("parent") String parent, @PathParam("name") @ParamParser(AtmosObjectName.class)
@BinderParam(BindMetadataToHeaders.class) AtmosObject object, PutOptions... options);
AtmosObject readFile(String path, GetOptions... options);
@Named("ReadObject")
@GET
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
@Fallback(NullOnNotFoundOr404.class)
@Path("/{path}")
@Consumes(MediaType.WILDCARD)
AtmosObject readFile(@PathParam("path") String path, GetOptions... options);
AtmosObject headFile(String path);
@Named("GetObjectMetadata")
@HEAD
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
@Fallback(NullOnNotFoundOr404.class)
@Path("/{path}")
@Consumes(MediaType.WILDCARD)
AtmosObject headFile(@PathParam("path") String path);
SystemMetadata getSystemMetadata(String path);
@Named("GetSystemMetadata")
@HEAD
@ResponseParser(ParseSystemMetadataFromHeaders.class)
@Fallback(NullOnNotFoundOr404.class)
// currently throws 403 errors @QueryParams(keys = "metadata/system")
@Path("/{path}")
@Consumes(MediaType.WILDCARD)
SystemMetadata getSystemMetadata(@PathParam("path") String path);
UserMetadata getUserMetadata(String path);
@Named("GetUserMetadata")
@HEAD
@ResponseParser(ParseUserMetadataFromHeaders.class)
@Fallback(NullOnNotFoundOr404.class)
@Path("/{path}")
@QueryParams(keys = "metadata/user")
@Consumes(MediaType.WILDCARD)
UserMetadata getUserMetadata(@PathParam("path") String path);
void deletePath(String path);
@Named("DeleteObject")
@DELETE
@Fallback(TrueOn404FalseOnPathNotEmpty.class)
@Path("/{path}")
@Consumes(MediaType.WILDCARD)
boolean deletePath(@PathParam("path") String path);
boolean pathExists(String path);
@Named("GetObjectMetadata")
@HEAD
@Fallback(FalseOnNotFoundOr404.class)
@Path("/{path}")
@Consumes(MediaType.WILDCARD)
boolean pathExists(@PathParam("path") String path);
boolean isPublic(String path);
@Named("GetObjectMetadata")
@HEAD
@ResponseParser(ReturnTrueIfGroupACLIsOtherRead.class)
@Path("/{path}")
@Consumes(MediaType.WILDCARD)
@Fallback(FalseOnNotFoundOr404.class)
boolean isPublic(@PathParam("path") String path);
}

View File

@ -1,289 +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.atmos.blobstore;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.transform;
import static org.jclouds.atmos.options.PutOptions.Builder.publicRead;
import java.net.URI;
import java.util.Set;
import java.util.concurrent.Callable;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.atmos.AtmosAsyncClient;
import org.jclouds.atmos.AtmosClient;
import org.jclouds.atmos.blobstore.functions.BlobStoreListOptionsToListOptions;
import org.jclouds.atmos.blobstore.functions.BlobToObject;
import org.jclouds.atmos.blobstore.functions.DirectoryEntryListToResourceMetadataList;
import org.jclouds.atmos.blobstore.functions.ObjectToBlob;
import org.jclouds.atmos.blobstore.functions.ObjectToBlobMetadata;
import org.jclouds.atmos.domain.AtmosObject;
import org.jclouds.atmos.domain.BoundedSet;
import org.jclouds.atmos.domain.DirectoryEntry;
import org.jclouds.atmos.options.ListOptions;
import org.jclouds.atmos.util.AtmosUtils;
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.functions.BlobToHttpGetOptions;
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
import org.jclouds.blobstore.options.CreateContainerOptions;
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.crypto.Crypto;
import org.jclouds.domain.Location;
import org.jclouds.http.options.GetOptions;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Supplier;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
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 AtmosBlobStore}
*/
@Deprecated
@Singleton
public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
private final AtmosAsyncClient async;
private final AtmosClient sync;
private final ObjectToBlob object2Blob;
private final ObjectToBlobMetadata object2BlobMd;
private final BlobToObject blob2Object;
private final BlobStoreListOptionsToListOptions container2ContainerListOptions;
private final DirectoryEntryListToResourceMetadataList container2ResourceList;
private final Crypto crypto;
private final BlobToHttpGetOptions blob2ObjectGetOptions;
private final Provider<FetchBlobMetadata> fetchBlobMetadataProvider;
private final LoadingCache<String, Boolean> isPublic;
@Inject
AtmosAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, Supplier<Location> defaultLocation,
@Memoized Supplier<Set<? extends Location>> locations, AtmosAsyncClient async, AtmosClient sync,
ObjectToBlob object2Blob, ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object,
BlobStoreListOptionsToListOptions container2ContainerListOptions,
DirectoryEntryListToResourceMetadataList container2ResourceList, Crypto crypto,
BlobToHttpGetOptions blob2ObjectGetOptions, Provider<FetchBlobMetadata> fetchBlobMetadataProvider,
LoadingCache<String, Boolean> isPublic) {
super(context, blobUtils, userExecutor, defaultLocation, locations);
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
this.sync = checkNotNull(sync, "sync");
this.async = checkNotNull(async, "async");
this.container2ContainerListOptions = checkNotNull(container2ContainerListOptions,
"container2ContainerListOptions");
this.container2ResourceList = checkNotNull(container2ResourceList, "container2ResourceList");
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd");
this.crypto = checkNotNull(crypto, "crypto");
this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider, "fetchBlobMetadataProvider");
this.isPublic = checkNotNull(isPublic, "isPublic");
}
/**
* This implementation invokes {@link AtmosAsyncClient#headFile}
*/
@Override
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
return transform(async.headFile(container + "/" + key), new Function<AtmosObject, BlobMetadata>() {
@Override
public BlobMetadata apply(AtmosObject from) {
return object2BlobMd.apply(from);
}
}, userExecutor);
}
/**
* This implementation invokes {@link AtmosAsyncClient#createDirectory}
* <p/>
* Note location is ignored
*/
@Override
public ListenableFuture<Boolean> createContainerInLocation(Location location, String container) {
return transform(async.createDirectory(container), new Function<URI, Boolean>() {
public Boolean apply(URI from) {
return from != null;
}
}, userExecutor);
}
/**
* This implementation invokes {@link AtmosAsyncClient#createDirectory}
*/
@Override
public ListenableFuture<Void> createDirectory(String container, String directory) {
return transform(async.createDirectory(container + "/" + directory), new Function<URI, Void>() {
public Void apply(URI from) {
return null; // no etag
}
}, userExecutor);
}
/**
* This implementation invokes {@link AtmosAsyncClient#deletePath} followed by
* {@link AtmosAsyncClient#pathExists} until it is true.
*/
protected boolean deleteAndVerifyContainerGone(final String container) {
sync.deletePath(container + "/");
return !sync.pathExists(container + "/");
}
/**
* This implementation invokes {@link AtmosAsyncClient#pathExists}
*/
@Override
public ListenableFuture<Boolean> containerExists(String container) {
return async.pathExists(container + "/");
}
/**
* This implementation invokes {@link AtmosAsyncClient#pathExists}
*/
@Override
public ListenableFuture<Boolean> directoryExists(String container, String directory) {
return async.pathExists(container + "/" + directory + "/");
}
/**
* This implementation invokes {@link #removeBlob}
*/
@Override
public ListenableFuture<Void> deleteDirectory(String containerName, String directory) {
return removeBlob(containerName, directory + "/");
}
/**
* This implementation invokes {@link AtmosAsyncClient#pathExists}
*
* @param container
* container
* @param key
* file name
*/
@Override
public ListenableFuture<Boolean> blobExists(String container, String key) {
return async.pathExists(container + "/" + key);
}
/**
* This implementation invokes {@link AtmosAsyncClient#readFile}
*/
@Override
public ListenableFuture<Blob> getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions options) {
GetOptions httpOptions = blob2ObjectGetOptions.apply(options);
ListenableFuture<AtmosObject> returnVal = async.readFile(container + "/" + key, httpOptions);
return transform(returnVal, object2Blob, userExecutor);
}
/**
* This implementation invokes {@link AtmosAsyncClient#listDirectories}
*/
@Override
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
return transform(async.listDirectories(), container2ResourceList, userExecutor);
}
/**
* This implementation invokes {@link AtmosAsyncClient#listDirectory}
*/
@Override
public ListenableFuture<PageSet<? extends StorageMetadata>> list(String container,
org.jclouds.blobstore.options.ListContainerOptions options) {
container = AtmosUtils.adjustContainerIfDirOptionPresent(container, options);
ListOptions nativeOptions = container2ContainerListOptions.apply(options);
ListenableFuture<BoundedSet<? extends DirectoryEntry>> returnVal = async.listDirectory(container, nativeOptions);
ListenableFuture<PageSet<? extends StorageMetadata>> list = transform(returnVal, container2ResourceList,
userExecutor);
return options.isDetailed() ? transform(list,
fetchBlobMetadataProvider.get().setContainerName(container)) : list;
}
/**
* This implementation invokes {@link AtmosAsyncClient#createFile}
* <p/>
* Since there is no etag support in atmos, we just return the path.
*/
@Override
public ListenableFuture<String> putBlob(final String container, final Blob blob) {
final org.jclouds.atmos.options.PutOptions options = new org.jclouds.atmos.options.PutOptions();
try {
if (isPublic.getUnchecked(container + "/"))
options.publicRead();
} catch (CacheLoader.InvalidCacheLoadException e) {
// nulls not permitted
}
return userExecutor.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return AtmosUtils.putBlob(sync, crypto, blob2Object, container, blob, options);
}
@Override
public String toString() {
return "putBlob(" + container + "," + blob.getMetadata().getName() + ")";
}
});
}
/**
* This implementation invokes {@link AtmosAsyncClient#deletePath}
*/
@Override
public ListenableFuture<Void> removeBlob(String container, String key) {
return Futures.transform(async.deletePath(container + "/" + key), Functions.constant((Void) null),
userExecutor);
}
@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())
return transform(async.createDirectory(container, publicRead()), new Function<URI, Boolean>() {
public Boolean apply(URI from) {
return from != null;
}
}, userExecutor);
return createContainerInLocation(location, container);
}
}

View File

@ -23,7 +23,7 @@ import static org.jclouds.reflect.Reflection2.method;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.atmos.AtmosAsyncClient;
import org.jclouds.atmos.AtmosClient;
import org.jclouds.atmos.blobstore.functions.BlobToObject;
import org.jclouds.atmos.domain.AtmosObject;
import org.jclouds.atmos.options.PutOptions;
@ -54,9 +54,9 @@ public class AtmosBlobRequestSigner implements BlobRequestSigner {
this.processor = checkNotNull(processor, "processor");
this.blobToObject = checkNotNull(blobToObject, "blobToObject");
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
this.getMethod = method(AtmosAsyncClient.class, "readFile", String.class, GetOptions[].class);
this.deleteMethod = method(AtmosAsyncClient.class, "deletePath", String.class);
this.createMethod = method(AtmosAsyncClient.class, "createFile", String.class, AtmosObject.class, PutOptions[].class);
this.getMethod = method(AtmosClient.class, "readFile", String.class, GetOptions[].class);
this.deleteMethod = method(AtmosClient.class, "deletePath", String.class);
this.createMethod = method(AtmosClient.class, "createFile", String.class, AtmosObject.class, PutOptions[].class);
}
@Override

View File

@ -21,13 +21,13 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Singleton;
import org.jclouds.atmos.AtmosClient;
import org.jclouds.atmos.blobstore.AtmosAsyncBlobStore;
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;
@ -36,15 +36,12 @@ import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Scopes;
/**
* Configures the {@link AtmosBlobStoreContext}; requires {@link AtmosAsyncBlobStore} bound.
*/
public class AtmosBlobStoreContextModule extends AbstractModule {
@Override
protected void configure() {
bind(ConsistencyModel.class).toInstance(ConsistencyModel.EVENTUAL);
bind(AsyncBlobStore.class).to(AtmosAsyncBlobStore.class).in(Scopes.SINGLETON);
bind(AsyncBlobStore.class).to(SubmissionAsyncBlobStore.class).in(Scopes.SINGLETON);
bind(BlobStore.class).to(AtmosBlobStore.class).in(Scopes.SINGLETON);
bind(BlobRequestSigner.class).to(AtmosBlobRequestSigner.class);
}

View File

@ -22,7 +22,6 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.atmos.AtmosAsyncClient;
import org.jclouds.atmos.AtmosClient;
import org.jclouds.atmos.handlers.AtmosClientErrorRetryHandler;
import org.jclouds.atmos.handlers.AtmosServerErrorRetryHandler;
@ -34,8 +33,8 @@ import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.config.HttpApiModule;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
@ -45,8 +44,8 @@ import com.google.inject.Provides;
* Configures the EMC Atmos Online Storage authentication service connection, including logging and
* http transport.
*/
@ConfiguresRestClient
public class AtmosRestClientModule extends RestClientModule<AtmosClient, AtmosAsyncClient> {
@ConfiguresHttpApi
public class AtmosHttpApiModule extends HttpApiModule<AtmosClient> {
@Override
protected void configure() {

View File

@ -63,7 +63,7 @@ public class AtmosClientLiveTest extends BaseBlobStoreIntegrationTest {
}
public AtmosClient getApi() {
return view.unwrap(AtmosApiMetadata.CONTEXT_TOKEN).getApi();
return view.unwrapApi(AtmosClient.class);
}
private static final class HeadMatches implements Runnable {

View File

@ -25,7 +25,7 @@ import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.atmos.blobstore.functions.BlobToObject;
import org.jclouds.atmos.config.AtmosRestClientModule;
import org.jclouds.atmos.config.AtmosHttpApiModule;
import org.jclouds.atmos.domain.AtmosObject;
import org.jclouds.atmos.fallbacks.TrueOn404FalseOnPathNotEmpty;
import org.jclouds.atmos.filters.SignRequest;
@ -46,7 +46,7 @@ import org.jclouds.http.functions.ParseURIFromListOrLocationHeaderIf20x;
import org.jclouds.http.functions.ReleasePayloadAndReturn;
import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.options.GetOptions;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.internal.BaseAsyncClientTest;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.BeforeClass;
@ -57,17 +57,14 @@ import com.google.common.collect.ImmutableList;
import com.google.common.net.HttpHeaders;
import com.google.common.reflect.Invokable;
import com.google.inject.Module;
/**
* Tests behavior of {@code AtmosAsyncClient}
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "AtmosAsyncClientTest")
public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient> {
@Test(groups = "unit", testName = "AtmosClientTest")
public class AtmosClientTest extends BaseAsyncClientTest<AtmosClient> {
private BlobToObject blobToObject;
public void testListDirectories() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AtmosAsyncClient.class, "listDirectories", ListOptions[].class);
Invokable<?, ?> method = method(AtmosClient.class, "listDirectories", ListOptions[].class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.of());
assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/ HTTP/1.1");
@ -82,7 +79,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
}
public void testListDirectory() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AtmosAsyncClient.class, "listDirectory", String.class, ListOptions[].class);
Invokable<?, ?> method = method(AtmosClient.class, "listDirectory", String.class, ListOptions[].class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("directory"));
assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/directory/ HTTP/1.1");
@ -97,7 +94,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
}
public void testListDirectoriesOptions() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AtmosAsyncClient.class, "listDirectories", ListOptions[].class);
Invokable<?, ?> method = method(AtmosClient.class, "listDirectories", ListOptions[].class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of(new ListOptions().limit(1).token("asda")));
assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/ HTTP/1.1");
@ -112,7 +109,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
}
public void testListDirectoryOptions() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AtmosAsyncClient.class, "listDirectory", String.class, ListOptions[].class);
Invokable<?, ?> method = method(AtmosClient.class, "listDirectory", String.class, ListOptions[].class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("directory", new ListOptions().limit(1).token("asda")));
assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/directory/ HTTP/1.1");
@ -127,7 +124,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
}
public void testCreateDirectory() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AtmosAsyncClient.class, "createDirectory", String.class, PutOptions[].class);
Invokable<?, ?> method = method(AtmosClient.class, "createDirectory", String.class, PutOptions[].class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir"));
assertRequestLineEquals(request, "POST https://accesspoint.atmosonline.com/rest/namespace/dir/ HTTP/1.1");
@ -142,7 +139,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
}
public void testCreateDirectoryOptions() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AtmosAsyncClient.class, "createDirectory", String.class, PutOptions[].class);
Invokable<?, ?> method = method(AtmosClient.class, "createDirectory", String.class, PutOptions[].class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir", PutOptions.Builder.publicRead()));
assertRequestLineEquals(request, "POST https://accesspoint.atmosonline.com/rest/namespace/dir/ HTTP/1.1");
@ -158,7 +155,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
}
public void testCreateFile() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AtmosAsyncClient.class, "createFile", String.class, AtmosObject.class,
Invokable<?, ?> method = method(AtmosClient.class, "createFile", String.class, AtmosObject.class,
PutOptions[].class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir", blobToObject
.apply(BindBlobToMultipartFormTest.TEST_BLOB)));
@ -175,7 +172,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
}
public void testCreateFileOptions() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AtmosAsyncClient.class, "createFile", String.class, AtmosObject.class,
Invokable<?, ?> method = method(AtmosClient.class, "createFile", String.class, AtmosObject.class,
PutOptions[].class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir", blobToObject
.apply(BindBlobToMultipartFormTest.TEST_BLOB), PutOptions.Builder.publicRead()));
@ -193,7 +190,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
}
public void testUpdateFile() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AtmosAsyncClient.class, "updateFile", String.class, AtmosObject.class,
Invokable<?, ?> method = method(AtmosClient.class, "updateFile", String.class, AtmosObject.class,
PutOptions[].class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir", blobToObject
.apply(BindBlobToMultipartFormTest.TEST_BLOB)));
@ -210,7 +207,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
}
public void testUpdateFileOptions() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AtmosAsyncClient.class, "updateFile", String.class, AtmosObject.class,
Invokable<?, ?> method = method(AtmosClient.class, "updateFile", String.class, AtmosObject.class,
PutOptions[].class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir", blobToObject
.apply(BindBlobToMultipartFormTest.TEST_BLOB), PutOptions.Builder.publicRead()));
@ -228,7 +225,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
}
public void testReadFile() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AtmosAsyncClient.class, "readFile", String.class, GetOptions[].class);
Invokable<?, ?> method = method(AtmosClient.class, "readFile", String.class, GetOptions[].class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir/file"));
assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/dir/file HTTP/1.1");
@ -243,7 +240,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
}
public void testGetSystemMetadata() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AtmosAsyncClient.class, "getSystemMetadata", String.class);
Invokable<?, ?> method = method(AtmosClient.class, "getSystemMetadata", String.class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir/file"));
assertRequestLineEquals(request, "HEAD https://accesspoint.atmosonline.com/rest/namespace/dir/file HTTP/1.1");
@ -258,7 +255,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
}
public void testDeletePath() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AtmosAsyncClient.class, "deletePath", String.class);
Invokable<?, ?> method = method(AtmosClient.class, "deletePath", String.class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir/file"));
assertRequestLineEquals(request, "DELETE https://accesspoint.atmosonline.com/rest/namespace/dir/file HTTP/1.1");
@ -273,7 +270,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
}
public void testIsPublic() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AtmosAsyncClient.class, "isPublic", String.class);
Invokable<?, ?> method = method(AtmosClient.class, "isPublic", String.class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir/file"));
assertRequestLineEquals(request, "HEAD https://accesspoint.atmosonline.com/rest/namespace/dir/file HTTP/1.1");
@ -288,7 +285,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
}
public void testNewObject() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AtmosAsyncClient.class, "newObject");
Invokable<?, ?> method = method(AtmosClient.class, "newObject");
assertEquals(method.getReturnType().getRawType(), AtmosObject.class);
}
@ -307,11 +304,11 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
@Override
protected Module createModule() {
return new TestAtmosRestClientModule();
return new TestAtmosHttpApiModule();
}
@ConfiguresRestClient
private static final class TestAtmosRestClientModule extends AtmosRestClientModule {
@ConfiguresHttpApi
private static final class TestAtmosHttpApiModule extends AtmosHttpApiModule {
@Override
protected void configure() {
super.configure();

View File

@ -23,15 +23,15 @@ import java.util.Date;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.atmos.AtmosApiMetadata;
import org.jclouds.atmos.AtmosAsyncClient;
import org.jclouds.atmos.config.AtmosRestClientModule;
import org.jclouds.atmos.AtmosClient;
import org.jclouds.atmos.config.AtmosHttpApiModule;
import org.jclouds.atmos.filters.SignRequest;
import org.jclouds.blobstore.BlobRequestSigner;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.Blob.Factory;
import org.jclouds.date.TimeStamp;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.internal.BaseAsyncClientTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@ -45,7 +45,7 @@ import com.google.inject.Module;
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "AtmosBlobRequestSignerTest")
public class AtmosBlobRequestSignerTest extends BaseAsyncClientTest<AtmosAsyncClient> {
public class AtmosBlobRequestSignerTest extends BaseAsyncClientTest<AtmosClient> {
public AtmosBlobRequestSignerTest() {
// this is base64 decoded in the signer;
@ -126,11 +126,11 @@ public class AtmosBlobRequestSignerTest extends BaseAsyncClientTest<AtmosAsyncCl
@Override
protected Module createModule() {
return new TestAtmosRestClientModule();
return new TestAtmosHttpApiModule();
}
@ConfiguresRestClient
private static final class TestAtmosRestClientModule extends AtmosRestClientModule {
@ConfiguresHttpApi
private static final class TestAtmosHttpApiModule extends AtmosHttpApiModule {
@Override
protected void configure() {
super.configure();

View File

@ -25,12 +25,12 @@ import java.security.NoSuchAlgorithmException;
import javax.ws.rs.core.MediaType;
import org.jclouds.ContextBuilder;
import org.jclouds.atmos.config.AtmosRestClientModule;
import org.jclouds.atmos.config.AtmosHttpApiModule;
import org.jclouds.atmos.reference.AtmosHeaders;
import org.jclouds.date.TimeStamp;
import org.jclouds.http.HttpRequest;
import org.jclouds.logging.config.NullLoggingModule;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.internal.BaseRestApiTest.MockModule;
import org.jclouds.util.Strings2;
import org.testng.annotations.BeforeClass;
@ -93,15 +93,15 @@ public class SignRequestTest {
.newBuilder("atmos")
.credentials(UID, KEY)
.modules(
ImmutableSet.<Module> of(new MockModule(), new TestAtmosRestClientModule(), new NullLoggingModule()))
ImmutableSet.<Module> of(new MockModule(), new TestAtmosHttpApiModule(), new NullLoggingModule()))
.buildInjector();
filter = injector.getInstance(SignRequest.class);
}
@ConfiguresRestClient
private static final class TestAtmosRestClientModule extends AtmosRestClientModule {
@ConfiguresHttpApi
private static final class TestAtmosHttpApiModule extends AtmosHttpApiModule {
@Override
protected void configure() {

View File

@ -1,246 +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.atmos.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.ExecutionException;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.atmos.AtmosAsyncClient;
import org.jclouds.atmos.blobstore.functions.BlobMetadataToObject;
import org.jclouds.atmos.blobstore.functions.BlobToObject;
import org.jclouds.atmos.blobstore.functions.ListOptionsToBlobStoreListOptions;
import org.jclouds.atmos.blobstore.functions.ObjectToBlob;
import org.jclouds.atmos.blobstore.functions.ResourceMetadataListToDirectoryEntryList;
import org.jclouds.atmos.domain.AtmosObject;
import org.jclouds.atmos.domain.BoundedSet;
import org.jclouds.atmos.domain.DirectoryEntry;
import org.jclouds.atmos.domain.SystemMetadata;
import org.jclouds.atmos.domain.UserMetadata;
import org.jclouds.atmos.options.ListOptions;
import org.jclouds.atmos.options.PutOptions;
import org.jclouds.blobstore.LocalAsyncBlobStore;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions;
import org.jclouds.http.options.GetOptions;
import org.jclouds.lifecycle.Closer;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Throwables;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* Implementation of {@link AtmosAsyncClient} which keeps all data in a local Map object.
*/
public class StubAtmosAsyncClient implements AtmosAsyncClient {
private final HttpGetOptionsListToGetOptions httpGetOptionsConverter;
private final LocalAsyncBlobStore blobStore;
private final AtmosObject.Factory objectProvider;
private final ObjectToBlob object2Blob;
private final BlobToObject blob2Object;
private final BlobMetadataToObject blob2ObjectInfo;
private final ListOptionsToBlobStoreListOptions container2ContainerListOptions;
private final ResourceMetadataListToDirectoryEntryList resource2ObjectList;
private final ListeningExecutorService userExecutor;
private final Closer closer;
@Inject
private StubAtmosAsyncClient(LocalAsyncBlobStore blobStore, AtmosObject.Factory objectProvider,
HttpGetOptionsListToGetOptions httpGetOptionsConverter, ObjectToBlob object2Blob, BlobToObject blob2Object,
BlobMetadataToObject blob2ObjectInfo, ListOptionsToBlobStoreListOptions container2ContainerListOptions,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
ResourceMetadataListToDirectoryEntryList resource2ContainerList, Closer closer) {
this.blobStore = blobStore;
this.objectProvider = objectProvider;
this.httpGetOptionsConverter = httpGetOptionsConverter;
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
this.blob2ObjectInfo = checkNotNull(blob2ObjectInfo, "blob2ObjectInfo");
this.container2ContainerListOptions = checkNotNull(container2ContainerListOptions,
"container2ContainerListOptions");
this.resource2ObjectList = checkNotNull(resource2ContainerList, "resource2ContainerList");
this.userExecutor = userExecutor;
this.closer = checkNotNull(closer, "closer");
}
@Override
public ListenableFuture<URI> createDirectory(String directoryName, PutOptions... options) {
final String container;
final String path;
if (directoryName.indexOf('/') != -1) {
container = directoryName.substring(0, directoryName.indexOf('/'));
path = directoryName.substring(directoryName.indexOf('/') + 1);
} else {
container = directoryName;
path = null;
}
return Futures.transform(blobStore.createContainerInLocation(null, container), new Function<Boolean, URI>() {
public URI apply(Boolean from) {
if (path != null) {
Blob blob = blobStore.blobBuilder(path + "/").payload("").contentType("application/directory").build();
blobStore.putBlob(container, blob);
}
return URI.create("http://stub/containers/" + container);
}
}, userExecutor);
}
@Override
public ListenableFuture<URI> createFile(String parent, AtmosObject object, PutOptions... options) {
final String uri = "http://stub/containers/" + parent + "/" + object.getContentMetadata().getName();
String file = object.getContentMetadata().getName();
String container = parent;
if (parent.indexOf('/') != -1) {
container = parent.substring(0, parent.indexOf('/'));
String path = parent.substring(parent.indexOf('/') + 1);
if (!path.equals(""))
object.getContentMetadata().setName(path + "/" + file);
}
Blob blob = object2Blob.apply(object);
return Futures.transform(blobStore.putBlob(container, blob), new Function<String, URI>() {
public URI apply(String from) {
return URI.create(uri);
}
}, userExecutor);
}
@Override
public ListenableFuture<Boolean> deletePath(String path) {
if (path.indexOf('/') == path.length() - 1) {
// chop off the trailing slash
return blobStore.deleteContainerIfEmpty(path.substring(0, path.length() - 1));
} else {
String container = path.substring(0, path.indexOf('/'));
path = path.substring(path.indexOf('/') + 1);
return Futures.transform(blobStore.removeBlob(container, path), Functions.constant(Boolean.TRUE), userExecutor);
}
}
@Override
public ListenableFuture<SystemMetadata> getSystemMetadata(String path) {
throw new UnsupportedOperationException();
}
@Override
public ListenableFuture<UserMetadata> getUserMetadata(String path) {
if (path.indexOf('/') == -1)
throw new UnsupportedOperationException();
else {
String container = path.substring(0, path.indexOf('/'));
path = path.substring(path.indexOf('/') + 1);
return Futures.transform(blobStore.blobMetadata(container, path), new Function<BlobMetadata, UserMetadata>() {
public UserMetadata apply(BlobMetadata from) {
return blob2ObjectInfo.apply(from).getUserMetadata();
}
}, userExecutor);
}
}
@Override
public ListenableFuture<AtmosObject> headFile(String path) {
String container = path.substring(0, path.indexOf('/'));
path = path.substring(path.indexOf('/') + 1);
try {
return Futures.transform(blobStore.getBlob(container, path), blob2Object, userExecutor);
} catch (Exception e) {
return immediateFailedFuture(Throwables.getRootCause(e));
}
}
@Override
public ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectories(ListOptions... optionsList) {
// org.jclouds.blobstore.options.ListOptions options = container2ContainerListOptions
// .apply(optionsList);
return Futures.transform(blobStore.list(), resource2ObjectList, userExecutor);
}
@Override
public ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectory(String directoryName,
ListOptions... optionsList) {
org.jclouds.blobstore.options.ListContainerOptions options = container2ContainerListOptions.apply(optionsList);
String container = directoryName;
if (directoryName.indexOf('/') != -1) {
container = directoryName.substring(0, directoryName.indexOf('/'));
String path = directoryName.substring(directoryName.indexOf('/') + 1);
if (!path.equals(""))
options.inDirectory(path);
}
return Futures.transform(blobStore.list(container, options), resource2ObjectList, userExecutor);
}
@Override
public AtmosObject newObject() {
return this.objectProvider.create(null);
}
@Override
public ListenableFuture<Boolean> pathExists(final String path) {
if (path.indexOf('/') == path.length() - 1) {
// chop off the trailing slash
return blobStore.containerExists(path.substring(0, path.length() - 1));
} else {
String container = path.substring(0, path.indexOf('/'));
String blobName = path.substring(path.indexOf('/') + 1);
try {
return immediateFuture(blobStore.blobMetadata(container, blobName).get() != null);
} catch (InterruptedException e) {
return immediateFailedFuture(e);
} catch (ExecutionException e) {
return immediateFailedFuture(e);
}
}
}
@Override
public ListenableFuture<AtmosObject> readFile(String path, GetOptions... options) {
String container = path.substring(0, path.indexOf('/'));
String blobName = path.substring(path.indexOf('/') + 1);
org.jclouds.blobstore.options.GetOptions getOptions = httpGetOptionsConverter.apply(options);
return Futures.transform(blobStore.getBlob(container, blobName, getOptions), blob2Object, userExecutor);
}
@Override
public ListenableFuture<Void> updateFile(String parent, AtmosObject object, PutOptions... options) {
throw new UnsupportedOperationException();
}
@Override
public ListenableFuture<Boolean> isPublic(String path) {
throw new UnsupportedOperationException();
}
@Override
public void close() throws IOException {
closer.close();
}
}