mirror of https://github.com/apache/jclouds.git
Issue 75: Added GET with options for object
git-svn-id: http://jclouds.googlecode.com/svn/trunk@1820 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
3c0547c7df
commit
427ccfa963
|
@ -66,7 +66,7 @@ public class GetOptions extends BaseHttpRequestOptions {
|
||||||
Multimap<String, String> headers = super.buildRequestHeaders();
|
Multimap<String, String> headers = super.buildRequestHeaders();
|
||||||
String range = getRange();
|
String range = getRange();
|
||||||
if (range != null)
|
if (range != null)
|
||||||
headers.put("Content-Range", this.getRange());
|
headers.put("Range", this.getRange());
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
|
|
||||||
import org.jclouds.http.functions.ParseETagHeader;
|
import org.jclouds.http.functions.ParseETagHeader;
|
||||||
|
import org.jclouds.http.options.GetOptions;
|
||||||
import org.jclouds.rackspace.cloudfiles.binders.CFObjectBinder;
|
import org.jclouds.rackspace.cloudfiles.binders.CFObjectBinder;
|
||||||
import org.jclouds.rackspace.cloudfiles.binders.UserMetadataBinder;
|
import org.jclouds.rackspace.cloudfiles.binders.UserMetadataBinder;
|
||||||
import org.jclouds.rackspace.cloudfiles.domain.AccountMetadata;
|
import org.jclouds.rackspace.cloudfiles.domain.AccountMetadata;
|
||||||
|
@ -86,13 +87,7 @@ public interface CloudFilesConnection {
|
||||||
@ResponseParser(ParseContainerListFromGsonResponse.class)
|
@ResponseParser(ParseContainerListFromGsonResponse.class)
|
||||||
@Query(key = "format", value = "json")
|
@Query(key = "format", value = "json")
|
||||||
@Path("/")
|
@Path("/")
|
||||||
List<ContainerMetadata> listOwnedContainers();
|
List<ContainerMetadata> listOwnedContainers(ListContainerOptions ... options);
|
||||||
|
|
||||||
@GET
|
|
||||||
@ResponseParser(ParseContainerListFromGsonResponse.class)
|
|
||||||
@Query(key = "format", value = "json")
|
|
||||||
@Path("/")
|
|
||||||
List<ContainerMetadata> listOwnedContainers(ListContainerOptions options);
|
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Path("{container}")
|
@Path("{container}")
|
||||||
|
@ -124,9 +119,7 @@ public interface CloudFilesConnection {
|
||||||
@ExceptionParser(ReturnS3ObjectNotFoundOn404.class)
|
@ExceptionParser(ReturnS3ObjectNotFoundOn404.class)
|
||||||
@Path("{container}/{key}")
|
@Path("{container}/{key}")
|
||||||
Future<CFObject> getObject(@PathParam("container") String container,
|
Future<CFObject> getObject(@PathParam("container") String container,
|
||||||
@PathParam("key") String key);
|
@PathParam("key") String key, GetOptions ... options);
|
||||||
|
|
||||||
// TODO: GET object with options
|
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@ResponseParser(ReturnTrueOn202FalseOtherwise.class)
|
@ResponseParser(ReturnTrueOn202FalseOtherwise.class)
|
||||||
|
|
|
@ -118,9 +118,10 @@ public class ParseObjectMetadataFromHeaders implements Function<HttpResponse, CF
|
||||||
private void addUserMetadataTo(HttpResponse from, Metadata metadata) {
|
private void addUserMetadataTo(HttpResponse from, Metadata metadata) {
|
||||||
for (Entry<String, String> header : from.getHeaders().entries()) {
|
for (Entry<String, String> header : from.getHeaders().entries()) {
|
||||||
if (header.getKey() != null
|
if (header.getKey() != null
|
||||||
&& header.getKey().startsWith(CloudFilesHeaders.USER_METADATA_PREFIX))
|
&& header.getKey().toLowerCase().startsWith(
|
||||||
|
CloudFilesHeaders.USER_METADATA_PREFIX.toLowerCase()))
|
||||||
{
|
{
|
||||||
metadata.getUserMetadata().put(header.getKey(), header.getValue());
|
metadata.getUserMetadata().put(header.getKey().toLowerCase(), header.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
import org.jclouds.http.HttpUtils;
|
import org.jclouds.http.HttpUtils;
|
||||||
|
import org.jclouds.http.options.GetOptions;
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
import org.jclouds.rackspace.cloudfiles.domain.AccountMetadata;
|
import org.jclouds.rackspace.cloudfiles.domain.AccountMetadata;
|
||||||
import org.jclouds.rackspace.cloudfiles.domain.CFObject;
|
import org.jclouds.rackspace.cloudfiles.domain.CFObject;
|
||||||
|
@ -78,13 +79,30 @@ public class CloudFilesConnectionLiveTest {
|
||||||
long initialContainerCount = response.size();
|
long initialContainerCount = response.size();
|
||||||
assertTrue(initialContainerCount >= 0);
|
assertTrue(initialContainerCount >= 0);
|
||||||
|
|
||||||
String[] containerNames = new String[] { bucketPrefix + ".testListOwnedContainers1",
|
// Create test containers
|
||||||
|
String[] containerNames = new String[] {
|
||||||
|
bucketPrefix + ".testListOwnedContainers1",
|
||||||
bucketPrefix + ".testListOwnedContainers2" };
|
bucketPrefix + ".testListOwnedContainers2" };
|
||||||
assertTrue(connection.putContainer(containerNames[0]));
|
assertTrue(connection.putContainer(containerNames[0]));
|
||||||
assertTrue(connection.putContainer(containerNames[1]));
|
assertTrue(connection.putContainer(containerNames[1]));
|
||||||
|
|
||||||
|
// Test default listing
|
||||||
response = connection.listOwnedContainers();
|
response = connection.listOwnedContainers();
|
||||||
assertEquals(response.size(), initialContainerCount + 2);
|
assertEquals(response.size(), initialContainerCount + 2);
|
||||||
|
|
||||||
|
// Test listing with options
|
||||||
|
response = connection.listOwnedContainers(ListContainerOptions.Builder
|
||||||
|
.afterMarker(containerNames[0].substring(0, containerNames[0].length() - 1))
|
||||||
|
.maxResults(1));
|
||||||
|
assertEquals(response.size(), 1);
|
||||||
|
assertEquals(response.get(0).getName(), containerNames[0]);
|
||||||
|
|
||||||
|
response = connection.listOwnedContainers(ListContainerOptions.Builder
|
||||||
|
.afterMarker(containerNames[0]).maxResults(1));
|
||||||
|
assertEquals(response.size(), 1);
|
||||||
|
assertEquals(response.get(0).getName(), containerNames[1]);
|
||||||
|
|
||||||
|
// Cleanup and test containers have been removed
|
||||||
assertTrue(connection.deleteContainerIfEmpty(containerNames[0]));
|
assertTrue(connection.deleteContainerIfEmpty(containerNames[0]));
|
||||||
assertTrue(connection.deleteContainerIfEmpty(containerNames[1]));
|
assertTrue(connection.deleteContainerIfEmpty(containerNames[1]));
|
||||||
response = connection.listOwnedContainers();
|
response = connection.listOwnedContainers();
|
||||||
|
@ -160,7 +178,7 @@ public class CloudFilesConnectionLiveTest {
|
||||||
object.generateETag();
|
object.generateETag();
|
||||||
object.getMetadata().setContentType("text/plain");
|
object.getMetadata().setContentType("text/plain");
|
||||||
object.getMetadata().getUserMetadata().put(
|
object.getMetadata().getUserMetadata().put(
|
||||||
CloudFilesHeaders.USER_METADATA_PREFIX + "metadata", "metadata-value");
|
CloudFilesHeaders.USER_METADATA_PREFIX + "Metadata", "metadata-value");
|
||||||
byte[] md5 = connection.putObject(containerName, object).get(10, TimeUnit.SECONDS);
|
byte[] md5 = connection.putObject(containerName, object).get(10, TimeUnit.SECONDS);
|
||||||
assertEquals(HttpUtils.toHexString(md5),
|
assertEquals(HttpUtils.toHexString(md5),
|
||||||
HttpUtils.toHexString(object.getMetadata().getETag()));
|
HttpUtils.toHexString(object.getMetadata().getETag()));
|
||||||
|
@ -178,13 +196,13 @@ public class CloudFilesConnectionLiveTest {
|
||||||
assertEquals(metadata.getUserMetadata().entries().size(), 1);
|
assertEquals(metadata.getUserMetadata().entries().size(), 1);
|
||||||
// Notice the quirk where CF changes the case of returned metadata names
|
// Notice the quirk where CF changes the case of returned metadata names
|
||||||
assertEquals(Iterables.getLast(metadata.getUserMetadata().get(
|
assertEquals(Iterables.getLast(metadata.getUserMetadata().get(
|
||||||
CloudFilesHeaders.USER_METADATA_PREFIX + "Metadata")),
|
(CloudFilesHeaders.USER_METADATA_PREFIX + "Metadata").toLowerCase())),
|
||||||
"metadata-value");
|
"metadata-value");
|
||||||
|
|
||||||
// Test POST to update object's metadata
|
// Test POST to update object's metadata
|
||||||
Multimap<String, String> userMetadata = HashMultimap.create();
|
Multimap<String, String> userMetadata = HashMultimap.create();
|
||||||
userMetadata.put(CloudFilesHeaders.USER_METADATA_PREFIX + "new-metadata-1", "value-1");
|
userMetadata.put(CloudFilesHeaders.USER_METADATA_PREFIX + "New-Metadata-1", "value-1");
|
||||||
userMetadata.put(CloudFilesHeaders.USER_METADATA_PREFIX + "new-metadata-2", "value-2");
|
userMetadata.put(CloudFilesHeaders.USER_METADATA_PREFIX + "New-Metadata-2", "value-2");
|
||||||
assertTrue(connection.setObjectMetadata(containerName, object.getKey(), userMetadata));
|
assertTrue(connection.setObjectMetadata(containerName, object.getKey(), userMetadata));
|
||||||
|
|
||||||
// Test GET of missing object
|
// Test GET of missing object
|
||||||
|
@ -193,18 +211,18 @@ public class CloudFilesConnectionLiveTest {
|
||||||
assertEquals(getObject, CFObject.NOT_FOUND);
|
assertEquals(getObject, CFObject.NOT_FOUND);
|
||||||
|
|
||||||
// Test GET of object (including updated metadata)
|
// Test GET of object (including updated metadata)
|
||||||
getObject = connection.getObject(containerName, object.getKey()).get(10, TimeUnit.SECONDS);
|
getObject = connection.getObject(containerName, object.getKey()).get(120, TimeUnit.SECONDS);
|
||||||
assertEquals(IOUtils.toString((InputStream)getObject.getData()), data);
|
assertEquals(IOUtils.toString((InputStream)getObject.getData()), data);
|
||||||
assertEquals(getObject.getKey(), object.getKey());
|
assertEquals(getObject.getKey(), object.getKey());
|
||||||
assertEquals(getObject.getContentLength(), data.length());
|
assertEquals(getObject.getContentLength(), data.length());
|
||||||
assertEquals(getObject.getMetadata().getContentType(), "text/plain");
|
assertEquals(getObject.getMetadata().getContentType(), "text/plain");
|
||||||
assertEquals(getObject.getMetadata().getETag(), object.getMetadata().getETag());
|
assertEquals(getObject.getMetadata().getETag(), object.getMetadata().getETag());
|
||||||
assertEquals(getObject.getMetadata().getUserMetadata().entries().size(), 2);
|
assertEquals(getObject.getMetadata().getUserMetadata().entries().size(), 2);
|
||||||
// Notice the quirk where CF changes the case of sreturned metadata names
|
// Notice the quirk where CF changes the case of returned metadata names
|
||||||
assertEquals(Iterables.getLast(getObject.getMetadata().getUserMetadata().get(
|
assertEquals(Iterables.getLast(getObject.getMetadata().getUserMetadata().get(
|
||||||
CloudFilesHeaders.USER_METADATA_PREFIX + "New-Metadata-1")), "value-1");
|
(CloudFilesHeaders.USER_METADATA_PREFIX + "New-Metadata-1").toLowerCase())), "value-1");
|
||||||
assertEquals(Iterables.getLast(getObject.getMetadata().getUserMetadata().get(
|
assertEquals(Iterables.getLast(getObject.getMetadata().getUserMetadata().get(
|
||||||
CloudFilesHeaders.USER_METADATA_PREFIX + "New-Metadata-2")), "value-2");
|
(CloudFilesHeaders.USER_METADATA_PREFIX + "New-Metadata-2").toLowerCase())), "value-2");
|
||||||
|
|
||||||
// Test PUT with invalid ETag (as if object's data was corrupted in transit)
|
// Test PUT with invalid ETag (as if object's data was corrupted in transit)
|
||||||
String correctEtag = HttpUtils.toHexString(object.getMetadata().getETag());
|
String correctEtag = HttpUtils.toHexString(object.getMetadata().getETag());
|
||||||
|
@ -222,7 +240,24 @@ public class CloudFilesConnectionLiveTest {
|
||||||
object = new CFObject("chunked-object", bais);
|
object = new CFObject("chunked-object", bais);
|
||||||
md5 = connection.putObject(containerName, object).get(10, TimeUnit.SECONDS);
|
md5 = connection.putObject(containerName, object).get(10, TimeUnit.SECONDS);
|
||||||
assertEquals(HttpUtils.toHexString(md5), correctEtag);
|
assertEquals(HttpUtils.toHexString(md5), correctEtag);
|
||||||
// TODO: Get and confirm data
|
|
||||||
|
// Test GET with options
|
||||||
|
// Non-matching ETag
|
||||||
|
try {
|
||||||
|
connection.getObject(containerName, object.getKey(),
|
||||||
|
GetOptions.Builder.ifETagDoesntMatch(md5)).get(120, TimeUnit.SECONDS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertEquals(e.getCause().getClass(), HttpResponseException.class);
|
||||||
|
assertEquals(((HttpResponseException) e.getCause()).getResponse().getStatusCode(), 304);
|
||||||
|
}
|
||||||
|
// Matching ETag
|
||||||
|
getObject = connection.getObject(containerName, object.getKey(),
|
||||||
|
GetOptions.Builder.ifETagMatches(md5)).get(120, TimeUnit.SECONDS);
|
||||||
|
assertEquals(getObject.getMetadata().getETag(), md5);
|
||||||
|
// Range
|
||||||
|
getObject = connection.getObject(containerName, object.getKey(),
|
||||||
|
GetOptions.Builder.startAt(8)).get(120, TimeUnit.SECONDS);
|
||||||
|
assertEquals(IOUtils.toString((InputStream)getObject.getData()), data.substring(8));
|
||||||
|
|
||||||
assertTrue(connection.deleteObject(containerName, "object"));
|
assertTrue(connection.deleteObject(containerName, "object"));
|
||||||
assertTrue(connection.deleteObject(containerName, "chunked-object"));
|
assertTrue(connection.deleteObject(containerName, "chunked-object"));
|
||||||
|
|
Loading…
Reference in New Issue