mirror of https://github.com/apache/jclouds.git
JCLOUDS-40 unasync atmos.
This commit is contained in:
parent
9df0cd24c6
commit
9b71a9dcb8
|
@ -91,7 +91,6 @@
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<systemPropertyVariables>
|
<systemPropertyVariables>
|
||||||
<test.initializer>${test.initializer}</test.initializer>
|
|
||||||
<jclouds.blobstore.httpstream.url>${jclouds.blobstore.httpstream.url}</jclouds.blobstore.httpstream.url>
|
<jclouds.blobstore.httpstream.url>${jclouds.blobstore.httpstream.url}</jclouds.blobstore.httpstream.url>
|
||||||
<jclouds.blobstore.httpstream.md5>${jclouds.blobstore.httpstream.md5}</jclouds.blobstore.httpstream.md5>
|
<jclouds.blobstore.httpstream.md5>${jclouds.blobstore.httpstream.md5}</jclouds.blobstore.httpstream.md5>
|
||||||
<test.atmos.endpoint>${test.atmos.endpoint}</test.atmos.endpoint>
|
<test.atmos.endpoint>${test.atmos.endpoint}</test.atmos.endpoint>
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.atmos;
|
package org.jclouds.atmos;
|
||||||
|
|
||||||
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
|
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
|
||||||
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
|
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
|
||||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
import static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
@ -23,27 +24,15 @@ import java.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.atmos.blobstore.config.AtmosBlobStoreContextModule;
|
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.blobstore.BlobStoreContext;
|
||||||
|
import org.jclouds.rest.internal.BaseHttpApiMetadata;
|
||||||
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.reflect.TypeToken;
|
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
|
||||||
/**
|
public class AtmosApiMetadata extends BaseHttpApiMetadata {
|
||||||
* 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
private static Builder builder() {
|
private static Builder builder() {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
|
@ -69,10 +58,9 @@ public class AtmosApiMetadata extends BaseRestApiMetadata {
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends BaseRestApiMetadata.Builder<Builder> {
|
public static class Builder extends BaseHttpApiMetadata.Builder<AtmosClient, Builder> {
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
protected Builder() {
|
protected Builder() {
|
||||||
super(AtmosClient.class, AtmosAsyncClient.class);
|
super(AtmosClient.class);
|
||||||
id("atmos")
|
id("atmos")
|
||||||
.name("EMC's Atmos API")
|
.name("EMC's Atmos API")
|
||||||
.identityName("Subtenant ID (UID)")
|
.identityName("Subtenant ID (UID)")
|
||||||
|
@ -82,7 +70,7 @@ public class AtmosApiMetadata extends BaseRestApiMetadata {
|
||||||
.defaultEndpoint("https://accesspoint.atmosonline.com")
|
.defaultEndpoint("https://accesspoint.atmosonline.com")
|
||||||
.defaultProperties(AtmosApiMetadata.defaultProperties())
|
.defaultProperties(AtmosApiMetadata.defaultProperties())
|
||||||
.view(typeToken(BlobStoreContext.class))
|
.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
|
@Override
|
||||||
|
|
|
@ -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);
|
|
||||||
|
|
||||||
}
|
|
|
@ -16,57 +16,162 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.atmos;
|
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.io.Closeable;
|
||||||
import java.net.URI;
|
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.AtmosObject;
|
||||||
import org.jclouds.atmos.domain.BoundedSet;
|
import org.jclouds.atmos.domain.BoundedSet;
|
||||||
import org.jclouds.atmos.domain.DirectoryEntry;
|
import org.jclouds.atmos.domain.DirectoryEntry;
|
||||||
import org.jclouds.atmos.domain.SystemMetadata;
|
import org.jclouds.atmos.domain.SystemMetadata;
|
||||||
import org.jclouds.atmos.domain.UserMetadata;
|
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.ListOptions;
|
||||||
import org.jclouds.atmos.options.PutOptions;
|
import org.jclouds.atmos.options.PutOptions;
|
||||||
import org.jclouds.http.options.GetOptions;
|
import org.jclouds.http.options.GetOptions;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
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;
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
/**
|
/** Provides access to EMC Atmos Online Storage resources via their REST API. */
|
||||||
* Provides access to EMC Atmos Online Storage resources via their REST API.
|
@RequestFilters(SignRequest.class)
|
||||||
* <p/>
|
@Path("/rest/namespace")
|
||||||
*
|
|
||||||
* @see AtmosAsyncClient
|
|
||||||
* @see <a href="https://community.emc.com/community/labs/atmos_online" />
|
|
||||||
*/
|
|
||||||
public interface AtmosClient extends Closeable {
|
public interface AtmosClient extends Closeable {
|
||||||
/**
|
|
||||||
* Creates a default implementation of AtmosObject
|
|
||||||
*/
|
|
||||||
@Provides
|
@Provides
|
||||||
AtmosObject newObject();
|
AtmosObject newObject();
|
||||||
|
|
||||||
|
@Named("ListDirectory")
|
||||||
|
@GET
|
||||||
|
@Path("/")
|
||||||
|
@ResponseParser(ParseDirectoryListFromContentAndHeaders.class)
|
||||||
|
@Consumes(MediaType.TEXT_XML)
|
||||||
BoundedSet<? extends DirectoryEntry> listDirectories(ListOptions... options);
|
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
|
@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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -23,7 +23,7 @@ import static org.jclouds.reflect.Reflection2.method;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
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.blobstore.functions.BlobToObject;
|
||||||
import org.jclouds.atmos.domain.AtmosObject;
|
import org.jclouds.atmos.domain.AtmosObject;
|
||||||
import org.jclouds.atmos.options.PutOptions;
|
import org.jclouds.atmos.options.PutOptions;
|
||||||
|
@ -54,9 +54,9 @@ public class AtmosBlobRequestSigner implements BlobRequestSigner {
|
||||||
this.processor = checkNotNull(processor, "processor");
|
this.processor = checkNotNull(processor, "processor");
|
||||||
this.blobToObject = checkNotNull(blobToObject, "blobToObject");
|
this.blobToObject = checkNotNull(blobToObject, "blobToObject");
|
||||||
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
||||||
this.getMethod = method(AtmosAsyncClient.class, "readFile", String.class, GetOptions[].class);
|
this.getMethod = method(AtmosClient.class, "readFile", String.class, GetOptions[].class);
|
||||||
this.deleteMethod = method(AtmosAsyncClient.class, "deletePath", String.class);
|
this.deleteMethod = method(AtmosClient.class, "deletePath", String.class);
|
||||||
this.createMethod = method(AtmosAsyncClient.class, "createFile", String.class, AtmosObject.class, PutOptions[].class);
|
this.createMethod = method(AtmosClient.class, "createFile", String.class, AtmosObject.class, PutOptions[].class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,13 +21,13 @@ import java.util.concurrent.TimeUnit;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.atmos.AtmosClient;
|
import org.jclouds.atmos.AtmosClient;
|
||||||
import org.jclouds.atmos.blobstore.AtmosAsyncBlobStore;
|
|
||||||
import org.jclouds.atmos.blobstore.AtmosBlobRequestSigner;
|
import org.jclouds.atmos.blobstore.AtmosBlobRequestSigner;
|
||||||
import org.jclouds.atmos.blobstore.AtmosBlobStore;
|
import org.jclouds.atmos.blobstore.AtmosBlobStore;
|
||||||
import org.jclouds.blobstore.AsyncBlobStore;
|
import org.jclouds.blobstore.AsyncBlobStore;
|
||||||
import org.jclouds.blobstore.BlobRequestSigner;
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
import org.jclouds.blobstore.BlobStore;
|
import org.jclouds.blobstore.BlobStore;
|
||||||
import org.jclouds.blobstore.attr.ConsistencyModel;
|
import org.jclouds.blobstore.attr.ConsistencyModel;
|
||||||
|
import org.jclouds.blobstore.internal.SubmissionAsyncBlobStore;
|
||||||
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
|
@ -36,15 +36,12 @@ import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import com.google.inject.Scopes;
|
import com.google.inject.Scopes;
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the {@link AtmosBlobStoreContext}; requires {@link AtmosAsyncBlobStore} bound.
|
|
||||||
*/
|
|
||||||
public class AtmosBlobStoreContextModule extends AbstractModule {
|
public class AtmosBlobStoreContextModule extends AbstractModule {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(ConsistencyModel.class).toInstance(ConsistencyModel.EVENTUAL);
|
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(BlobStore.class).to(AtmosBlobStore.class).in(Scopes.SINGLETON);
|
||||||
bind(BlobRequestSigner.class).to(AtmosBlobRequestSigner.class);
|
bind(BlobRequestSigner.class).to(AtmosBlobRequestSigner.class);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import java.util.concurrent.TimeUnit;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.atmos.AtmosAsyncClient;
|
|
||||||
import org.jclouds.atmos.AtmosClient;
|
import org.jclouds.atmos.AtmosClient;
|
||||||
import org.jclouds.atmos.handlers.AtmosClientErrorRetryHandler;
|
import org.jclouds.atmos.handlers.AtmosClientErrorRetryHandler;
|
||||||
import org.jclouds.atmos.handlers.AtmosServerErrorRetryHandler;
|
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.ClientError;
|
||||||
import org.jclouds.http.annotation.Redirection;
|
import org.jclouds.http.annotation.Redirection;
|
||||||
import org.jclouds.http.annotation.ServerError;
|
import org.jclouds.http.annotation.ServerError;
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
import org.jclouds.rest.ConfiguresHttpApi;
|
||||||
import org.jclouds.rest.config.RestClientModule;
|
import org.jclouds.rest.config.HttpApiModule;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Suppliers;
|
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
|
* Configures the EMC Atmos Online Storage authentication service connection, including logging and
|
||||||
* http transport.
|
* http transport.
|
||||||
*/
|
*/
|
||||||
@ConfiguresRestClient
|
@ConfiguresHttpApi
|
||||||
public class AtmosRestClientModule extends RestClientModule<AtmosClient, AtmosAsyncClient> {
|
public class AtmosHttpApiModule extends HttpApiModule<AtmosClient> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
|
@ -63,7 +63,7 @@ public class AtmosClientLiveTest extends BaseBlobStoreIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public AtmosClient getApi() {
|
public AtmosClient getApi() {
|
||||||
return view.unwrap(AtmosApiMetadata.CONTEXT_TOKEN).getApi();
|
return view.unwrapApi(AtmosClient.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class HeadMatches implements Runnable {
|
private static final class HeadMatches implements Runnable {
|
||||||
|
|
|
@ -25,7 +25,7 @@ import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
|
||||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
import org.jclouds.apis.ApiMetadata;
|
import org.jclouds.apis.ApiMetadata;
|
||||||
import org.jclouds.atmos.blobstore.functions.BlobToObject;
|
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.domain.AtmosObject;
|
||||||
import org.jclouds.atmos.fallbacks.TrueOn404FalseOnPathNotEmpty;
|
import org.jclouds.atmos.fallbacks.TrueOn404FalseOnPathNotEmpty;
|
||||||
import org.jclouds.atmos.filters.SignRequest;
|
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.ReleasePayloadAndReturn;
|
||||||
import org.jclouds.http.functions.ReturnTrueIf2xx;
|
import org.jclouds.http.functions.ReturnTrueIf2xx;
|
||||||
import org.jclouds.http.options.GetOptions;
|
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.BaseAsyncClientTest;
|
||||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||||
import org.testng.annotations.BeforeClass;
|
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.net.HttpHeaders;
|
||||||
import com.google.common.reflect.Invokable;
|
import com.google.common.reflect.Invokable;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
/**
|
|
||||||
* Tests behavior of {@code AtmosAsyncClient}
|
@Test(groups = "unit", testName = "AtmosClientTest")
|
||||||
*/
|
public class AtmosClientTest extends BaseAsyncClientTest<AtmosClient> {
|
||||||
// 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> {
|
|
||||||
|
|
||||||
private BlobToObject blobToObject;
|
private BlobToObject blobToObject;
|
||||||
|
|
||||||
public void testListDirectories() throws SecurityException, NoSuchMethodException, IOException {
|
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());
|
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.of());
|
||||||
|
|
||||||
assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/ HTTP/1.1");
|
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 {
|
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"));
|
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("directory"));
|
||||||
|
|
||||||
assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/directory/ HTTP/1.1");
|
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 {
|
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")));
|
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");
|
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 {
|
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")));
|
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");
|
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 {
|
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"));
|
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir"));
|
||||||
|
|
||||||
assertRequestLineEquals(request, "POST https://accesspoint.atmosonline.com/rest/namespace/dir/ HTTP/1.1");
|
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 {
|
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()));
|
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");
|
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 {
|
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);
|
PutOptions[].class);
|
||||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir", blobToObject
|
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir", blobToObject
|
||||||
.apply(BindBlobToMultipartFormTest.TEST_BLOB)));
|
.apply(BindBlobToMultipartFormTest.TEST_BLOB)));
|
||||||
|
@ -175,7 +172,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreateFileOptions() throws SecurityException, NoSuchMethodException, IOException {
|
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);
|
PutOptions[].class);
|
||||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir", blobToObject
|
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir", blobToObject
|
||||||
.apply(BindBlobToMultipartFormTest.TEST_BLOB), PutOptions.Builder.publicRead()));
|
.apply(BindBlobToMultipartFormTest.TEST_BLOB), PutOptions.Builder.publicRead()));
|
||||||
|
@ -193,7 +190,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUpdateFile() throws SecurityException, NoSuchMethodException, IOException {
|
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);
|
PutOptions[].class);
|
||||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir", blobToObject
|
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir", blobToObject
|
||||||
.apply(BindBlobToMultipartFormTest.TEST_BLOB)));
|
.apply(BindBlobToMultipartFormTest.TEST_BLOB)));
|
||||||
|
@ -210,7 +207,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUpdateFileOptions() throws SecurityException, NoSuchMethodException, IOException {
|
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);
|
PutOptions[].class);
|
||||||
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir", blobToObject
|
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir", blobToObject
|
||||||
.apply(BindBlobToMultipartFormTest.TEST_BLOB), PutOptions.Builder.publicRead()));
|
.apply(BindBlobToMultipartFormTest.TEST_BLOB), PutOptions.Builder.publicRead()));
|
||||||
|
@ -228,7 +225,7 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testReadFile() throws SecurityException, NoSuchMethodException, IOException {
|
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"));
|
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir/file"));
|
||||||
|
|
||||||
assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/dir/file HTTP/1.1");
|
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 {
|
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"));
|
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir/file"));
|
||||||
|
|
||||||
assertRequestLineEquals(request, "HEAD https://accesspoint.atmosonline.com/rest/namespace/dir/file HTTP/1.1");
|
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 {
|
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"));
|
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir/file"));
|
||||||
|
|
||||||
assertRequestLineEquals(request, "DELETE https://accesspoint.atmosonline.com/rest/namespace/dir/file HTTP/1.1");
|
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 {
|
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"));
|
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("dir/file"));
|
||||||
|
|
||||||
assertRequestLineEquals(request, "HEAD https://accesspoint.atmosonline.com/rest/namespace/dir/file HTTP/1.1");
|
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 {
|
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);
|
assertEquals(method.getReturnType().getRawType(), AtmosObject.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,11 +304,11 @@ public class AtmosAsyncClientTest extends BaseAsyncClientTest<AtmosAsyncClient>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Module createModule() {
|
protected Module createModule() {
|
||||||
return new TestAtmosRestClientModule();
|
return new TestAtmosHttpApiModule();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConfiguresRestClient
|
@ConfiguresHttpApi
|
||||||
private static final class TestAtmosRestClientModule extends AtmosRestClientModule {
|
private static final class TestAtmosHttpApiModule extends AtmosHttpApiModule {
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
super.configure();
|
super.configure();
|
|
@ -23,15 +23,15 @@ import java.util.Date;
|
||||||
|
|
||||||
import org.jclouds.apis.ApiMetadata;
|
import org.jclouds.apis.ApiMetadata;
|
||||||
import org.jclouds.atmos.AtmosApiMetadata;
|
import org.jclouds.atmos.AtmosApiMetadata;
|
||||||
import org.jclouds.atmos.AtmosAsyncClient;
|
import org.jclouds.atmos.AtmosClient;
|
||||||
import org.jclouds.atmos.config.AtmosRestClientModule;
|
import org.jclouds.atmos.config.AtmosHttpApiModule;
|
||||||
import org.jclouds.atmos.filters.SignRequest;
|
import org.jclouds.atmos.filters.SignRequest;
|
||||||
import org.jclouds.blobstore.BlobRequestSigner;
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
import org.jclouds.blobstore.domain.Blob;
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
import org.jclouds.blobstore.domain.Blob.Factory;
|
import org.jclouds.blobstore.domain.Blob.Factory;
|
||||||
import org.jclouds.date.TimeStamp;
|
import org.jclouds.date.TimeStamp;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
import org.jclouds.rest.ConfiguresHttpApi;
|
||||||
import org.jclouds.rest.internal.BaseAsyncClientTest;
|
import org.jclouds.rest.internal.BaseAsyncClientTest;
|
||||||
import org.testng.annotations.BeforeClass;
|
import org.testng.annotations.BeforeClass;
|
||||||
import org.testng.annotations.Test;
|
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
|
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||||
@Test(groups = "unit", testName = "AtmosBlobRequestSignerTest")
|
@Test(groups = "unit", testName = "AtmosBlobRequestSignerTest")
|
||||||
public class AtmosBlobRequestSignerTest extends BaseAsyncClientTest<AtmosAsyncClient> {
|
public class AtmosBlobRequestSignerTest extends BaseAsyncClientTest<AtmosClient> {
|
||||||
|
|
||||||
public AtmosBlobRequestSignerTest() {
|
public AtmosBlobRequestSignerTest() {
|
||||||
// this is base64 decoded in the signer;
|
// this is base64 decoded in the signer;
|
||||||
|
@ -126,11 +126,11 @@ public class AtmosBlobRequestSignerTest extends BaseAsyncClientTest<AtmosAsyncCl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Module createModule() {
|
protected Module createModule() {
|
||||||
return new TestAtmosRestClientModule();
|
return new TestAtmosHttpApiModule();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConfiguresRestClient
|
@ConfiguresHttpApi
|
||||||
private static final class TestAtmosRestClientModule extends AtmosRestClientModule {
|
private static final class TestAtmosHttpApiModule extends AtmosHttpApiModule {
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
super.configure();
|
super.configure();
|
||||||
|
|
|
@ -25,12 +25,12 @@ import java.security.NoSuchAlgorithmException;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import org.jclouds.ContextBuilder;
|
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.atmos.reference.AtmosHeaders;
|
||||||
import org.jclouds.date.TimeStamp;
|
import org.jclouds.date.TimeStamp;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.logging.config.NullLoggingModule;
|
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.rest.internal.BaseRestApiTest.MockModule;
|
||||||
import org.jclouds.util.Strings2;
|
import org.jclouds.util.Strings2;
|
||||||
import org.testng.annotations.BeforeClass;
|
import org.testng.annotations.BeforeClass;
|
||||||
|
@ -93,15 +93,15 @@ public class SignRequestTest {
|
||||||
.newBuilder("atmos")
|
.newBuilder("atmos")
|
||||||
.credentials(UID, KEY)
|
.credentials(UID, KEY)
|
||||||
.modules(
|
.modules(
|
||||||
ImmutableSet.<Module> of(new MockModule(), new TestAtmosRestClientModule(), new NullLoggingModule()))
|
ImmutableSet.<Module> of(new MockModule(), new TestAtmosHttpApiModule(), new NullLoggingModule()))
|
||||||
.buildInjector();
|
.buildInjector();
|
||||||
|
|
||||||
filter = injector.getInstance(SignRequest.class);
|
filter = injector.getInstance(SignRequest.class);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConfiguresRestClient
|
@ConfiguresHttpApi
|
||||||
private static final class TestAtmosRestClientModule extends AtmosRestClientModule {
|
private static final class TestAtmosHttpApiModule extends AtmosHttpApiModule {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue