Issue 73: normalizing names of objects; break metadata into interfaces so that they can be implemented differently

git-svn-id: http://jclouds.googlecode.com/svn/trunk@1986 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-10-19 01:14:25 +00:00
parent ff9abb6884
commit ee6ffff298
75 changed files with 860 additions and 509 deletions

View File

@ -49,7 +49,7 @@ import org.jclouds.aws.s3.xml.ListAllMyBucketsHandler;
import org.jclouds.aws.s3.xml.ListBucketHandler; import org.jclouds.aws.s3.xml.ListBucketHandler;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.functions.BlobKey; import org.jclouds.blobstore.functions.BlobName;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseETagHeader; import org.jclouds.http.functions.ParseETagHeader;
@ -181,7 +181,7 @@ public interface S3BlobStore extends BlobStore<BucketMetadata, ObjectMetadata, S
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
Future<String> putBlob( Future<String> putBlob(
@HostPrefixParam String bucketName, @HostPrefixParam String bucketName,
@PathParam("key") @ParamParser(BlobKey.class) @BinderParam(BindS3ObjectToEntity.class) S3Object object); @PathParam("key") @ParamParser(BlobName.class) @BinderParam(BindS3ObjectToEntity.class) S3Object object);
@PUT @PUT
@Path("/") @Path("/")

View File

@ -55,7 +55,7 @@ import org.jclouds.aws.s3.xml.CopyObjectHandler;
import org.jclouds.aws.s3.xml.ListAllMyBucketsHandler; import org.jclouds.aws.s3.xml.ListAllMyBucketsHandler;
import org.jclouds.aws.s3.xml.ListBucketHandler; import org.jclouds.aws.s3.xml.ListBucketHandler;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.functions.BlobKey; import org.jclouds.blobstore.functions.BlobName;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404; import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
@ -206,7 +206,7 @@ public interface S3Connection {
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
Future<String> putObject( Future<String> putObject(
@HostPrefixParam String bucketName, @HostPrefixParam String bucketName,
@PathParam("key") @ParamParser(BlobKey.class) @BinderParam(BindS3ObjectToEntity.class) S3Object object, @PathParam("key") @ParamParser(BlobName.class) @BinderParam(BindS3ObjectToEntity.class) S3Object object,
PutObjectOptions... options); PutObjectOptions... options);
/** /**

View File

@ -31,11 +31,11 @@ import javax.inject.Named;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.binders.BindBlobToEntity; import org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
public class BindS3ObjectToEntity extends BindBlobToEntity { public class BindS3ObjectToEntity extends BindBlobToEntityAndUserMetadataToHeadersWithPrefix {
@Inject @Inject
public BindS3ObjectToEntity(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) { public BindS3ObjectToEntity(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
super(metadataPrefix); super(metadataPrefix);

View File

@ -23,7 +23,7 @@
*/ */
package org.jclouds.aws.s3.domain; package org.jclouds.aws.s3.domain;
import org.jclouds.blobstore.domain.ContainerMetadata; import org.jclouds.blobstore.internal.ContainerMetadataImpl;
import org.joda.time.DateTime; import org.joda.time.DateTime;
/** /**
@ -31,7 +31,7 @@ import org.joda.time.DateTime;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class BucketMetadata extends ContainerMetadata { public class BucketMetadata extends ContainerMetadataImpl {
protected DateTime creationDate; protected DateTime creationDate;
public DateTime getCreationDate() { public DateTime getCreationDate() {

View File

@ -25,7 +25,7 @@ package org.jclouds.aws.s3.domain;
import java.io.Serializable; import java.io.Serializable;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.internal.BlobMetadataImpl;
/** /**
* /** Amazon S3 is designed to store objects. Objects are stored in {@link S3BucketListing buckets} * /** Amazon S3 is designed to store objects. Objects are stored in {@link S3BucketListing buckets}
@ -38,7 +38,7 @@ import org.jclouds.blobstore.domain.BlobMetadata;
* *
* @see <a href= "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingMetadata.html" /> * @see <a href= "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingMetadata.html" />
*/ */
public class ObjectMetadata extends BlobMetadata implements Serializable { public class ObjectMetadata extends BlobMetadataImpl implements Serializable {
/** The serialVersionUID */ /** The serialVersionUID */
private static final long serialVersionUID = -4415449798024051115L; private static final long serialVersionUID = -4415449798024051115L;
@ -51,7 +51,7 @@ public class ObjectMetadata extends BlobMetadata implements Serializable {
dataDisposition).append(", owner=").append(owner).append(", storageClass=").append( dataDisposition).append(", owner=").append(owner).append(", storageClass=").append(
storageClass).append(", allHeaders=").append(allHeaders).append(", dataEncoding=") storageClass).append(", allHeaders=").append(allHeaders).append(", dataEncoding=")
.append(dataEncoding).append(", dataType=").append(dataType).append(", eTag=") .append(dataEncoding).append(", dataType=").append(dataType).append(", eTag=")
.append(eTag).append(", key=").append(key).append(", lastModified=").append( .append(eTag).append(", key=").append(name).append(", lastModified=").append(
lastModified).append(", size=").append(size).append(", userMetadata=") lastModified).append(", size=").append(size).append(", userMetadata=")
.append(userMetadata).append("]"); .append(userMetadata).append("]");
return builder.toString(); return builder.toString();
@ -186,7 +186,7 @@ public class ObjectMetadata extends BlobMetadata implements Serializable {
} }
public int compareTo(ObjectMetadata o) { public int compareTo(ObjectMetadata o) {
return (this == o) ? 0 : getKey().compareTo(o.getKey()); return (this == o) ? 0 : getName().compareTo(o.getName());
} }
public void setContentEncoding(String dataEncoding) { public void setContentEncoding(String dataEncoding) {

View File

@ -25,7 +25,7 @@ package org.jclouds.aws.s3.domain;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.internal.BlobImpl;
/** /**
* Amazon S3 is designed to store objects. Objects are stored in {@link S3Bucket buckets} and * Amazon S3 is designed to store objects. Objects are stored in {@link S3Bucket buckets} and
@ -37,7 +37,7 @@ import org.jclouds.blobstore.domain.Blob;
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html" * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html"
* /> * />
*/ */
public class S3Object extends Blob<ObjectMetadata> { public class S3Object extends BlobImpl<ObjectMetadata> {
public S3Object(ObjectMetadata metadata, Object data) { public S3Object(ObjectMetadata metadata, Object data) {
super(metadata, data); super(metadata, data);

View File

@ -121,7 +121,7 @@ public class StubS3Connection extends StubBlobStore<BucketMetadata, ObjectMetada
ObjectMetadata lastMarkerMetadata = Iterables.find(contents, ObjectMetadata lastMarkerMetadata = Iterables.find(contents,
new Predicate<ObjectMetadata>() { new Predicate<ObjectMetadata>() {
public boolean apply(ObjectMetadata metadata) { public boolean apply(ObjectMetadata metadata) {
return metadata.getKey().equals(finalMarker); return metadata.getName().equals(finalMarker);
} }
}); });
contents = contents.tailSet(lastMarkerMetadata); contents = contents.tailSet(lastMarkerMetadata);
@ -133,7 +133,7 @@ public class StubS3Connection extends StubBlobStore<BucketMetadata, ObjectMetada
contents = Sets.newTreeSet(Iterables.filter(contents, contents = Sets.newTreeSet(Iterables.filter(contents,
new Predicate<ObjectMetadata>() { new Predicate<ObjectMetadata>() {
public boolean apply(ObjectMetadata o) { public boolean apply(ObjectMetadata o) {
return (o != null && o.getKey().startsWith(prefix)); return (o != null && o.getName().startsWith(prefix));
} }
})); }));
} }
@ -161,7 +161,7 @@ public class StubS3Connection extends StubBlobStore<BucketMetadata, ObjectMetada
if (!contentsSlice.contains(contents.last())) { if (!contentsSlice.contains(contents.last())) {
// Partial listing // Partial listing
truncated = true; truncated = true;
marker = contentsSlice.last().getKey(); marker = contentsSlice.last().getName();
} else { } else {
marker = null; marker = null;
} }
@ -229,7 +229,7 @@ public class StubS3Connection extends StubBlobStore<BucketMetadata, ObjectMetada
final PutObjectOptions options = (nullableOptions == null) ? new PutObjectOptions() final PutObjectOptions options = (nullableOptions == null) ? new PutObjectOptions()
: nullableOptions; : nullableOptions;
if (options.getAcl() != null) if (options.getAcl() != null)
keyToAcl.put(bucketName + "/" + object.getKey(), options.getAcl()); keyToAcl.put(bucketName + "/" + object.getName(), options.getAcl());
return super.putBlob(bucketName, object); return super.putBlob(bucketName, object);
} }

View File

@ -132,7 +132,7 @@ public class S3ParserTest extends PerformanceTest {
assert container.getBucketName().equals("adrianjbosstest"); assert container.getBucketName().equals("adrianjbosstest");
assert container.size() == 1; assert container.size() == 1;
ObjectMetadata object = container.iterator().next(); ObjectMetadata object = container.iterator().next();
assert object.getKey().equals("3366"); assert object.getName().equals("3366");
DateTime expected = new DateTime("2009-03-12T02:00:13.000Z"); DateTime expected = new DateTime("2009-03-12T02:00:13.000Z");
assert object.getLastModified().equals(expected) : String.format( assert object.getLastModified().equals(expected) : String.format(
"expected %1$s, but got %1$s", expected, object.getLastModified()); "expected %1$s, but got %1$s", expected, object.getLastModified());

View File

@ -96,7 +96,7 @@ public class Util {
} }
public static S3Object convertObjectHead(org.jclouds.aws.s3.domain.ObjectMetadata jcObjectMD) { public static S3Object convertObjectHead(org.jclouds.aws.s3.domain.ObjectMetadata jcObjectMD) {
S3Object jsObject = new S3Object(jcObjectMD.getKey()); S3Object jsObject = new S3Object(jcObjectMD.getName());
if (jcObjectMD.getOwner() != null) { if (jcObjectMD.getOwner() != null) {
jsObject.setOwner(new S3Owner(jcObjectMD.getOwner().getId(), jcObjectMD.getOwner() jsObject.setOwner(new S3Owner(jcObjectMD.getOwner().getId(), jcObjectMD.getOwner()
.getDisplayName())); .getDisplayName()));

View File

@ -51,9 +51,9 @@ import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.filters.SharedKeyAuthentication; import org.jclouds.azure.storage.filters.SharedKeyAuthentication;
import org.jclouds.azure.storage.options.ListOptions; import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.reference.AzureStorageHeaders; import org.jclouds.azure.storage.reference.AzureStorageHeaders;
import org.jclouds.blobstore.binders.BindBlobToEntity; import org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix;
import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix; import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix;
import org.jclouds.blobstore.functions.BlobKey; import org.jclouds.blobstore.functions.BlobName;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseETagHeader; import org.jclouds.http.functions.ParseETagHeader;
@ -271,7 +271,7 @@ public interface AzureBlobConnection {
@Path("{container}/{key}") @Path("{container}/{key}")
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
Future<String> putBlob(@PathParam("container") String container, Future<String> putBlob(@PathParam("container") String container,
@PathParam("key") @ParamParser(BlobKey.class) @BinderParam(BindBlobToEntity.class) Blob object); @PathParam("key") @ParamParser(BlobName.class) @BinderParam(BindBlobToEntityAndUserMetadataToHeadersWithPrefix.class) Blob object);
/** /**
* The Get Blob operation reads or downloads a blob from the system, including its metadata and * The Get Blob operation reads or downloads a blob from the system, including its metadata and

View File

@ -50,7 +50,7 @@ import org.jclouds.azure.storage.filters.SharedKeyAuthentication;
import org.jclouds.azure.storage.options.ListOptions; import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.reference.AzureStorageHeaders; import org.jclouds.azure.storage.reference.AzureStorageHeaders;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.functions.BlobKey; import org.jclouds.blobstore.functions.BlobName;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseETagHeader; import org.jclouds.http.functions.ParseETagHeader;
@ -149,7 +149,7 @@ public interface AzureBlobStore extends BlobStore<ContainerMetadata, BlobMetadat
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
Future<String> putBlob( Future<String> putBlob(
@PathParam("container") String container, @PathParam("container") String container,
@PathParam("key") @ParamParser(BlobKey.class) @BinderParam(GenerateMD5AndBindBlobToEntity.class) Blob object); @PathParam("key") @ParamParser(BlobName.class) @BinderParam(GenerateMD5AndBindBlobToEntity.class) Blob object);
@GET @GET
@ResponseParser(ParseBlobFromHeadersAndHttpContent.class) @ResponseParser(ParseBlobFromHeadersAndHttpContent.class)

View File

@ -34,7 +34,7 @@ import org.jclouds.azure.storage.blob.domain.BlobMetadata;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
public class BindBlobToEntity extends org.jclouds.blobstore.binders.BindBlobToEntity { public class BindBlobToEntity extends org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix {
@Inject @Inject
public BindBlobToEntity(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) { public BindBlobToEntity(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
super(metadataPrefix); super(metadataPrefix);

View File

@ -47,7 +47,7 @@ public class GenerateMD5AndBindBlobToEntity extends BindBlobToEntity {
try { try {
object.generateMD5(); object.generateMD5();
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException("Could not generate MD5 for " + object.getKey(), e); throw new RuntimeException("Could not generate MD5 for " + object.getName(), e);
} }
} }
super.bindToRequest(request, entity); super.bindToRequest(request, entity);

View File

@ -23,10 +23,12 @@
*/ */
package org.jclouds.azure.storage.blob.domain; package org.jclouds.azure.storage.blob.domain;
import org.jclouds.blobstore.internal.BlobImpl;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
public class Blob extends org.jclouds.blobstore.domain.Blob<BlobMetadata> { public class Blob extends BlobImpl<BlobMetadata> {
public Blob(BlobMetadata metadata, BlobMetadata data) { public Blob(BlobMetadata metadata, BlobMetadata data) {
super(metadata, data); super(metadata, data);

View File

@ -27,6 +27,7 @@ import java.net.URI;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.blobstore.internal.BlobMetadataImpl;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import com.google.inject.internal.Nullable; import com.google.inject.internal.Nullable;
@ -36,7 +37,7 @@ import com.google.inject.internal.Nullable;
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class BlobMetadata extends org.jclouds.blobstore.domain.BlobMetadata { public class BlobMetadata extends BlobMetadataImpl {
/** The serialVersionUID */ /** The serialVersionUID */
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private URI url; private URI url;

View File

@ -36,7 +36,7 @@ import com.google.common.collect.Multimap;
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class ContainerMetadata extends org.jclouds.blobstore.domain.ContainerMetadata { public class ContainerMetadata extends org.jclouds.blobstore.internal.ContainerMetadataImpl {
private URI url; private URI url;
private DateTime lastModified; private DateTime lastModified;
private byte[] eTag; private byte[] eTag;

View File

@ -53,8 +53,8 @@ public class AddMD5ToListBlobsResponse extends ContainerNameEnumerationResultsHa
ListBlobsResponse response = super.getResult(); ListBlobsResponse response = super.getResult();
checkNotNull(response.getContainerUrl(), "containerUrl"); checkNotNull(response.getContainerUrl(), "containerUrl");
for (BlobMetadata md : response) { for (BlobMetadata md : response) {
checkNotNull(md.getKey(), "key"); checkNotNull(md.getName(), "key");
md.setContentMD5(util.getMD5(response.getContainerUrl(), md.getKey())); md.setContentMD5(util.getMD5(response.getContainerUrl(), md.getName()));
} }
return response; return response;
} }

View File

@ -251,8 +251,8 @@ public class AzureBlobConnectionLiveTest {
} }
// Test HEAD of object // Test HEAD of object
BlobMetadata metadata = connection.getBlobProperties(privateContainer, object.getKey()); BlobMetadata metadata = connection.getBlobProperties(privateContainer, object.getName());
// TODO assertEquals(metadata.getKey(), object.getKey()); // TODO assertEquals(metadata.getName(), object.getName());
// we can't check this while hacking around lack of content-md5, as GET of the first byte will // we can't check this while hacking around lack of content-md5, as GET of the first byte will
// show incorrect length 1, the returned size, as opposed to the real length. This is an ok // show incorrect length 1, the returned size, as opposed to the real length. This is an ok
// tradeoff, as a container list will contain the correct size of the objects in an // tradeoff, as a container list will contain the correct size of the objects in an
@ -271,7 +271,7 @@ public class AzureBlobConnectionLiveTest {
// Multimap<String, String> userMetadata = HashMultimap.create(); // Multimap<String, String> userMetadata = HashMultimap.create();
// userMetadata.put("New-Metadata-1", "value-1"); // userMetadata.put("New-Metadata-1", "value-1");
// userMetadata.put("New-Metadata-2", "value-2"); // userMetadata.put("New-Metadata-2", "value-2");
// assertTrue(connection.setObjectMetadata(privateContainer, object.getKey(), userMetadata)); // assertTrue(connection.setObjectMetadata(privateContainer, object.getName(), userMetadata));
// Test GET of missing object // Test GET of missing object
try { try {
@ -281,10 +281,10 @@ public class AzureBlobConnectionLiveTest {
e.printStackTrace(); e.printStackTrace();
} }
// Test GET of object (including updated metadata) // Test GET of object (including updated metadata)
Blob getBlob = connection.getBlob(privateContainer, object.getKey()).get(120, Blob getBlob = connection.getBlob(privateContainer, object.getName()).get(120,
TimeUnit.SECONDS); TimeUnit.SECONDS);
assertEquals(IOUtils.toString((InputStream) getBlob.getData()), data); assertEquals(IOUtils.toString((InputStream) getBlob.getData()), data);
// TODO assertEquals(getBlob.getKey(), object.getKey()); // TODO assertEquals(getBlob.getName(), object.getName());
assertEquals(getBlob.getContentLength(), data.length()); assertEquals(getBlob.getContentLength(), data.length());
assertEquals(getBlob.getMetadata().getContentType(), "text/plain"); assertEquals(getBlob.getMetadata().getContentType(), "text/plain");
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(getBlob.getMetadata() assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(getBlob.getMetadata()
@ -323,7 +323,7 @@ public class AzureBlobConnectionLiveTest {
// Test GET with options // Test GET with options
// Non-matching ETag // Non-matching ETag
try { try {
connection.getBlob(privateContainer, object.getKey(), connection.getBlob(privateContainer, object.getName(),
GetOptions.Builder.ifETagDoesntMatch(newEtag)).get(120, TimeUnit.SECONDS); GetOptions.Builder.ifETagDoesntMatch(newEtag)).get(120, TimeUnit.SECONDS);
} catch (Exception e) { } catch (Exception e) {
assertEquals(e.getCause().getClass(), HttpResponseException.class); assertEquals(e.getCause().getClass(), HttpResponseException.class);
@ -331,7 +331,7 @@ public class AzureBlobConnectionLiveTest {
} }
// Matching ETag // Matching ETag
getBlob = connection.getBlob(privateContainer, object.getKey(), getBlob = connection.getBlob(privateContainer, object.getName(),
GetOptions.Builder.ifETagMatches(newEtag)).get(120, TimeUnit.SECONDS); GetOptions.Builder.ifETagMatches(newEtag)).get(120, TimeUnit.SECONDS);
assertEquals(getBlob.getMetadata().getETag(), newEtag); assertEquals(getBlob.getMetadata().getETag(), newEtag);
@ -339,7 +339,7 @@ public class AzureBlobConnectionLiveTest {
// doesn't work per // doesn't work per
// http://social.msdn.microsoft.com/Forums/en-US/windowsazure/thread/479fa63f-51df-4b66-96b5-33ae362747b6 // http://social.msdn.microsoft.com/Forums/en-US/windowsazure/thread/479fa63f-51df-4b66-96b5-33ae362747b6
// getBlob = connection // getBlob = connection
// .getBlob(privateContainer, object.getKey(), GetOptions.Builder.startAt(8)).get(120, // .getBlob(privateContainer, object.getName(), GetOptions.Builder.startAt(8)).get(120,
// TimeUnit.SECONDS); // TimeUnit.SECONDS);
// assertEquals(IOUtils.toString((InputStream) getBlob.getData()), data.substring(8)); // assertEquals(IOUtils.toString((InputStream) getBlob.getData()), data.substring(8));

View File

@ -122,7 +122,7 @@ public class AddMD5ToListBlobsResponseTest extends BaseHandlerTest {
), null, null, 4, "newblob2.txt", null, "myfolder/"); ), null, null, 4, "newblob2.txt", null, "myfolder/");
BoundedSortedSet<ListBlobsResponse> result = (BoundedSortedSet<ListBlobsResponse>) factory BoundedSortedSet<ListBlobsResponse> result = (BoundedSortedSet<ListBlobsResponse>) factory
.create(injector.getInstance(ContainerNameEnumerationResultsHandler.class)) .create(injector.getInstance(AddMD5ToListBlobsResponse.class))
.parse(is); .parse(is);
assertEquals(result, list); assertEquals(result, list);

View File

@ -66,7 +66,7 @@ public class BlobStoreContextImpl<S, C extends ContainerMetadata, M extends Blob
public B newBlob(String key) { public B newBlob(String key) {
Object object = blobProvider.get(); Object object = blobProvider.get();
B blob = (B) object; B blob = (B) object;
blob.getMetadata().setKey(key); blob.getMetadata().setName(key);
return blob; return blob;
} }

View File

@ -24,10 +24,7 @@
package org.jclouds.blobstore.binders; package org.jclouds.blobstore.binders;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
@ -36,20 +33,10 @@ import org.jclouds.http.HttpUtils;
import org.jclouds.rest.Binder; import org.jclouds.rest.Binder;
public class BindBlobToEntity implements Binder { public class BindBlobToEntity implements Binder {
private final String metadataPrefix;
@Inject
public BindBlobToEntity(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
this.metadataPrefix = metadataPrefix;
}
public void bindToRequest(HttpRequest request, Object entity) { public void bindToRequest(HttpRequest request, Object entity) {
Blob<?> object = (Blob<?>) entity; Blob<?> object = (Blob<?>) entity;
for (String key : object.getMetadata().getUserMetadata().keySet()) {
request.getHeaders().put(key.startsWith(metadataPrefix) ? key : metadataPrefix + key,
object.getMetadata().getUserMetadata().get(key));
}
request.setEntity(checkNotNull(object.getData(), "object.getContent()")); request.setEntity(checkNotNull(object.getData(), "object.getContent()"));
request.getHeaders() request.getHeaders()
.put( .put(

View File

@ -0,0 +1,52 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.blobstore.binders;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest;
public class BindBlobToEntityAndUserMetadataToHeadersWithPrefix extends BindBlobToEntity {
private final String metadataPrefix;
@Inject
public BindBlobToEntityAndUserMetadataToHeadersWithPrefix(
@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
this.metadataPrefix = metadataPrefix;
}
public void bindToRequest(HttpRequest request, Object entity) {
Blob<?> object = (Blob<?>) entity;
for (String key : object.getMetadata().getUserMetadata().keySet()) {
request.getHeaders().put(key.startsWith(metadataPrefix) ? key : metadataPrefix + key,
object.getMetadata().getUserMetadata().get(key));
}
super.bindToRequest(request, entity);
}
}

View File

@ -52,7 +52,7 @@ public class BindBlobToMultipartForm implements Binder {
public void bindToRequest(HttpRequest request, Object entity) { public void bindToRequest(HttpRequest request, Object entity) {
Blob<?> object = (Blob<?>) entity; Blob<?> object = (Blob<?>) entity;
Key key = BlobStoreUtils.parseKey(new Key("junk", object.getKey())); Key key = BlobStoreUtils.parseKey(new Key("junk", object.getName()));
Multimap<String, String> partHeaders = ImmutableMultimap.of("Content-Disposition", String Multimap<String, String> partHeaders = ImmutableMultimap.of("Content-Disposition", String
.format("form-data; name=\"%s\"; filename=\"%s\"", key.getKey(), key.getKey()), .format("form-data; name=\"%s\"; filename=\"%s\"", key.getKey(), key.getKey()),
HttpHeaders.CONTENT_TYPE, checkNotNull(object.getMetadata().getContentType(), HttpHeaders.CONTENT_TYPE, checkNotNull(object.getMetadata().getContentType(),

View File

@ -23,17 +23,12 @@
*/ */
package org.jclouds.blobstore.domain; package org.jclouds.blobstore.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.awt.Container; import java.awt.Container;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import javax.inject.Inject; import org.jclouds.blobstore.internal.BlobImpl;
import org.jclouds.http.HttpUtils; import com.google.inject.ImplementedBy;
import org.jclouds.http.HttpUtils.MD5InputStreamResult;
/** /**
* Value type for an HTTP Blob service. Blobs are stored in {@link Container containers} and consist * Value type for an HTTP Blob service. Blobs are stored in {@link Container containers} and consist
@ -43,81 +38,13 @@ import org.jclouds.http.HttpUtils.MD5InputStreamResult;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class Blob<M extends BlobMetadata> implements Comparable<Blob<M>> { @ImplementedBy(BlobImpl.class)
public interface Blob<M extends BlobMetadata> {
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Blob<M> other = (Blob<M>) obj;
if (contentLength != other.contentLength)
return false;
if (contentRange == null) {
if (other.contentRange != null)
return false;
} else if (!contentRange.equals(other.contentRange))
return false;
if (data == null) {
if (other.data != null)
return false;
} else if (!data.equals(other.data))
return false;
if (getMetadata() == null) {
if (other.getMetadata() != null)
return false;
} else if (!getMetadata().equals(other.getMetadata()))
return false;
return true;
}
@Override
public String toString() {
return "Blob [contentLength=" + contentLength + ", contentRange=" + contentRange + ", data="
+ data + ", metadata=" + getMetadata() + "]";
}
protected Object data;
private M metadata;
protected long contentLength = -1;
protected String contentRange;
@SuppressWarnings("unchecked")
public Blob(String key) {
// TODO: why are we getting a generic warning here?
this((M) new BlobMetadata(key));
}
@SuppressWarnings("unchecked")
@Inject
public Blob() {
this((M) new BlobMetadata());
}
public Blob(M metadata) {
this.setMetadata(metadata);
}
public Blob(M metadata, Object data) {
this(metadata);
setData(data);
}
public Blob(String key, Object data) {
this(key);
setData(data);
}
/** /**
* @see BlobMetadata#getKey() * @see BlobMetadata#getName()
*/ */
public String getKey() { String getName();
return getMetadata().getKey();
}
/** /**
* Sets entity for the request or the content from the response. If size isn't set, this will * Sets entity for the request or the content from the response. If size isn't set, this will
@ -127,11 +54,7 @@ public class Blob<M extends BlobMetadata> implements Comparable<Blob<M>> {
* typically InputStream for downloads, or File, byte [], String, or InputStream for * typically InputStream for downloads, or File, byte [], String, or InputStream for
* uploads. * uploads.
*/ */
public void setData(Object data) { void setData(Object data);
this.data = checkNotNull(data, "data");
if (getMetadata().getSize() == -1)
this.getMetadata().setSize(HttpUtils.calculateSize(data));
}
/** /**
* generate an MD5 Hash for the current data. * generate an MD5 Hash for the current data.
@ -143,46 +66,19 @@ public class Blob<M extends BlobMetadata> implements Comparable<Blob<M>> {
* @throws IOException * @throws IOException
* if there is a problem generating the hash. * if there is a problem generating the hash.
*/ */
public void generateMD5() throws IOException { void generateMD5() throws IOException;
checkState(data != null, "data");
if (data instanceof InputStream) {
MD5InputStreamResult result = HttpUtils.generateMD5Result((InputStream) data);
getMetadata().setSize(result.length);
getMetadata().setContentMD5(result.eTag);
setData(result.data);
} else {
getMetadata().setContentMD5(HttpUtils.md5(data));
}
}
/** /**
* @return InputStream, if downloading, or whatever was set during {@link #setData(Object)} * @return InputStream, if downloading, or whatever was set during {@link #setData(Object)}
*/ */
public Object getData() { Object getData();
return data;
}
/** /**
* @return System and User metadata relevant to this object. * @return System and User metadata relevant to this object.
*/ */
public M getMetadata() { M getMetadata();
return metadata;
}
@Override void setContentLength(long contentLength);
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (contentLength ^ (contentLength >>> 32));
result = prime * result + ((contentRange == null) ? 0 : contentRange.hashCode());
result = prime * result + ((data == null) ? 0 : data.hashCode());
result = prime * result + ((getMetadata() == null) ? 0 : getMetadata().hashCode());
return result;
}
public void setContentLength(long contentLength) {
this.contentLength = contentLength;
}
/** /**
* Returns the total size of the downloaded object, or the chunk that's available. * Returns the total size of the downloaded object, or the chunk that's available.
@ -194,13 +90,9 @@ public class Blob<M extends BlobMetadata> implements Comparable<Blob<M>> {
* @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH * @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
* @see GetObjectOptions * @see GetObjectOptions
*/ */
public long getContentLength() { long getContentLength();
return contentLength;
}
public void setContentRange(String contentRange) { void setContentRange(String contentRange);
this.contentRange = contentRange;
}
/** /**
* If this is not-null, {@link #getContentLength() } will the size of chunk of the Value available * If this is not-null, {@link #getContentLength() } will the size of chunk of the Value available
@ -209,16 +101,8 @@ public class Blob<M extends BlobMetadata> implements Comparable<Blob<M>> {
* @see org.jclouds.http.HttpHeaders#CONTENT_RANGE * @see org.jclouds.http.HttpHeaders#CONTENT_RANGE
* @see GetObjectOptions * @see GetObjectOptions
*/ */
public String getContentRange() { String getContentRange();
return contentRange;
}
public void setMetadata(M metadata) { void setMetadata(M metadata);
this.metadata = metadata;
}
public int compareTo(Blob<M> o) {
return (this == o) ? 0 : getKey().compareTo(o.getKey());
}
} }

View File

@ -23,120 +23,23 @@
*/ */
package org.jclouds.blobstore.domain; package org.jclouds.blobstore.domain;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.Map; import java.util.Map;
import javax.inject.Inject; import org.jclouds.blobstore.internal.BlobMetadataImpl;
import javax.ws.rs.core.MediaType;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.inject.ImplementedBy;
/** /**
* System and user Metadata for the {@link Blob}. * System and user Metadata for the {@link Blob}.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class BlobMetadata implements Comparable<BlobMetadata>, Serializable { @ImplementedBy(BlobMetadataImpl.class)
/** The serialVersionUID */ public interface BlobMetadata {
private static final long serialVersionUID = -5932618957134612231L;
protected String key; void setName(String key);
protected String eTag;
protected volatile long size = -1;
private byte[] contentMD5;
protected Multimap<String, String> allHeaders = HashMultimap.create();
protected Map<String, String> userMetadata = Maps.newHashMap();
protected DateTime lastModified;
protected String dataType = MediaType.APPLICATION_OCTET_STREAM;
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("BlobMetadata [key=").append(key).append(", eTag=").append(eTag).append(
", lastModified=").append(lastModified).append(", size=").append(size).append(
", dataType=").append(dataType).append(", userMetadata=").append(userMetadata)
.append("]");
return builder.toString();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dataType == null) ? 0 : dataType.hashCode());
result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
result = prime * result + ((key == null) ? 0 : key.hashCode());
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
result = prime * result + (int) (size ^ (size >>> 32));
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BlobMetadata other = (BlobMetadata) obj;
if (dataType == null) {
if (other.dataType != null)
return false;
} else if (!dataType.equals(other.dataType))
return false;
if (eTag == null) {
if (other.eTag != null)
return false;
} else if (!eTag.equals(other.eTag))
return false;
if (key == null) {
if (other.key != null)
return false;
} else if (!key.equals(other.key))
return false;
if (lastModified == null) {
if (other.lastModified != null)
return false;
} else if (!lastModified.equals(other.lastModified))
return false;
if (size != other.size)
return false;
if (userMetadata == null) {
if (other.userMetadata != null)
return false;
} else if (!userMetadata.equals(other.userMetadata))
return false;
return true;
}
@Inject
public BlobMetadata() {
super();
}
/**
* @param key
* @see #getKey()
*/
public BlobMetadata(String key) {
setKey(key);
}
public void setKey(String key) {
checkNotNull(key, "key");
checkArgument(!key.startsWith("/"), "keys cannot start with /");
this.key = key;
}
/** /**
* The key is the handle that you assign to an object that allows you retrieve it later. A key is * The key is the handle that you assign to an object that allows you retrieve it later. A key is
@ -145,30 +48,20 @@ public class BlobMetadata implements Comparable<BlobMetadata>, Serializable {
* *
* @see <a href= "http://docs.amazonwebservices.com/AmazonHTTP/2006-03-01/UsingKeys.html" /> * @see <a href= "http://docs.amazonwebservices.com/AmazonHTTP/2006-03-01/UsingKeys.html" />
*/ */
public String getKey() { String getName();
return key;
}
public DateTime getLastModified() { DateTime getLastModified();
return lastModified;
}
public void setLastModified(DateTime lastModified) { void setLastModified(DateTime lastModified);
this.lastModified = lastModified;
}
/** /**
* The size of the object, in bytes. * The size of the object, in bytes.
* *
* @see <a href= "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.13." /> * @see <a href= "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.13." />
*/ */
public long getSize() { long getSize();
return size;
}
public void setSize(long size) { void setSize(long size);
this.size = size;
}
/** /**
* A standard MIME type describing the format of the contents. If none is provided, the default * A standard MIME type describing the format of the contents. If none is provided, the default
@ -176,65 +69,28 @@ public class BlobMetadata implements Comparable<BlobMetadata>, Serializable {
* *
* @see <a href= "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.17." /> * @see <a href= "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.17." />
*/ */
public String getContentType() { String getContentType();
return dataType;
}
public void setContentType(String dataType) { void setContentType(String dataType);
this.dataType = dataType;
}
public void setContentMD5(byte[] contentMD5) { void setContentMD5(byte[] contentMD5);
if (contentMD5 != null) {
this.contentMD5 = new byte[contentMD5.length];
System.arraycopy(contentMD5, 0, this.contentMD5, 0, contentMD5.length);
}
}
public byte[] getContentMD5() { byte[] getContentMD5();
if (contentMD5 != null) {
byte[] retval = new byte[contentMD5.length];
System.arraycopy(this.contentMD5, 0, retval, 0, contentMD5.length);
return retval;
} else {
return null;
}
}
public void setETag(String eTag) { void setETag(String eTag);
this.eTag = eTag;
}
/** /**
* @return the eTag value stored in the Etag header returned by HTTP. * @return the eTag value stored in the Etag header returned by HTTP.
*/ */
public String getETag() { String getETag();
return eTag;
}
public void setUserMetadata(Map<String, String> userMetadata) { void setUserMetadata(Map<String, String> userMetadata);
this.userMetadata = userMetadata;
}
/** /**
* Any key-value pairs associated with the object. * Any key-value pairs associated with the object.
*/ */
public Map<String, String> getUserMetadata() { Map<String, String> getUserMetadata();
return userMetadata;
}
public void setAllHeaders(Multimap<String, String> allHeaders) { Multimap<String, String> getAllHeaders();
this.allHeaders = allHeaders;
}
/**
* @return all http response headers associated with this Value
*/
public Multimap<String, String> getAllHeaders() {
return allHeaders;
}
public int compareTo(BlobMetadata o) {
return (this == o) ? 0 : getKey().compareTo(o.getKey());
}
} }

View File

@ -23,62 +23,20 @@
*/ */
package org.jclouds.blobstore.domain; package org.jclouds.blobstore.domain;
import static com.google.common.base.Preconditions.checkNotNull; import org.jclouds.blobstore.internal.ContainerMetadataImpl;
import com.google.inject.ImplementedBy;
/** /**
* System metadata of the Container * System metadata of the Container
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class ContainerMetadata implements Comparable<ContainerMetadata> { @ImplementedBy(ContainerMetadataImpl.class)
public interface ContainerMetadata {
protected String name; void setName(String name);
/** String getName();
* @see #getName()
*/
public ContainerMetadata(String name) {
this.name = checkNotNull(name, "name");
}
public ContainerMetadata() {
super();
}
public void setName(String name) {
this.name = checkNotNull(name, "name");
}
public String getName() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ContainerMetadata other = (ContainerMetadata) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public int compareTo(ContainerMetadata o) {
return (this == o) ? 0 : getName().compareTo(o.getName());
}
} }

View File

@ -28,11 +28,11 @@ import org.jclouds.blobstore.domain.BlobMetadata;
import com.google.common.base.Function; import com.google.common.base.Function;
public class BlobKey implements Function<Object, String> { public class BlobName implements Function<Object, String> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public String apply(Object from) { public String apply(Object from) {
return ((Blob<BlobMetadata>) from).getKey(); return ((Blob<BlobMetadata>) from).getName();
} }
} }

View File

@ -52,7 +52,7 @@ public class ParseContentTypeFromHeaders<M extends BlobMetadata> implements
public M apply(HttpResponse from) { public M apply(HttpResponse from) {
String objectKey = getKeyFor(from); String objectKey = getKeyFor(from);
M to = metadataFactory.get(); M to = metadataFactory.get();
to.setKey(objectKey); to.setName(objectKey);
addAllHeadersTo(from, to); addAllHeadersTo(from, to);
setContentTypeOrThrowException(from, to); setContentTypeOrThrowException(from, to);
return to; return to;

View File

@ -140,7 +140,7 @@ public abstract class BaseBlobMap<C extends ContainerMetadata, M extends BlobMet
public Set<String> keySet() { public Set<String> keySet() {
Set<String> keys = Sets.newHashSet(); Set<String> keys = Sets.newHashSet();
for (BlobMetadata object : getAllBlobMetadata.execute(connection, containerName)) for (BlobMetadata object : getAllBlobMetadata.execute(connection, containerName))
keys.add(object.getKey()); keys.add(object.getName());
return keys; return keys;
} }

View File

@ -0,0 +1,226 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.blobstore.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.io.IOException;
import java.io.InputStream;
import javax.inject.Inject;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.HttpUtils.MD5InputStreamResult;
/**
* Value type for an HTTP Blob service. Blobs are stored in {@link ContainerMetadata containers} and consist
* of a {@link org.jclouds.blobstore.domain.Value#getData() value}, a {@link Blob#getKey key and
*
* @link Blob.Metadata#getUserMetadata() metadata}
*
* @author Adrian Cole
*/
public class BlobImpl<M extends BlobMetadata> implements Blob<M>, Comparable<Blob<M>> {
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BlobImpl<M> other = (BlobImpl<M>) obj;
if (contentLength != other.contentLength)
return false;
if (contentRange == null) {
if (other.contentRange != null)
return false;
} else if (!contentRange.equals(other.contentRange))
return false;
if (data == null) {
if (other.data != null)
return false;
} else if (!data.equals(other.data))
return false;
if (getMetadata() == null) {
if (other.getMetadata() != null)
return false;
} else if (!getMetadata().equals(other.getMetadata()))
return false;
return true;
}
@Override
public String toString() {
return "Blob [contentLength=" + contentLength + ", contentRange=" + contentRange + ", data="
+ data + ", metadata=" + getMetadata() + "]";
}
protected Object data;
private M metadata;
protected long contentLength = -1;
protected String contentRange;
@SuppressWarnings("unchecked")
public BlobImpl(String key) {
// TODO: why are we getting a generic warning here?
this((M) new BlobMetadataImpl(key));
}
@SuppressWarnings("unchecked")
@Inject
public BlobImpl() {
this((M) new BlobMetadataImpl());
}
public BlobImpl(M metadata) {
this.setMetadata(metadata);
}
public BlobImpl(M metadata, Object data) {
this(metadata);
setData(data);
}
public BlobImpl(String key, Object data) {
this(key);
setData(data);
}
/**
* @see BlobMetadata#getName()
*/
public String getName() {
return getMetadata().getName();
}
/**
* Sets entity for the request or the content from the response. If size isn't set, this will
* attempt to discover it.
*
* @param data
* typically InputStream for downloads, or File, byte [], String, or InputStream for
* uploads.
*/
public void setData(Object data) {
this.data = checkNotNull(data, "data");
if (getMetadata().getSize() == -1)
this.getMetadata().setSize(HttpUtils.calculateSize(data));
}
/**
* generate an MD5 Hash for the current data.
* <p/>
* <h2>Note</h2>
* <p/>
* If this is an InputStream, it will be converted to a byte array first.
*
* @throws IOException
* if there is a problem generating the hash.
*/
public void generateMD5() throws IOException {
checkState(data != null, "data");
if (data instanceof InputStream) {
MD5InputStreamResult result = HttpUtils.generateMD5Result((InputStream) data);
getMetadata().setSize(result.length);
getMetadata().setContentMD5(result.eTag);
setData(result.data);
} else {
getMetadata().setContentMD5(HttpUtils.md5(data));
}
}
/**
* @return InputStream, if downloading, or whatever was set during {@link #setData(Object)}
*/
public Object getData() {
return data;
}
/**
* @return System and User metadata relevant to this object.
*/
public M getMetadata() {
return metadata;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (contentLength ^ (contentLength >>> 32));
result = prime * result + ((contentRange == null) ? 0 : contentRange.hashCode());
result = prime * result + ((data == null) ? 0 : data.hashCode());
result = prime * result + ((getMetadata() == null) ? 0 : getMetadata().hashCode());
return result;
}
public void setContentLength(long contentLength) {
this.contentLength = contentLength;
}
/**
* Returns the total size of the downloaded object, or the chunk that's available.
* <p/>
* Chunking is only used when org.jclouds.http.GetOptions is called with options like tail,
* range, or startAt.
*
* @return the length in bytes that can be be obtained from {@link #getData()}
* @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
* @see GetObjectOptions
*/
public long getContentLength() {
return contentLength;
}
public void setContentRange(String contentRange) {
this.contentRange = contentRange;
}
/**
* If this is not-null, {@link #getContentLength() } will the size of chunk of the Value available
* via {@link #getData()}
*
* @see org.jclouds.http.HttpHeaders#CONTENT_RANGE
* @see GetObjectOptions
*/
public String getContentRange() {
return contentRange;
}
public void setMetadata(M metadata) {
this.metadata = metadata;
}
public int compareTo(Blob<M> o) {
return (this == o) ? 0 : getName().compareTo(o.getName());
}
}

View File

@ -79,7 +79,7 @@ public class BlobMapImpl<C extends ContainerMetadata, M extends BlobMetadata, B
public Set<java.util.Map.Entry<String, B>> entrySet() { public Set<java.util.Map.Entry<String, B>> entrySet() {
Set<Map.Entry<String, B>> entrySet = new HashSet<Map.Entry<String, B>>(); Set<Map.Entry<String, B>> entrySet = new HashSet<Map.Entry<String, B>>();
for (B value : values()) { for (B value : values()) {
Map.Entry<String, B> entry = new Entry(value.getKey(), value); Map.Entry<String, B> entry = new Entry(value.getName(), value);
entrySet.add(entry); entrySet.add(entry);
} }
return entrySet; return entrySet;

View File

@ -0,0 +1,247 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.blobstore.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;
import javax.inject.Inject;
import javax.ws.rs.core.MediaType;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.joda.time.DateTime;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
/**
* System and user Metadata for the {@link Blob}.
*
* @author Adrian Cole
*/
public class BlobMetadataImpl implements Serializable, BlobMetadata, Comparable<BlobMetadata> {
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BlobMetadataImpl other = (BlobMetadataImpl) obj;
if (!Arrays.equals(contentMD5, other.contentMD5))
return false;
if (dataType == null) {
if (other.dataType != null)
return false;
} else if (!dataType.equals(other.dataType))
return false;
if (eTag == null) {
if (other.eTag != null)
return false;
} else if (!eTag.equals(other.eTag))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (lastModified == null) {
if (other.lastModified != null)
return false;
} else if (!lastModified.equals(other.lastModified))
return false;
if (size != other.size)
return false;
if (userMetadata == null) {
if (other.userMetadata != null)
return false;
} else if (!userMetadata.equals(other.userMetadata))
return false;
return true;
}
/** The serialVersionUID */
private static final long serialVersionUID = -5932618957134612231L;
protected String name;
protected String eTag;
protected volatile long size = -1;
private byte[] contentMD5;
protected Multimap<String, String> allHeaders = HashMultimap.create();
protected Map<String, String> userMetadata = Maps.newHashMap();
protected DateTime lastModified;
protected String dataType = MediaType.APPLICATION_OCTET_STREAM;
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("BlobMetadata [name=").append(name).append(", eTag=").append(eTag).append(
", lastModified=").append(lastModified).append(", size=").append(size).append(
", dataType=").append(dataType).append(", userMetadata=").append(userMetadata)
.append("]");
return builder.toString();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(contentMD5);
result = prime * result + ((dataType == null) ? 0 : dataType.hashCode());
result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
result = prime * result + (int) (size ^ (size >>> 32));
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode());
return result;
}
@Inject
public BlobMetadataImpl() {
super();
}
/**
* @param name
* @see #getKey()
*/
public BlobMetadataImpl(String name) {
setName(name);
}
public void setName(String name) {
checkNotNull(name, "name");
checkArgument(!name.startsWith("/"), "names cannot start with /");
this.name = name;
}
/**
* The name is the handle that you assign to an object that allows you retrieve it later. A name
* is a sequence of Unicode characters whose UTF-8 encoding is at most 1024 bytes long. Each
* object in a bucket must have a unique name.
*
* @see <a href= "http://docs.amazonwebservices.com/AmazonHTTP/2006-03-01/UsingKeys.html" />
*/
public String getName() {
return name;
}
public DateTime getLastModified() {
return lastModified;
}
public void setLastModified(DateTime lastModified) {
this.lastModified = lastModified;
}
/**
* The size of the object, in bytes.
*
* @see <a href= "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.13." />
*/
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
/**
* A standard MIME type describing the format of the contents. If none is provided, the default
* is binary/octet-stream.
*
* @see <a href= "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.17." />
*/
public String getContentType() {
return dataType;
}
public void setContentType(String dataType) {
this.dataType = dataType;
}
public void setContentMD5(byte[] contentMD5) {
if (contentMD5 != null) {
this.contentMD5 = new byte[contentMD5.length];
System.arraycopy(contentMD5, 0, this.contentMD5, 0, contentMD5.length);
}
}
public byte[] getContentMD5() {
if (contentMD5 != null) {
byte[] retval = new byte[contentMD5.length];
System.arraycopy(this.contentMD5, 0, retval, 0, contentMD5.length);
return retval;
} else {
return null;
}
}
public void setETag(String eTag) {
this.eTag = eTag;
}
/**
* @return the eTag value stored in the Etag header returned by HTTP.
*/
public String getETag() {
return eTag;
}
public void setUserMetadata(Map<String, String> userMetadata) {
this.userMetadata = userMetadata;
}
/**
* Any key-value pairs associated with the object.
*/
public Map<String, String> getUserMetadata() {
return userMetadata;
}
public void setAllHeaders(Multimap<String, String> allHeaders) {
this.allHeaders = allHeaders;
}
/**
* @return all http response headers associated with this Value
*/
public Multimap<String, String> getAllHeaders() {
return allHeaders;
}
public int compareTo(BlobMetadata o) {
return (this == o) ? 0 : getName().compareTo(o.getName());
}
}

View File

@ -0,0 +1,86 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.blobstore.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.blobstore.domain.ContainerMetadata;
/**
* System metadata of the Container
*
* @author Adrian Cole
*/
public class ContainerMetadataImpl implements ContainerMetadata, Comparable<ContainerMetadata> {
protected String name;
/**
* @see #getName()
*/
public ContainerMetadataImpl(String name) {
this.name = checkNotNull(name, "name");
}
public ContainerMetadataImpl() {
super();
}
public void setName(String name) {
this.name = checkNotNull(name, "name");
}
public String getName() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ContainerMetadataImpl other = (ContainerMetadataImpl) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public int compareTo(ContainerMetadata o) {
return (this == o) ? 0 : getName().compareTo(o.getName());
}
}

View File

@ -144,7 +144,7 @@ public class InputStreamMapImpl<C extends ContainerMetadata, M extends BlobMetad
public Set<Map.Entry<String, InputStream>> entrySet() { public Set<Map.Entry<String, InputStream>> entrySet() {
Set<Map.Entry<String, InputStream>> entrySet = new HashSet<Map.Entry<String, InputStream>>(); Set<Map.Entry<String, InputStream>> entrySet = new HashSet<Map.Entry<String, InputStream>>();
for (B object : this.getAllBlobs.execute(connection, containerName)) { for (B object : this.getAllBlobs.execute(connection, containerName)) {
entrySet.add(new Entry(object.getKey(), (InputStream) object.getData())); entrySet.add(new Entry(object.getName(), (InputStream) object.getData()));
} }
return entrySet; return entrySet;
} }
@ -226,7 +226,7 @@ public class InputStreamMapImpl<C extends ContainerMetadata, M extends BlobMetad
Set<Future<String>> puts = Sets.newHashSet(); Set<Future<String>> puts = Sets.newHashSet();
for (Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) { for (Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
B object = blobFactory.get(); B object = blobFactory.get();
object.getMetadata().setKey(entry.getKey()); object.getMetadata().setName(entry.getKey());
object.setData(entry.getValue()); object.setData(entry.getValue());
object.generateMD5(); object.generateMD5();
puts.add(connection.putBlob(containerName, object)); puts.add(connection.putBlob(containerName, object));
@ -288,7 +288,7 @@ public class InputStreamMapImpl<C extends ContainerMetadata, M extends BlobMetad
@VisibleForTesting @VisibleForTesting
InputStream putInternal(String s, Object o) { InputStream putInternal(String s, Object o) {
B object = blobFactory.get(); B object = blobFactory.get();
object.getMetadata().setKey(s); object.getMetadata().setName(s);
try { try {
InputStream returnVal = containsKey(s) ? get(s) : null; InputStream returnVal = containsKey(s) ? get(s) : null;
object.setData(o); object.setData(o);

View File

@ -65,7 +65,7 @@ public class DeleteAllKeysClearContainerStrategy<C extends ContainerMetadata, M
public void execute(BlobStore<C, M, B> connection, final String containerName) { public void execute(BlobStore<C, M, B> connection, final String containerName) {
Set<Future<Void>> deletes = Sets.newHashSet(); Set<Future<Void>> deletes = Sets.newHashSet();
for (M md : getAllBlobMetadata.execute(connection, containerName)) { for (M md : getAllBlobMetadata.execute(connection, containerName)) {
deletes.add(connection.removeBlob(containerName, md.getKey())); deletes.add(connection.removeBlob(containerName, md.getName()));
} }
for (Future<Void> isdeleted : deletes) { for (Future<Void> isdeleted : deletes) {
try { try {

View File

@ -23,6 +23,7 @@
*/ */
package org.jclouds.blobstore.strategy.internal; package org.jclouds.blobstore.strategy.internal;
import java.util.Comparator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
@ -78,10 +79,16 @@ public class RetryOnNotFoundGetAllBlobsStrategy<C extends ContainerMetadata, M e
} }
public SortedSet<B> execute(BlobStore<C, M, B> connection, String container) { public SortedSet<B> execute(BlobStore<C, M, B> connection, String container) {
SortedSet<B> objects = Sets.<B> newTreeSet(); SortedSet<B> objects = Sets.<B> newTreeSet(new Comparator<B>() {
public int compare(B o1, B o2) {
return (o1 == o2) ? 0 : o1.getName().compareTo(o2.getName());
}
});
Map<String, Future<B>> futureObjects = Maps.newHashMap(); Map<String, Future<B>> futureObjects = Maps.newHashMap();
for (M md : getAllBlobMetadata.execute(connection, container)) { for (M md : getAllBlobMetadata.execute(connection, container)) {
futureObjects.put(md.getKey(), connection.getBlob(container, md.getKey())); futureObjects.put(md.getName(), connection.getBlob(container, md.getName()));
} }
for (Entry<String, Future<B>> futureObjectEntry : futureObjects.entrySet()) { for (Entry<String, Future<B>> futureObjectEntry : futureObjects.entrySet()) {
try { try {
@ -103,7 +110,7 @@ public class RetryOnNotFoundGetAllBlobsStrategy<C extends ContainerMetadata, M e
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
try { try {
B object = value.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); B object = value.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
object.getMetadata().setKey(key); object.getMetadata().setName(key);
objects.add(object); objects.add(object);
return; return;
} catch (KeyNotFoundException e) { } catch (KeyNotFoundException e) {

View File

@ -34,6 +34,7 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.internal.BlobImpl;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -55,7 +56,7 @@ public class BindBlobToMultipartFormTest {
addData(BOUNDRY, "hello", builder); addData(BOUNDRY, "hello", builder);
builder.append("--").append(BOUNDRY).append("--").append("\r\n"); builder.append("--").append(BOUNDRY).append("--").append("\r\n");
EXPECTS = builder.toString(); EXPECTS = builder.toString();
TEST_BLOB = new Blob<BlobMetadata>("hello"); TEST_BLOB = new BlobImpl<BlobMetadata>("hello");
TEST_BLOB.setData("hello"); TEST_BLOB.setData("hello");
TEST_BLOB.getMetadata().setContentType(MediaType.TEXT_PLAIN); TEST_BLOB.getMetadata().setContentType(MediaType.TEXT_PLAIN);
} }

View File

@ -29,6 +29,7 @@ import java.io.File;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import org.jclouds.blobstore.internal.BlobImpl;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@Test(groups = "unit", testName = "blobstore.BlobTest") @Test(groups = "unit", testName = "blobstore.BlobTest")
@ -36,7 +37,7 @@ public class BlobTest {
@Test @Test
void testSetNoContentType() { void testSetNoContentType() {
Blob<BlobMetadata> object = new Blob<BlobMetadata>("test"); Blob<BlobMetadata> object = new BlobImpl<BlobMetadata>("test");
File file = new File("hello.txt"); File file = new File("hello.txt");
object.setData(file); object.setData(file);
assertEquals(object.getMetadata().getContentType(), MediaType.APPLICATION_OCTET_STREAM); assertEquals(object.getMetadata().getContentType(), MediaType.APPLICATION_OCTET_STREAM);

View File

@ -36,6 +36,7 @@ import javax.ws.rs.core.HttpHeaders;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.internal.BlobImpl;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -65,7 +66,7 @@ public class ParseBlobFromHeadersAndHttpContentTest {
private Provider<Blob<BlobMetadata>> blobProvider = new Provider<Blob<BlobMetadata>>() { private Provider<Blob<BlobMetadata>> blobProvider = new Provider<Blob<BlobMetadata>>() {
public Blob<BlobMetadata> get() { public Blob<BlobMetadata> get() {
return new Blob<BlobMetadata>("key"); return new BlobImpl<BlobMetadata>("key");
} }
}; };

View File

@ -36,6 +36,7 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.internal.BlobMetadataImpl;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.GeneratedHttpRequest;
@ -52,7 +53,7 @@ public class ParseBlobMetadataFromHeadersTest {
private Provider<BlobMetadata> blobMetadataProvider = new Provider<BlobMetadata>() { private Provider<BlobMetadata> blobMetadataProvider = new Provider<BlobMetadata>() {
public BlobMetadata get() { public BlobMetadata get() {
return new BlobMetadata("key"); return new BlobMetadataImpl("key");
} }
}; };
@ -74,7 +75,7 @@ public class ParseBlobMetadataFromHeadersTest {
Multimap<String, String> allHeaders = ImmutableMultimap.of("key", "value"); Multimap<String, String> allHeaders = ImmutableMultimap.of("key", "value");
HttpResponse from = new HttpResponse(); HttpResponse from = new HttpResponse();
from.setHeaders(allHeaders); from.setHeaders(allHeaders);
BlobMetadata metadata = new BlobMetadata("test"); BlobMetadata metadata = new BlobMetadataImpl("test");
parser.addAllHeadersTo(from, metadata); parser.addAllHeadersTo(from, metadata);
assertEquals(metadata.getAllHeaders().get("key"), Collections.singletonList("value")); assertEquals(metadata.getAllHeaders().get("key"), Collections.singletonList("value"));
} }
@ -86,14 +87,14 @@ public class ParseBlobMetadataFromHeadersTest {
from.getHeaders().put(HttpHeaders.LAST_MODIFIED, "Wed, 09 Sep 2009 19:50:23 GMT"); from.getHeaders().put(HttpHeaders.LAST_MODIFIED, "Wed, 09 Sep 2009 19:50:23 GMT");
from.getHeaders().put(HttpHeaders.CONTENT_LENGTH, "100"); from.getHeaders().put(HttpHeaders.CONTENT_LENGTH, "100");
BlobMetadata metadata = parser.apply(from); BlobMetadata metadata = parser.apply(from);
assertEquals(metadata.getKey(), "key"); assertEquals(metadata.getName(), "key");
} }
@Test @Test
public void testSetContentLength() { public void testSetContentLength() {
HttpResponse from = new HttpResponse(); HttpResponse from = new HttpResponse();
from.getHeaders().put(HttpHeaders.CONTENT_LENGTH, "100"); from.getHeaders().put(HttpHeaders.CONTENT_LENGTH, "100");
BlobMetadata metadata = new BlobMetadata("test"); BlobMetadata metadata = new BlobMetadataImpl("test");
parser.setContentLengthOrThrowException(from, metadata); parser.setContentLengthOrThrowException(from, metadata);
assertEquals(metadata.getSize(), 100); assertEquals(metadata.getSize(), 100);
} }
@ -101,7 +102,7 @@ public class ParseBlobMetadataFromHeadersTest {
@Test(expectedExceptions = HttpException.class) @Test(expectedExceptions = HttpException.class)
public void testSetContentLengthException() { public void testSetContentLengthException() {
HttpResponse from = new HttpResponse(); HttpResponse from = new HttpResponse();
BlobMetadata metadata = new BlobMetadata("test"); BlobMetadata metadata = new BlobMetadataImpl("test");
parser.setContentLengthOrThrowException(from, metadata); parser.setContentLengthOrThrowException(from, metadata);
} }
@ -109,7 +110,7 @@ public class ParseBlobMetadataFromHeadersTest {
public void testSetContentType() { public void testSetContentType() {
HttpResponse from = new HttpResponse(); HttpResponse from = new HttpResponse();
from.getHeaders().put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON); from.getHeaders().put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
BlobMetadata metadata = new BlobMetadata("test"); BlobMetadata metadata = new BlobMetadataImpl("test");
parser.setContentTypeOrThrowException(from, metadata); parser.setContentTypeOrThrowException(from, metadata);
assertEquals(metadata.getContentType(), MediaType.APPLICATION_JSON); assertEquals(metadata.getContentType(), MediaType.APPLICATION_JSON);
} }
@ -117,7 +118,7 @@ public class ParseBlobMetadataFromHeadersTest {
@Test(expectedExceptions = HttpException.class) @Test(expectedExceptions = HttpException.class)
public void testSetContentTypeException() { public void testSetContentTypeException() {
HttpResponse from = new HttpResponse(); HttpResponse from = new HttpResponse();
BlobMetadata metadata = new BlobMetadata("test"); BlobMetadata metadata = new BlobMetadataImpl("test");
parser.setContentTypeOrThrowException(from, metadata); parser.setContentTypeOrThrowException(from, metadata);
} }
@ -125,7 +126,7 @@ public class ParseBlobMetadataFromHeadersTest {
public void testSetLastModified() { public void testSetLastModified() {
HttpResponse from = new HttpResponse(); HttpResponse from = new HttpResponse();
from.getHeaders().put(HttpHeaders.LAST_MODIFIED, "Wed, 09 Sep 2009 19:50:23 GMT"); from.getHeaders().put(HttpHeaders.LAST_MODIFIED, "Wed, 09 Sep 2009 19:50:23 GMT");
BlobMetadata metadata = new BlobMetadata("test"); BlobMetadata metadata = new BlobMetadataImpl("test");
parser.parseLastModifiedOrThrowException(from, metadata); parser.parseLastModifiedOrThrowException(from, metadata);
assertEquals(metadata.getLastModified(), new DateService() assertEquals(metadata.getLastModified(), new DateService()
.rfc822DateParse("Wed, 09 Sep 2009 19:50:23 GMT")); .rfc822DateParse("Wed, 09 Sep 2009 19:50:23 GMT"));
@ -134,7 +135,7 @@ public class ParseBlobMetadataFromHeadersTest {
@Test(expectedExceptions = HttpException.class) @Test(expectedExceptions = HttpException.class)
public void testSetLastModifiedException() { public void testSetLastModifiedException() {
HttpResponse from = new HttpResponse(); HttpResponse from = new HttpResponse();
BlobMetadata metadata = new BlobMetadata("test"); BlobMetadata metadata = new BlobMetadataImpl("test");
parser.parseLastModifiedOrThrowException(from, metadata); parser.parseLastModifiedOrThrowException(from, metadata);
} }
@ -142,7 +143,7 @@ public class ParseBlobMetadataFromHeadersTest {
public void testAddETagTo() { public void testAddETagTo() {
HttpResponse from = new HttpResponse(); HttpResponse from = new HttpResponse();
from.getHeaders().put(HttpHeaders.ETAG, "0xfeb"); from.getHeaders().put(HttpHeaders.ETAG, "0xfeb");
BlobMetadata metadata = new BlobMetadata("test"); BlobMetadata metadata = new BlobMetadataImpl("test");
parser.addETagTo(from, metadata); parser.addETagTo(from, metadata);
assertEquals(metadata.getETag(), "0xfeb"); assertEquals(metadata.getETag(), "0xfeb");
} }
@ -152,7 +153,7 @@ public class ParseBlobMetadataFromHeadersTest {
Multimap<String, String> allHeaders = ImmutableMultimap.of("prefix" + "key", "value"); Multimap<String, String> allHeaders = ImmutableMultimap.of("prefix" + "key", "value");
HttpResponse from = new HttpResponse(); HttpResponse from = new HttpResponse();
from.setHeaders(allHeaders); from.setHeaders(allHeaders);
BlobMetadata metadata = new BlobMetadata("test"); BlobMetadata metadata = new BlobMetadataImpl("test");
parser.addUserMetadataTo(from, metadata); parser.addUserMetadataTo(from, metadata);
assertEquals(metadata.getUserMetadata().get("key"), "value"); assertEquals(metadata.getUserMetadata().get("key"), "value");
} }

View File

@ -26,8 +26,8 @@ package org.jclouds.blobstore.integration;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.integration.internal.BaseBlobIntegrationTest; import org.jclouds.blobstore.integration.internal.BaseBlobIntegrationTest;
import org.jclouds.blobstore.internal.ContainerMetadataImpl;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
@ -37,6 +37,6 @@ import org.testng.annotations.Test;
*/ */
@Test(groups = { "integration"}, testName = "blobstore.StubBlobIntegrationTest") @Test(groups = { "integration"}, testName = "blobstore.StubBlobIntegrationTest")
public class StubBlobIntegrationTest extends public class StubBlobIntegrationTest extends
BaseBlobIntegrationTest<BlobStore<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>, ContainerMetadata, BlobMetadata, Blob<BlobMetadata>> { BaseBlobIntegrationTest<BlobStore<ContainerMetadataImpl, BlobMetadata, Blob<BlobMetadata>>, ContainerMetadataImpl, BlobMetadata, Blob<BlobMetadata>> {
} }

View File

@ -26,8 +26,8 @@ package org.jclouds.blobstore.integration;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.integration.internal.BaseBlobMapIntegrationTest; import org.jclouds.blobstore.integration.internal.BaseBlobMapIntegrationTest;
import org.jclouds.blobstore.internal.ContainerMetadataImpl;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
@ -36,6 +36,6 @@ import org.testng.annotations.Test;
@Test(groups = { "integration", "live" }, testName = "blobstore.StubBlobMapIntegrationTest") @Test(groups = { "integration", "live" }, testName = "blobstore.StubBlobMapIntegrationTest")
public class StubBlobMapIntegrationTest extends public class StubBlobMapIntegrationTest extends
BaseBlobMapIntegrationTest<BlobStore<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>, ContainerMetadata, BlobMetadata, Blob<BlobMetadata>> { BaseBlobMapIntegrationTest<BlobStore<ContainerMetadataImpl, BlobMetadata, Blob<BlobMetadata>>, ContainerMetadataImpl, BlobMetadata, Blob<BlobMetadata>> {
} }

View File

@ -26,8 +26,8 @@ package org.jclouds.blobstore.integration;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.integration.internal.BaseContainerIntegrationTest; import org.jclouds.blobstore.integration.internal.BaseContainerIntegrationTest;
import org.jclouds.blobstore.internal.ContainerMetadataImpl;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
@ -37,6 +37,6 @@ import org.testng.annotations.Test;
@Test(groups = { "integration", "live" }, testName = "blobstore.StubContainerIntegrationTest") @Test(groups = { "integration", "live" }, testName = "blobstore.StubContainerIntegrationTest")
public class StubContainerIntegrationTest public class StubContainerIntegrationTest
extends extends
BaseContainerIntegrationTest<BlobStore<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>, ContainerMetadata, BlobMetadata, Blob<BlobMetadata>> { BaseContainerIntegrationTest<BlobStore<ContainerMetadataImpl, BlobMetadata, Blob<BlobMetadata>>, ContainerMetadataImpl, BlobMetadata, Blob<BlobMetadata>> {
} }

View File

@ -26,8 +26,8 @@ package org.jclouds.blobstore.integration;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.integration.internal.BaseInputStreamMapIntegrationTest; import org.jclouds.blobstore.integration.internal.BaseInputStreamMapIntegrationTest;
import org.jclouds.blobstore.internal.ContainerMetadataImpl;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
@ -35,6 +35,6 @@ import org.testng.annotations.Test;
*/ */
@Test(groups = { "integration", "live" }, testName = "blobstore.StubInputStreamMapIntegrationTest") @Test(groups = { "integration", "live" }, testName = "blobstore.StubInputStreamMapIntegrationTest")
public class StubInputStreamMapIntegrationTest extends public class StubInputStreamMapIntegrationTest extends
BaseInputStreamMapIntegrationTest<BlobStore<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>, ContainerMetadata, BlobMetadata, Blob<BlobMetadata>> { BaseInputStreamMapIntegrationTest<BlobStore<ContainerMetadataImpl, BlobMetadata, Blob<BlobMetadata>>, ContainerMetadataImpl, BlobMetadata, Blob<BlobMetadata>> {
} }

View File

@ -26,8 +26,8 @@ package org.jclouds.blobstore.integration;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.integration.internal.BaseServiceIntegrationTest; import org.jclouds.blobstore.integration.internal.BaseServiceIntegrationTest;
import org.jclouds.blobstore.internal.ContainerMetadataImpl;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
@ -36,6 +36,6 @@ import org.testng.annotations.Test;
@Test(groups = { "integration", "live" }, testName = "blobstore.StubServiceIntegrationTest") @Test(groups = { "integration", "live" }, testName = "blobstore.StubServiceIntegrationTest")
public class StubServiceIntegrationTest public class StubServiceIntegrationTest
extends extends
BaseServiceIntegrationTest<BlobStore<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>, ContainerMetadata, BlobMetadata, Blob<BlobMetadata>> { BaseServiceIntegrationTest<BlobStore<ContainerMetadataImpl, BlobMetadata, Blob<BlobMetadata>>, ContainerMetadataImpl, BlobMetadata, Blob<BlobMetadata>> {
} }

View File

@ -46,8 +46,11 @@ public class StubBlobStoreConnectionModule extends AbstractModule {
protected void configure() { protected void configure() {
bind(new TypeLiteral<Map<String, Map<String, Blob<BlobMetadata>>>>() { bind(new TypeLiteral<Map<String, Map<String, Blob<BlobMetadata>>>>() {
}).toInstance(map); }).toInstance(map);
bind(new TypeLiteral<BlobStore<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() { bind(
}).to(new TypeLiteral<StubBlobStore<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() { new TypeLiteral<BlobStore<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() {
})
.to(
new TypeLiteral<StubBlobStore<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() {
}).asEagerSingleton(); }).asEagerSingleton();
} }
} }

View File

@ -357,7 +357,7 @@ public class BaseBlobIntegrationTest<S, C extends ContainerMetadata, M extends B
try { try {
assertNotNull(context.getBlobStore().putBlob(containerName, object).get(30, assertNotNull(context.getBlobStore().putBlob(containerName, object).get(30,
TimeUnit.SECONDS)); TimeUnit.SECONDS));
object = context.getBlobStore().getBlob(containerName, object.getKey()).get(30, object = context.getBlobStore().getBlob(containerName, object.getName()).get(30,
TimeUnit.SECONDS); TimeUnit.SECONDS);
String returnedString = BlobStoreUtils.getContentAsStringAndClose(object); String returnedString = BlobStoreUtils.getContentAsStringAndClose(object);
assertEquals(returnedString, realObject); assertEquals(returnedString, realObject);

View File

@ -168,11 +168,11 @@ public class BaseBlobMapIntegrationTest<S, C extends ContainerMetadata, M extend
B object = context.newBlob("one"); B object = context.newBlob("one");
object.setData(IOUtils.toInputStream("apple")); object.setData(IOUtils.toInputStream("apple"));
object.generateMD5(); object.generateMD5();
B old = map.put(object.getKey(), object); B old = map.put(object.getName(), object);
getOneReturnsAppleAndOldValueIsNull(map, old); getOneReturnsAppleAndOldValueIsNull(map, old);
object.setData(IOUtils.toInputStream("bear")); object.setData(IOUtils.toInputStream("bear"));
object.generateMD5(); object.generateMD5();
B apple = map.put(object.getKey(), object); B apple = map.put(object.getName(), object);
getOneReturnsBearAndOldValueIsApple(map, apple); getOneReturnsBearAndOldValueIsApple(map, apple);
} finally { } finally {
returnContainer(bucketName); returnContainer(bucketName);

View File

@ -43,6 +43,7 @@ import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata; import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.internal.ContainerMetadataImpl;
import org.jclouds.blobstore.util.BlobStoreUtils; import org.jclouds.blobstore.util.BlobStoreUtils;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
@ -166,10 +167,10 @@ public class BaseBlobStoreIntegrationTest<S, C extends ContainerMetadata, M exte
throws Exception { throws Exception {
try { try {
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
Iterable<ContainerMetadata> testContainers = Iterables.filter( Iterable<ContainerMetadataImpl> testContainers = Iterables.filter(
(SortedSet<ContainerMetadata>) context.getBlobStore().listContainers(), (SortedSet<ContainerMetadataImpl>) context.getBlobStore().listContainers(),
new Predicate<ContainerMetadata>() { new Predicate<ContainerMetadataImpl>() {
public boolean apply(ContainerMetadata input) { public boolean apply(ContainerMetadataImpl input) {
return input.getName().startsWith(CONTAINER_PREFIX.toLowerCase()); return input.getName().startsWith(CONTAINER_PREFIX.toLowerCase());
} }
}); });

View File

@ -28,6 +28,7 @@ import java.util.SortedSet;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata; import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.internal.ContainerMetadataImpl;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
@ -40,7 +41,7 @@ public class BaseServiceIntegrationTest<S, C extends ContainerMetadata, M extend
@Test(groups = { "integration", "live" }) @Test(groups = { "integration", "live" })
void containerDoesntExist() throws Exception { void containerDoesntExist() throws Exception {
SortedSet<C> list = context.getBlobStore().listContainers(); SortedSet<C> list = context.getBlobStore().listContainers();
assert !list.contains(new ContainerMetadata("shouldntexist")); assert !list.contains(new ContainerMetadataImpl("shouldntexist"));
} }
} }

View File

@ -35,6 +35,7 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutput; import java.io.ObjectOutput;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.SortedSet; import java.util.SortedSet;
@ -146,14 +147,22 @@ public class StubBlobStore<C extends ContainerMetadata, M extends BlobMetadata,
if (realContents == null) if (realContents == null)
throw new ContainerNotFoundException(name); throw new ContainerNotFoundException(name);
SortedSet<M> contents = Sets.newTreeSet(Iterables.transform(realContents.keySet(), SortedSet<M> contents = Sets.newTreeSet(new Comparator<M>() {
public int compare(M o1, M o2) {
return (o1 == o2) ? 0 : o1.getName().compareTo(o2.getName());
}
});
Iterables.addAll(contents, Iterables.transform(realContents.keySet(),
new Function<String, M>() { new Function<String, M>() {
public M apply(String key) { public M apply(String key) {
return realContents.get(key).getMetadata(); return realContents.get(key).getMetadata();
} }
})); }));
return Sets.newTreeSet(contents); return contents;
} }
}; };
} }
@ -184,7 +193,7 @@ public class StubBlobStore<C extends ContainerMetadata, M extends BlobMetadata,
public M copy(M in, String newKey) { public M copy(M in, String newKey) {
M newMd = copy(in); M newMd = copy(in);
newMd.setKey(newKey); newMd.setName(newKey);
return newMd; return newMd;
} }
@ -257,7 +266,14 @@ public class StubBlobStore<C extends ContainerMetadata, M extends BlobMetadata,
} }
public SortedSet<C> listContainers() { public SortedSet<C> listContainers() {
return Sets.newTreeSet(Iterables.transform(getContainerToBlobs().keySet(), SortedSet<C> returnVal = Sets.newTreeSet(new Comparator<C>() {
public int compare(C o1, C o2) {
return (o1 == o2) ? 0 : o1.getName().compareTo(o2.getName());
}
});
Iterables.addAll(returnVal, Iterables.transform(getContainerToBlobs().keySet(),
new Function<String, C>() { new Function<String, C>() {
public C apply(String name) { public C apply(String name) {
C cmd = containerMetaProvider.get(); C cmd = containerMetaProvider.get();
@ -266,6 +282,7 @@ public class StubBlobStore<C extends ContainerMetadata, M extends BlobMetadata,
} }
})); }));
return returnVal;
} }
public Future<Boolean> createContainer(final String name) { public Future<Boolean> createContainer(final String name) {
@ -297,9 +314,9 @@ public class StubBlobStore<C extends ContainerMetadata, M extends BlobMetadata,
public boolean apply(M metadata) { public boolean apply(M metadata) {
if (prefix == null) if (prefix == null)
return metadata.getKey().indexOf(delimiter) == -1; return metadata.getName().indexOf(delimiter) == -1;
if (metadata.getKey().startsWith(prefix)) if (metadata.getName().startsWith(prefix))
return metadata.getKey().replaceFirst(prefix, "").indexOf(delimiter) == -1; return metadata.getName().replaceFirst(prefix, "").indexOf(delimiter) == -1;
return false; return false;
} }
} }
@ -315,7 +332,7 @@ public class StubBlobStore<C extends ContainerMetadata, M extends BlobMetadata,
} }
public String apply(M metadata) { public String apply(M metadata) {
String working = metadata.getKey(); String working = metadata.getName();
if (prefix != null) { if (prefix != null) {
if (working.startsWith(prefix)) { if (working.startsWith(prefix)) {
@ -401,7 +418,7 @@ public class StubBlobStore<C extends ContainerMetadata, M extends BlobMetadata,
B blob = blobProvider.get(); B blob = blobProvider.get();
blob.setMetadata(newMd); blob.setMetadata(newMd);
blob.setData(data); blob.setData(data);
container.put(object.getKey(), blob); container.put(object.getName(), blob);
// Set HTTP headers to match metadata // Set HTTP headers to match metadata
newMd.getAllHeaders().put(HttpHeaders.LAST_MODIFIED, newMd.getAllHeaders().put(HttpHeaders.LAST_MODIFIED,

View File

@ -30,7 +30,6 @@ import java.util.Map;
import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobMap;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.BlobStoreContextImpl;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata; import org.jclouds.blobstore.domain.ContainerMetadata;
@ -86,14 +85,14 @@ public class BaseBlobMapTest {
assertEquals(type4, type5); assertEquals(type4, type5);
TypeLiteral type6 = new TypeLiteral<BlobStoreContextImpl<BlobStore<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>, ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() { TypeLiteral type6 = new TypeLiteral<BlobStoreContext<BlobStore<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>, ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() {
}; };
TypeLiteral type7 = TypeLiteral.get(Types.newParameterizedType(BlobStoreContextImpl.class, TypeLiteral type7 = TypeLiteral.get(Types.newParameterizedType(BlobStoreContext.class, Types
Types.newParameterizedType(BlobStore.class, ContainerMetadata.class, .newParameterizedType(BlobStore.class, ContainerMetadata.class, BlobMetadata.class,
BlobMetadata.class, Types.newParameterizedType(Blob.class, Types.newParameterizedType(Blob.class, BlobMetadata.class)),
BlobMetadata.class)), ContainerMetadata.class, BlobMetadata.class, ContainerMetadata.class, BlobMetadata.class, Types.newParameterizedType(Blob.class,
Types.newParameterizedType(Blob.class, BlobMetadata.class))); BlobMetadata.class)));
assertEquals(type6, type7); assertEquals(type6, type7);
} }

View File

@ -25,7 +25,6 @@ package org.jclouds.blobstore.strategy.internal;
import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock; import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay; import static org.easymock.classextension.EasyMock.replay;
import java.util.HashSet; import java.util.HashSet;
@ -40,6 +39,7 @@ import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata; import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.integration.StubBlobStoreContextBuilder; import org.jclouds.blobstore.integration.StubBlobStoreContextBuilder;
import org.jclouds.blobstore.internal.BlobImpl;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -73,7 +73,7 @@ public class RetryOnNotFoundGetAllBlobsStrategyTest {
public void testIfNotFoundRetryOtherwiseAddToSet() throws InterruptedException, public void testIfNotFoundRetryOtherwiseAddToSet() throws InterruptedException,
ExecutionException, TimeoutException { ExecutionException, TimeoutException {
Future<Blob<BlobMetadata>> futureObject = createMock(Future.class); Future<Blob<BlobMetadata>> futureObject = createMock(Future.class);
Blob<BlobMetadata> object = new Blob<BlobMetadata>("key"); Blob<BlobMetadata> object = new BlobImpl<BlobMetadata>("key");
expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andThrow( expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andThrow(
new KeyNotFoundException()); new KeyNotFoundException());
expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andReturn( expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andReturn(
@ -92,7 +92,7 @@ public class RetryOnNotFoundGetAllBlobsStrategyTest {
public void testIfNotFoundRetryOtherwiseAddToSetButNeverGetsIt() throws InterruptedException, public void testIfNotFoundRetryOtherwiseAddToSetButNeverGetsIt() throws InterruptedException,
ExecutionException, TimeoutException { ExecutionException, TimeoutException {
Future<Blob<BlobMetadata>> futureObject = createMock(Future.class); Future<Blob<BlobMetadata>> futureObject = createMock(Future.class);
Blob object = createNiceMock(Blob.class); Blob object = createMock(Blob.class);
expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andThrow( expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andThrow(
new KeyNotFoundException()).atLeastOnce(); new KeyNotFoundException()).atLeastOnce();
replay(futureObject); replay(futureObject);

View File

@ -42,7 +42,7 @@ public class BindFileInfoToXmlEntity implements Binder {
public void bindToRequest(HttpRequest request, Object toBind) { public void bindToRequest(HttpRequest request, Object toBind) {
Blob<?> blob = (Blob<?>) toBind; Blob<?> blob = (Blob<?>) toBind;
String bareKey = BlobStoreUtils.parseKey(new Key("trash", blob.getKey())).getKey(); String bareKey = BlobStoreUtils.parseKey(new Key("trash", blob.getName())).getKey();
String file = String.format( String file = String.format(
"<file><name>%s</name><mime_type>%s</mime_type><public>false</public></file>", "<file><name>%s</name><mime_type>%s</mime_type><public>false</public></file>",
bareKey, blob.getMetadata().getContentType()); bareKey, blob.getMetadata().getContentType());

View File

@ -32,7 +32,7 @@ import org.joda.time.DateTime;
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class ContainerMetadata extends org.jclouds.blobstore.domain.ContainerMetadata implements public class ContainerMetadata extends org.jclouds.blobstore.internal.ContainerMetadataImpl implements
PCSObject { PCSObject {
private URI url; private URI url;
private URI parent; private URI parent;

View File

@ -25,6 +25,7 @@ package org.jclouds.mezeo.pcs2.domain;
import java.net.URI; import java.net.URI;
import org.jclouds.blobstore.internal.BlobMetadataImpl;
import org.jclouds.mezeo.pcs2.util.PCSUtils; import org.jclouds.mezeo.pcs2.util.PCSUtils;
import org.joda.time.DateTime; import org.joda.time.DateTime;
@ -33,7 +34,7 @@ import org.joda.time.DateTime;
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class FileMetadata extends org.jclouds.blobstore.domain.BlobMetadata { public class FileMetadata extends BlobMetadataImpl {
/** The serialVersionUID */ /** The serialVersionUID */
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private URI url; private URI url;
@ -47,7 +48,7 @@ public class FileMetadata extends org.jclouds.blobstore.domain.BlobMetadata {
@Override @Override
public String toString() { public String toString() {
return "FileMetadata [key=" + key + ", created=" + created + ", isInProject=" + isInProject return "FileMetadata [key=" + name + ", created=" + created + ", isInProject=" + isInProject
+ ", isPublic=" + isPublic + ", isShared=" + isShared + ", owner=" + owner + ", isPublic=" + isPublic + ", isShared=" + isShared + ", owner=" + owner
+ ", url=" + url + ", version=" + version + ", allHeaders=" + allHeaders + ", url=" + url + ", version=" + version + ", allHeaders=" + allHeaders
+ ", dataType=" + dataType + ", eTag=" + eTag + ", accessed=" + ", dataType=" + dataType + ", eTag=" + eTag + ", accessed="

View File

@ -23,11 +23,13 @@
*/ */
package org.jclouds.mezeo.pcs2.domain; package org.jclouds.mezeo.pcs2.domain;
import org.jclouds.blobstore.internal.BlobImpl;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
public class PCSFile extends org.jclouds.blobstore.domain.Blob<FileMetadata> { public class PCSFile extends BlobImpl<FileMetadata> {
public PCSFile(FileMetadata metadata, FileMetadata data) { public PCSFile(FileMetadata metadata, FileMetadata data) {
super(metadata, data); super(metadata, data);

View File

@ -89,7 +89,7 @@ public class AddMetadataAndReturnId implements Function<HttpResponse, String>,
String container = request.getArgs()[0].toString(); String container = request.getArgs()[0].toString();
PCSFile file = (PCSFile) request.getArgs()[1]; PCSFile file = (PCSFile) request.getArgs()[1];
Key key = new Key(container, file.getKey()); Key key = new Key(container, file.getName());
String id = checkNotNull(fileCache.get(key), String.format( String id = checkNotNull(fileCache.get(key), String.format(
"file %s should have an id in cache by now", key)); "file %s should have an id in cache by now", key));

View File

@ -87,7 +87,7 @@ public class CreateSubFolderIfNotExistsAndGetResourceId implements Function<Obje
Object[] args = (Object[]) from; Object[] args = (Object[]) from;
checkArgument(args[0] instanceof String, "arg[0] must be a container name"); checkArgument(args[0] instanceof String, "arg[0] must be a container name");
checkArgument(args[1] instanceof Blob, "arg[1] must be a pcsfile"); checkArgument(args[1] instanceof Blob, "arg[1] must be a pcsfile");
Key key = BlobStoreUtils.parseKey(new Key(args[0].toString(), ((Blob) args[1]).getKey())); Key key = BlobStoreUtils.parseKey(new Key(args[0].toString(), ((Blob) args[1]).getName()));
try { try {
return finder.get(key.getContainer()); return finder.get(key.getContainer());
} catch (ComputationException e) { } catch (ComputationException e) {

View File

@ -93,7 +93,7 @@ public class CreateSubFolderIfNotExistsAndNewFileResource implements Function<Ob
URI newFile = connection.createFile(containerUri, file).get( URI newFile = connection.createFile(containerUri, file).get(
this.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); this.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
String id = PCSUtils.getFileId(newFile); String id = PCSUtils.getFileId(newFile);
fileCache.put(new Key(container, file.getKey()), id); fileCache.put(new Key(container, file.getName()), id);
return id; return id;
} catch (Exception e) { } catch (Exception e) {
Utils.<ContainerNotFoundException> rethrowIfRuntimeOrSameType(e); Utils.<ContainerNotFoundException> rethrowIfRuntimeOrSameType(e);

View File

@ -67,7 +67,7 @@ public class FindIdInFileList implements Function<Key, String> {
String idForNameInListOrException(String container, String toFind, String idForNameInListOrException(String container, String toFind,
SortedSet<FileMetadata> response) { SortedSet<FileMetadata> response) {
for (FileMetadata data : response) { for (FileMetadata data : response) {
if (toFind.equals(data.getKey())) { if (toFind.equals(data.getName())) {
String path = data.getUrl().getPath(); String path = data.getUrl().getPath();
int indexAfterContainersSlash = path.indexOf("files/") + "files/".length(); int indexAfterContainersSlash = path.indexOf("files/") + "files/".length();
return path.substring(indexAfterContainersSlash); return path.substring(indexAfterContainersSlash);

View File

@ -202,7 +202,7 @@ public class PCSBlobStoreTest {
return new StubBlobStore.FutureBase<URI>() { return new StubBlobStore.FutureBase<URI>() {
public URI get() throws InterruptedException, ExecutionException { public URI get() throws InterruptedException, ExecutionException {
return URI.create("http://localhost/" + object.getKey()); return URI.create("http://localhost/" + object.getName());
} }
}; };
} }

View File

@ -133,7 +133,7 @@ public class PCSConnectionLiveTest {
connection.deleteFile(objectURI).get(10, TimeUnit.SECONDS); connection.deleteFile(objectURI).get(10, TimeUnit.SECONDS);
// try sending it in 2 parts // try sending it in 2 parts
object.getMetadata().setKey("sad"); object.getMetadata().setName("sad");
objectURI = connection.createFile(container, object).get(30, TimeUnit.SECONDS); objectURI = connection.createFile(container, object).get(30, TimeUnit.SECONDS);
object.setData(data.substring(0, 2)); object.setData(data.substring(0, 2));

View File

@ -47,7 +47,7 @@ import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ParseURIList; import org.jclouds.http.functions.ParseURIFromListOrLocationHeaderIf20x;
import org.jclouds.http.functions.ReturnInputStream; import org.jclouds.http.functions.ReturnInputStream;
import org.jclouds.http.functions.ReturnVoidIf2xx; import org.jclouds.http.functions.ReturnVoidIf2xx;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
@ -108,7 +108,7 @@ public class PCSConnectionTest {
.singletonList("application/vnd.csp.container-info+xml")); .singletonList("application/vnd.csp.container-info+xml"));
assertEquals(httpMethod.getEntity(), "<container><name>container</name></container>"); assertEquals(httpMethod.getEntity(), "<container><name>container</name></container>");
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ParseURIList.class); ParseURIFromListOrLocationHeaderIf20x.class);
// TODO check generic type of response parser // TODO check generic type of response parser
} }
@ -181,7 +181,7 @@ public class PCSConnectionTest {
assertEquals(Utils.toStringAndClose((InputStream) httpMethod.getEntity()), assertEquals(Utils.toStringAndClose((InputStream) httpMethod.getEntity()),
BindBlobToMultipartFormTest.EXPECTS); BindBlobToMultipartFormTest.EXPECTS);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ParseURIList.class); ParseURIFromListOrLocationHeaderIf20x.class);
} }
public void testDownloadFile() throws SecurityException, NoSuchMethodException, IOException { public void testDownloadFile() throws SecurityException, NoSuchMethodException, IOException {

View File

@ -59,7 +59,7 @@ public class AssembleBlobFromBlobMetadataCallTest {
replay(response); replay(response);
PCSFile file = callable.apply(response); PCSFile file = callable.apply(response);
assertEquals(file.getMetadata(), metadata); assertEquals(file.getMetadata(), metadata);
assertEquals(file.getKey(), "blob"); assertEquals(file.getName(), "blob");
assertEquals(file.getData(), data); assertEquals(file.getData(), data);
assertEquals(file.getContentLength(), metadata.getSize()); assertEquals(file.getContentLength(), metadata.getSize());
} }

View File

@ -33,9 +33,9 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest; import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
import org.jclouds.blobstore.internal.BlobImpl;
import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.nirvanix.sdn.domain.UploadInfo; import org.jclouds.nirvanix.sdn.domain.UploadInfo;
import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeGroups;
@ -77,7 +77,7 @@ public class SDNConnectionLiveTest {
assertNotNull(uploadInfo.getToken()); assertNotNull(uploadInfo.getToken());
connection.upload(uploadInfo.getHost(), uploadInfo.getToken(), containerName, connection.upload(uploadInfo.getHost(), uploadInfo.getToken(), containerName,
new Blob<BlobMetadata>("test.txt", "value")).get(30, TimeUnit.SECONDS); new BlobImpl<BlobMetadata>("test.txt", "value")).get(30, TimeUnit.SECONDS);
String metadataS = connection.getMetadata(containerName + "/test.txt").get(30, String metadataS = connection.getMetadata(containerName + "/test.txt").get(30,
TimeUnit.SECONDS); TimeUnit.SECONDS);

View File

@ -35,10 +35,10 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.binders.BindBlobToEntity; import org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.functions.BlobKey; import org.jclouds.blobstore.functions.BlobName;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseETagHeader; import org.jclouds.http.functions.ParseETagHeader;
@ -113,7 +113,7 @@ public interface CloudFilesBlobStore extends
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
Future<String> putBlob( Future<String> putBlob(
@PathParam("container") String container, @PathParam("container") String container,
@PathParam("key") @ParamParser(BlobKey.class) @BinderParam(BindBlobToEntity.class) Blob<BlobMetadata> object); @PathParam("key") @ParamParser(BlobName.class) @BinderParam(BindBlobToEntityAndUserMetadataToHeadersWithPrefix.class) Blob<BlobMetadata> object);
@GET @GET
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class) @ResponseParser(ParseObjectFromHeadersAndHttpContent.class)

View File

@ -37,11 +37,11 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import org.jclouds.blobstore.binders.BindBlobToEntity; import org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix;
import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix; import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.functions.BlobKey; import org.jclouds.blobstore.functions.BlobName;
import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404; import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseETagHeader; import org.jclouds.http.functions.ParseETagHeader;
@ -205,7 +205,7 @@ public interface CloudFilesConnection {
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
Future<String> putObject( Future<String> putObject(
@PathParam("container") String container, @PathParam("container") String container,
@PathParam("key") @ParamParser(BlobKey.class) @BinderParam(BindBlobToEntity.class) Blob<BlobMetadata> object); @PathParam("key") @ParamParser(BlobName.class) @BinderParam(BindBlobToEntityAndUserMetadataToHeadersWithPrefix.class) Blob<BlobMetadata> object);
@GET @GET
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class) @ResponseParser(ParseObjectFromHeadersAndHttpContent.class)

View File

@ -30,12 +30,12 @@ import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.blobstore.binders.BindBlobToEntity; import org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
public class BindCFObjectAsEntity extends BindBlobToEntity { public class BindCFObjectAsEntity extends BindBlobToEntityAndUserMetadataToHeadersWithPrefix {
@Inject @Inject
public BindCFObjectAsEntity(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) { public BindCFObjectAsEntity(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
super(metadataPrefix); super(metadataPrefix);

View File

@ -28,7 +28,7 @@ package org.jclouds.rackspace.cloudfiles.domain;
* @author James Murty * @author James Murty
* *
*/ */
public class ContainerCDNMetadata extends org.jclouds.blobstore.domain.ContainerMetadata { public class ContainerCDNMetadata extends org.jclouds.blobstore.internal.ContainerMetadataImpl {
private long ttl; private long ttl;
private boolean cdn_enabled; private boolean cdn_enabled;

View File

@ -28,7 +28,7 @@ package org.jclouds.rackspace.cloudfiles.domain;
* @author Adrian Cole * @author Adrian Cole
* *
*/ */
public class ContainerMetadata extends org.jclouds.blobstore.domain.ContainerMetadata { public class ContainerMetadata extends org.jclouds.blobstore.internal.ContainerMetadataImpl {
private long count; private long count;
private long bytes; private long bytes;

View File

@ -27,11 +27,13 @@ import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Comparator;
import java.util.SortedSet; import java.util.SortedSet;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.internal.BlobMetadataImpl;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseJson; import org.jclouds.http.functions.ParseJson;
import org.joda.time.DateTime; import org.joda.time.DateTime;
@ -76,10 +78,17 @@ public class ParseBlobMetadataListFromJsonResponse extends ParseJson<SortedSet<B
try { try {
SortedSet<CloudFilesMetadata> list = gson.fromJson(new InputStreamReader(stream, "UTF-8"), SortedSet<CloudFilesMetadata> list = gson.fromJson(new InputStreamReader(stream, "UTF-8"),
listType); listType);
return Sets.newTreeSet(Iterables.transform(list, SortedSet<BlobMetadata> returnVal = Sets.newTreeSet(new Comparator<BlobMetadata>() {
public int compare(BlobMetadata o1, BlobMetadata o2) {
return (o1 == o2) ? 0 : o1.getName().compareTo(o2.getName());
}
});
Iterables.addAll(returnVal, Iterables.transform(list,
new Function<CloudFilesMetadata, BlobMetadata>() { new Function<CloudFilesMetadata, BlobMetadata>() {
public BlobMetadata apply(CloudFilesMetadata from) { public BlobMetadata apply(CloudFilesMetadata from) {
BlobMetadata metadata = new BlobMetadata(from.name); BlobMetadata metadata = new BlobMetadataImpl(from.name);
metadata.setSize(from.bytes); metadata.setSize(from.bytes);
metadata.setLastModified(from.last_modified); metadata.setLastModified(from.last_modified);
metadata.setContentType(from.content_type); metadata.setContentType(from.content_type);
@ -88,6 +97,7 @@ public class ParseBlobMetadataListFromJsonResponse extends ParseJson<SortedSet<B
return metadata; return metadata;
} }
})); }));
return returnVal;
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
throw new RuntimeException("jclouds requires UTF-8 encoding", e); throw new RuntimeException("jclouds requires UTF-8 encoding", e);

View File

@ -40,6 +40,7 @@ import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest; import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
import org.jclouds.blobstore.internal.BlobImpl;
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.http.options.GetOptions;
@ -277,7 +278,7 @@ public class CloudFilesConnectionLiveTest {
assertTrue(connection.createContainer(containerName).get(10, TimeUnit.SECONDS)); assertTrue(connection.createContainer(containerName).get(10, TimeUnit.SECONDS));
// Test PUT with string data, ETag hash, and a piece of metadata // Test PUT with string data, ETag hash, and a piece of metadata
Blob<BlobMetadata> object = new Blob<BlobMetadata>("object"); Blob<BlobMetadata> object = new BlobImpl<BlobMetadata>("object");
object.setData(data); object.setData(data);
object.setContentLength(data.length()); object.setContentLength(data.length());
object.generateMD5(); object.generateMD5();
@ -296,8 +297,8 @@ public class CloudFilesConnectionLiveTest {
} }
// Test HEAD of object // Test HEAD of object
BlobMetadata metadata = connection.getObjectMetadata(containerName, object.getKey()); BlobMetadata metadata = connection.getObjectMetadata(containerName, object.getName());
// TODO assertEquals(metadata.getKey(), object.getKey()); // TODO assertEquals(metadata.getName(), object.getName());
assertEquals(metadata.getSize(), data.length()); assertEquals(metadata.getSize(), data.length());
assertEquals(metadata.getContentType(), "text/plain"); assertEquals(metadata.getContentType(), "text/plain");
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(object.getMetadata() assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(object.getMetadata()
@ -310,7 +311,7 @@ public class CloudFilesConnectionLiveTest {
Map<String, String> userMetadata = Maps.newHashMap(); Map<String, String> userMetadata = Maps.newHashMap();
userMetadata.put("New-Metadata-1", "value-1"); userMetadata.put("New-Metadata-1", "value-1");
userMetadata.put("New-Metadata-2", "value-2"); userMetadata.put("New-Metadata-2", "value-2");
assertTrue(connection.setObjectMetadata(containerName, object.getKey(), userMetadata)); assertTrue(connection.setObjectMetadata(containerName, object.getName(), userMetadata));
// Test GET of missing object // Test GET of missing object
try { try {
@ -319,10 +320,10 @@ public class CloudFilesConnectionLiveTest {
} catch (KeyNotFoundException e) { } catch (KeyNotFoundException e) {
} }
// Test GET of object (including updated metadata) // Test GET of object (including updated metadata)
Blob<BlobMetadata> getBlob = connection.getObject(containerName, object.getKey()).get(120, Blob<BlobMetadata> getBlob = connection.getObject(containerName, object.getName()).get(120,
TimeUnit.SECONDS); TimeUnit.SECONDS);
assertEquals(IOUtils.toString((InputStream) getBlob.getData()), data); assertEquals(IOUtils.toString((InputStream) getBlob.getData()), data);
// TODO assertEquals(getBlob.getKey(), object.getKey()); // TODO assertEquals(getBlob.getName(), object.getName());
assertEquals(getBlob.getContentLength(), data.length()); assertEquals(getBlob.getContentLength(), data.length());
assertEquals(getBlob.getMetadata().getContentType(), "text/plain"); assertEquals(getBlob.getMetadata().getContentType(), "text/plain");
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(getBlob.getMetadata() assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(getBlob.getMetadata()
@ -345,7 +346,7 @@ public class CloudFilesConnectionLiveTest {
// Test PUT chunked/streamed upload with data of "unknown" length // Test PUT chunked/streamed upload with data of "unknown" length
ByteArrayInputStream bais = new ByteArrayInputStream(data.getBytes("UTF-8")); ByteArrayInputStream bais = new ByteArrayInputStream(data.getBytes("UTF-8"));
object = new Blob<BlobMetadata>("chunked-object"); object = new BlobImpl<BlobMetadata>("chunked-object");
object.setData(bais); object.setData(bais);
newEtag = connection.putObject(containerName, object).get(10, TimeUnit.SECONDS); newEtag = connection.putObject(containerName, object).get(10, TimeUnit.SECONDS);
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(getBlob.getMetadata() assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(getBlob.getMetadata()
@ -354,7 +355,7 @@ public class CloudFilesConnectionLiveTest {
// Test GET with options // Test GET with options
// Non-matching ETag // Non-matching ETag
try { try {
connection.getObject(containerName, object.getKey(), connection.getObject(containerName, object.getName(),
GetOptions.Builder.ifETagDoesntMatch(newEtag)).get(120, TimeUnit.SECONDS); GetOptions.Builder.ifETagDoesntMatch(newEtag)).get(120, TimeUnit.SECONDS);
} catch (Exception e) { } catch (Exception e) {
assertEquals(e.getCause().getClass(), HttpResponseException.class); assertEquals(e.getCause().getClass(), HttpResponseException.class);
@ -362,11 +363,12 @@ public class CloudFilesConnectionLiveTest {
} }
// Matching ETag // Matching ETag
getBlob = connection.getObject(containerName, object.getKey(), getBlob = connection.getObject(containerName, object.getName(),
GetOptions.Builder.ifETagMatches(newEtag)).get(120, TimeUnit.SECONDS); GetOptions.Builder.ifETagMatches(newEtag)).get(120, TimeUnit.SECONDS);
assertEquals(getBlob.getMetadata().getETag(), newEtag); assertEquals(getBlob.getMetadata().getETag(), newEtag);
getBlob = connection.getObject(containerName, object.getKey(), GetOptions.Builder.startAt(8)) getBlob = connection
.get(120, TimeUnit.SECONDS); .getObject(containerName, object.getName(), GetOptions.Builder.startAt(8)).get(120,
TimeUnit.SECONDS);
assertEquals(IOUtils.toString((InputStream) getBlob.getData()), data.substring(8)); assertEquals(IOUtils.toString((InputStream) getBlob.getData()), data.substring(8));
assertTrue(connection.removeObject(containerName, "object").get(10, TimeUnit.SECONDS)); assertTrue(connection.removeObject(containerName, "object").get(10, TimeUnit.SECONDS));

View File

@ -29,6 +29,8 @@ import java.io.InputStream;
import java.util.List; import java.util.List;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.internal.BlobMetadataImpl;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.config.ParserModule; import org.jclouds.http.functions.config.ParserModule;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -51,14 +53,16 @@ public class ParseBlobMetadataListFromJsonResponseTest {
public void testApplyInputStream() { public void testApplyInputStream() {
InputStream is = getClass().getResourceAsStream("/test_list_container.json"); InputStream is = getClass().getResourceAsStream("/test_list_container.json");
List<BlobMetadata> expects = Lists.newArrayList(); List<BlobMetadata> expects = Lists.newArrayList();
BlobMetadata one = new BlobMetadata("test_obj_1"); BlobMetadata one = new BlobMetadataImpl("test_obj_1");
one.setETag("4281c348eaf83e70ddce0e07221c3d28"); one.setETag("4281c348eaf83e70ddce0e07221c3d28");
one.setContentMD5(HttpUtils.fromHexString(one.getETag()));
one.setSize(14); one.setSize(14);
one.setContentType("application/octet-stream"); one.setContentType("application/octet-stream");
one.setLastModified(new DateTime("2009-02-03T05:26:32.612278")); one.setLastModified(new DateTime("2009-02-03T05:26:32.612278"));
expects.add(one); expects.add(one);
BlobMetadata two = new BlobMetadata("test_obj_2"); BlobMetadata two = new BlobMetadataImpl("test_obj_2");
two.setETag("b039efe731ad111bc1b0ef221c3849d0"); two.setETag("b039efe731ad111bc1b0ef221c3849d0");
two.setContentMD5(HttpUtils.fromHexString(two.getETag()));
two.setSize(64); two.setSize(64);
two.setContentType("application/octet-stream"); two.setContentType("application/octet-stream");
two.setLastModified(new DateTime("2009-02-03T05:26:32.612278")); two.setLastModified(new DateTime("2009-02-03T05:26:32.612278"));

View File

@ -29,6 +29,7 @@ import static org.testng.Assert.assertNotNull;
import javax.inject.Provider; import javax.inject.Provider;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.internal.BlobMetadataImpl;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.util.DateService; import org.jclouds.util.DateService;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -45,7 +46,7 @@ public class ParseObjectMetadataFromHeadersTest {
public void testEtagCaseIssue() { public void testEtagCaseIssue() {
ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders( ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders(
createNiceMock(DateService.class), "", createNiceMock(Provider.class)); createNiceMock(DateService.class), "", createNiceMock(Provider.class));
BlobMetadata md = new BlobMetadata("hello"); BlobMetadata md = new BlobMetadataImpl("hello");
HttpResponse response = new HttpResponse(); HttpResponse response = new HttpResponse();
response.getHeaders().put("Etag", "feb1"); response.getHeaders().put("Etag", "feb1");
parser.addETagTo(response, md); parser.addETagTo(response, md);