Issue 635:filesystem provider does not return md5 or etag on getBlob

This commit is contained in:
Adrian Cole 2011-07-23 23:21:06 +10:00
parent 81bf7268be
commit 6b9c68039b
5 changed files with 143 additions and 201 deletions

View File

@ -48,10 +48,10 @@ import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -66,14 +66,13 @@ import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobBuilder;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.MutableBlobMetadata; import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.MutableStorageMetadata; import org.jclouds.blobstore.domain.MutableStorageMetadata;
import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.PageSet;
import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.StorageType; import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.blobstore.domain.Blob.Factory;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl; import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl;
import org.jclouds.blobstore.domain.internal.PageSetImpl; import org.jclouds.blobstore.domain.internal.PageSetImpl;
import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions; import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions;
@ -96,10 +95,8 @@ import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.jclouds.http.options.HttpRequestOptions; import org.jclouds.http.options.HttpRequestOptions;
import org.jclouds.io.Payload;
import org.jclouds.io.Payloads; import org.jclouds.io.Payloads;
import org.jclouds.io.payloads.BaseMutableContentMetadata; import org.jclouds.io.payloads.BaseMutableContentMetadata;
import org.jclouds.io.payloads.FilePayload;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.annotations.ParamValidators; import org.jclouds.rest.annotations.ParamValidators;
@ -126,18 +123,15 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
protected final Crypto crypto; protected final Crypto crypto;
protected final HttpGetOptionsListToGetOptions httpGetOptionsConverter; protected final HttpGetOptionsListToGetOptions httpGetOptionsConverter;
protected final IfDirectoryReturnNameStrategy ifDirectoryReturnName; protected final IfDirectoryReturnNameStrategy ifDirectoryReturnName;
protected final Factory blobFactory;
protected final FilesystemStorageStrategy storageStrategy; protected final FilesystemStorageStrategy storageStrategy;
@Inject @Inject
protected FilesystemAsyncBlobStore(BlobStoreContext context, DateService dateService, Crypto crypto, protected FilesystemAsyncBlobStore(BlobStoreContext context, DateService dateService, Crypto crypto,
HttpGetOptionsListToGetOptions httpGetOptionsConverter, HttpGetOptionsListToGetOptions httpGetOptionsConverter, IfDirectoryReturnNameStrategy ifDirectoryReturnName,
IfDirectoryReturnNameStrategy ifDirectoryReturnName, Factory blobFactory, BlobUtils blobUtils, BlobUtils blobUtils, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation, Supplier<Location> defaultLocation, @Memoized Supplier<Set<? extends Location>> locations,
@Memoized Supplier<Set<? extends Location>> locations, FilesystemStorageStrategy storageStrategy) { FilesystemStorageStrategy storageStrategy) {
super(context, blobUtils, service, defaultLocation, locations); super(context, blobUtils, service, defaultLocation, locations);
// super(context, blobUtils, service, null, null);
this.blobFactory = blobFactory;
this.dateService = dateService; this.dateService = dateService;
this.crypto = crypto; this.crypto = crypto;
this.httpGetOptionsConverter = httpGetOptionsConverter; this.httpGetOptionsConverter = httpGetOptionsConverter;
@ -166,22 +160,22 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
} }
SortedSet<StorageMetadata> contents = newTreeSet(transform(blobBelongingToContainer, SortedSet<StorageMetadata> contents = newTreeSet(transform(blobBelongingToContainer,
new Function<String, StorageMetadata>() { new Function<String, StorageMetadata>() {
public StorageMetadata apply(String key) { public StorageMetadata apply(String key) {
Blob oldBlob = loadFileBlob(container, key); Blob oldBlob = loadFileBlob(container, key);
checkState(oldBlob != null, "blob " + key + " is not present although it was in the list of " checkState(oldBlob != null, "blob " + key + " is not present although it was in the list of "
+ container); + container);
checkState(oldBlob.getMetadata() != null, "blob " + container + "/" + key + " has no metadata"); checkState(oldBlob.getMetadata() != null, "blob " + container + "/" + key + " has no metadata");
MutableBlobMetadata md = copy(oldBlob.getMetadata()); MutableBlobMetadata md = copy(oldBlob.getMetadata());
String directoryName = ifDirectoryReturnName.execute(md); String directoryName = ifDirectoryReturnName.execute(md);
if (directoryName != null) { if (directoryName != null) {
md.setName(directoryName); md.setName(directoryName);
md.setType(StorageType.RELATIVE_PATH); md.setType(StorageType.RELATIVE_PATH);
}
return md;
} }
})); return md;
}
}));
String marker = null; String marker = null;
if (options != null) { if (options != null) {
@ -221,21 +215,21 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
if (delimiter != null) { if (delimiter != null) {
SortedSet<String> commonPrefixes = null; SortedSet<String> commonPrefixes = null;
Iterable<String> iterable = transform(contents, new CommonPrefixes(prefix != null ? prefix : null, Iterable<String> iterable = transform(contents, new CommonPrefixes(prefix != null ? prefix : null,
delimiter)); delimiter));
commonPrefixes = iterable != null ? newTreeSet(iterable) : new TreeSet<String>(); commonPrefixes = iterable != null ? newTreeSet(iterable) : new TreeSet<String>();
commonPrefixes.remove(CommonPrefixes.NO_PREFIX); commonPrefixes.remove(CommonPrefixes.NO_PREFIX);
contents = newTreeSet(filter(contents, new DelimiterFilter(prefix != null ? prefix : null, delimiter))); contents = newTreeSet(filter(contents, new DelimiterFilter(prefix != null ? prefix : null, delimiter)));
Iterables.<StorageMetadata> addAll(contents, transform(commonPrefixes, Iterables.<StorageMetadata> addAll(contents,
new Function<String, StorageMetadata>() { transform(commonPrefixes, new Function<String, StorageMetadata>() {
public StorageMetadata apply(String o) { public StorageMetadata apply(String o) {
MutableStorageMetadata md = new MutableStorageMetadataImpl(); MutableStorageMetadata md = new MutableStorageMetadataImpl();
md.setType(StorageType.RELATIVE_PATH); md.setType(StorageType.RELATIVE_PATH);
md.setName(o); md.setName(o);
return md; return md;
} }
})); }));
} }
// trim metadata, if the response isn't supposed to be detailed. // trim metadata, if the response isn't supposed to be detailed.
@ -247,11 +241,11 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
} }
return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(contents, return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(contents,
marker)); marker));
} }
private ContainerNotFoundException cnfe(final String name) { private ContainerNotFoundException cnfe(String name) {
return new ContainerNotFoundException(name, String.format("container %s not in filesystem", name)); return new ContainerNotFoundException(name, String.format("container %s not in filesystem", name));
} }
@ -265,7 +259,7 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
MutableBlobMetadata metadata = (MutableBlobMetadata) is.readObject(); MutableBlobMetadata metadata = (MutableBlobMetadata) is.readObject();
convertUserMetadataKeysToLowercase(metadata); convertUserMetadataKeysToLowercase(metadata);
metadata.setContentMetadata(BaseMutableContentMetadata.fromContentMetadata(in.getContentMetadata().toBuilder() metadata.setContentMetadata(BaseMutableContentMetadata.fromContentMetadata(in.getContentMetadata().toBuilder()
.build())); .build()));
return metadata; return metadata;
} catch (Exception e) { } catch (Exception e) {
propagate(e); propagate(e);
@ -292,7 +286,7 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public ListenableFuture<Void> removeBlob(final String container, final String key) { public ListenableFuture<Void> removeBlob(String container, String key) {
storageStrategy.removeBlob(container, key); storageStrategy.removeBlob(container, key);
return immediateFuture(null); return immediateFuture(null);
} }
@ -301,7 +295,7 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public ListenableFuture<Boolean> containerExists(final String containerName) { public ListenableFuture<Boolean> containerExists(String containerName) {
boolean exists = containerExistsSyncImpl(containerName); boolean exists = containerExistsSyncImpl(containerName);
return immediateFuture(exists); return immediateFuture(exists);
} }
@ -314,14 +308,14 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
Iterable<String> containers = storageStrategy.getAllContainerNames(); Iterable<String> containers = storageStrategy.getAllContainerNames();
return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(transform( return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(transform(
containers, new Function<String, StorageMetadata>() { containers, new Function<String, StorageMetadata>() {
public StorageMetadata apply(String name) { public StorageMetadata apply(String name) {
MutableStorageMetadata cmd = create(); MutableStorageMetadata cmd = create();
cmd.setName(name); cmd.setName(name);
cmd.setType(StorageType.CONTAINER); cmd.setType(StorageType.CONTAINER);
return cmd; return cmd;
} }
}), null)); }), null));
} }
protected MutableStorageMetadata create() { protected MutableStorageMetadata create() {
@ -334,7 +328,7 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
@Path("{container}") @Path("{container}")
@Override @Override
public ListenableFuture<Boolean> createContainerInLocation(final Location location, public ListenableFuture<Boolean> createContainerInLocation(final Location location,
@PathParam("container") @ParamValidators( { FilesystemContainerNameValidator.class }) String name) { @PathParam("container") @ParamValidators({ FilesystemContainerNameValidator.class }) String name) {
boolean result = storageStrategy.createContainer(name); boolean result = storageStrategy.createContainer(name);
return immediateFuture(result); return immediateFuture(result);
} }
@ -347,9 +341,9 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
} }
/** /**
* Load the blob with the given key belonging to the container with the given name. There must * Load the blob with the given key belonging to the container with the given
* exist a resource on the file system whose complete name is given concatenating the container * name. There must exist a resource on the file system whose complete name
* name and the key * is given concatenating the container name and the key
* *
* @param container * @param container
* it's the name of the container the blob belongs to * it's the name of the container the blob belongs to
@ -358,30 +352,20 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
* *
* @return the blob belonging to the given container with the given key * @return the blob belonging to the given container with the given key
*/ */
private Blob loadFileBlob(final String container, final String key) { private Blob loadFileBlob(String container, String key) {
logger.debug("Opening blob in container: %s - %s", container, key); logger.debug("Opening blob in container: %s - %s", container, key);
File blobPayload = storageStrategy.getFileForBlobKey(container, key); BlobBuilder builder = blobUtils.blobBuilder();
builder.name(key);
Payload payload = new FilePayload(blobPayload); File file = storageStrategy.getFileForBlobKey(container, key);
// Loading object metadata
MutableBlobMetadata metadata = new MutableBlobMetadataImpl();
metadata.setName(key);
metadata.setLastModified(new Date(blobPayload.lastModified()));
metadata.getContentMetadata().setContentLength(blobPayload.length());
// TODO What about the MD5? are we supposed to calculate it each time we load
// the file?
try { try {
payload = Payloads.calculateMD5(payload); builder.payload(file).calculateMD5();
} catch (IOException e) { } catch (IOException e) {
logger.error("An error occurred calculating MD5 for blob %s from container ", key, container); logger.error("An error occurred calculating MD5 for blob %s from container ", key, container);
Throwables.propagateIfPossible(e); Throwables.propagateIfPossible(e);
} }
metadata.getContentMetadata().setContentType(""); Blob blob = builder.build();
String eTag = CryptoStreams.hex(payload.getContentMetadata().getContentMD5()); if (blob.getPayload().getContentMetadata().getContentMD5() != null)
metadata.setETag(eTag); blob.getMetadata().setETag(CryptoStreams.hex(blob.getPayload().getContentMetadata().getContentMD5()));
// Creating new blob object
Blob blob = blobFactory.create(metadata);
blob.setPayload(blobPayload);
return blob; return blob;
} }
@ -504,7 +488,7 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
storageStrategy.writePayloadOnFile(containerName, blobKey, object.getPayload()); storageStrategy.writePayloadOnFile(containerName, blobKey, object.getPayload());
} catch (IOException e) { } catch (IOException e) {
logger.error(e, "An error occurred storing the new object with name [%s] to container [%s].", blobKey, logger.error(e, "An error occurred storing the new object with name [%s] to container [%s].", blobKey,
containerName); containerName);
Throwables.propagate(e); Throwables.propagate(e);
} }
return immediateFuture(eTag); return immediateFuture(eTag);
@ -551,7 +535,7 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
if (blob.getMetadata().getLastModified().before(modifiedSince)) { if (blob.getMetadata().getLastModified().before(modifiedSince)) {
HttpResponse response = new HttpResponse(304, null, null); HttpResponse response = new HttpResponse(304, null, null);
return immediateFailedFuture(new HttpResponseException(String.format("%1$s is before %2$s", blob return immediateFailedFuture(new HttpResponseException(String.format("%1$s is before %2$s", blob
.getMetadata().getLastModified(), modifiedSince), null, response)); .getMetadata().getLastModified(), modifiedSince), null, response));
} }
} }
@ -560,7 +544,7 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
if (blob.getMetadata().getLastModified().after(unmodifiedSince)) { if (blob.getMetadata().getLastModified().after(unmodifiedSince)) {
HttpResponse response = new HttpResponse(412, null, null); HttpResponse response = new HttpResponse(412, null, null);
return immediateFailedFuture(new HttpResponseException(String.format("%1$s is after %2$s", blob return immediateFailedFuture(new HttpResponseException(String.format("%1$s is after %2$s", blob
.getMetadata().getLastModified(), unmodifiedSince), null, response)); .getMetadata().getLastModified(), unmodifiedSince), null, response));
} }
} }
@ -602,10 +586,10 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public ListenableFuture<BlobMetadata> blobMetadata(final String container, final String key) { public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
try { try {
Blob blob = getBlob(container, key).get(); Blob blob = getBlob(container, key).get();
return immediateFuture(blob != null ? (BlobMetadata) copy(blob.getMetadata()) : null); return Futures.<BlobMetadata> immediateFuture(blob != null ? blob.getMetadata() : null);
} catch (Exception e) { } catch (Exception e) {
if (size(filter(getCausalChain(e), KeyNotFoundException.class)) >= 1) if (size(filter(getCausalChain(e), KeyNotFoundException.class)) >= 1)
return immediateFuture(null); return immediateFuture(null);
@ -620,8 +604,9 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
} }
/** /**
* Override parent method because it uses strange futures and listenables that creates problem in * Override parent method because it uses strange futures and listenables
* the test if more than one test that deletes the container is executed * that creates problem in the test if more than one test that deletes the
* container is executed
* *
* @param container * @param container
* @return * @return
@ -633,8 +618,8 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
} }
/** /**
* Each container is a directory, so in order to check if a container exists the corresponding * Each container is a directory, so in order to check if a container exists
* directory must exists. Synchronous implementation * the corresponding directory must exists. Synchronous implementation
* *
* @param containerName * @param containerName
* @return * @return
@ -670,7 +655,7 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
@Override @Override
public ListenableFuture<Boolean> createContainerInLocation(Location location, String container, public ListenableFuture<Boolean> createContainerInLocation(Location location, String container,
CreateContainerOptions options) { CreateContainerOptions options) {
if (options.isPublicRead()) if (options.isPublicRead())
throw new UnsupportedOperationException("publicRead"); throw new UnsupportedOperationException("publicRead");
return createContainerInLocation(location, container); return createContainerInLocation(location, container);

View File

@ -152,7 +152,7 @@ public interface FilesystemStorageStrategy {
* @param container * @param container
* @param key * @param key
*/ */
void removeBlob(final String container, final String key); void removeBlob(String container, String key);
/** /**
* Write a {@link Blob} {@link Payload} into a file * Write a {@link Blob} {@link Payload} into a file

View File

@ -24,13 +24,13 @@ import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider; import javax.inject.Provider;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
@ -47,8 +47,8 @@ import org.jclouds.logging.Logger;
import org.jclouds.rest.annotations.ParamValidators; import org.jclouds.rest.annotations.ParamValidators;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.inject.Inject; import com.google.common.io.Closeables;
import com.google.inject.name.Named; import com.google.common.io.Files;
/** /**
* *
@ -57,8 +57,6 @@ import com.google.inject.name.Named;
public class FilesystemStorageStrategyImpl implements FilesystemStorageStrategy { public class FilesystemStorageStrategyImpl implements FilesystemStorageStrategy {
private static final String BACK_SLASH = "\\"; private static final String BACK_SLASH = "\\";
/** The buffer size used to copy an InputStream to an OutputStream */
private static final int COPY_BUFFER_SIZE = 1024;
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@ -126,9 +124,8 @@ public class FilesystemStorageStrategyImpl implements FilesystemStorageStrategy
File containerFile = openFolder(container); File containerFile = openFolder(container);
File[] children = containerFile.listFiles(); File[] children = containerFile.listFiles();
if (null != children) { if (null != children) {
for (File child : children) { for (File child : children)
FileUtils.forceDelete(child); FileUtils.forceDelete(child);
}
} }
} catch (IOException e) { } catch (IOException e) {
logger.error(e, "An error occurred while clearing container %s", container); logger.error(e, "An error occurred while clearing container %s", container);
@ -201,41 +198,26 @@ public class FilesystemStorageStrategyImpl implements FilesystemStorageStrategy
public void writePayloadOnFile(String container, String blobKey, Payload payload) throws IOException { public void writePayloadOnFile(String container, String blobKey, Payload payload) throws IOException {
filesystemContainerNameValidator.validate(container); filesystemContainerNameValidator.validate(container);
filesystemBlobKeyValidator.validate(blobKey); filesystemBlobKeyValidator.validate(blobKey);
File outputFile = null; File outputFile = getFileForBlobKey(container, blobKey);
OutputStream output = null; if (payload.getRawContent().equals(outputFile)){
InputStream input = null; // we shouldn't re-copy the same contents
return;
}
FileOutputStream output = null;
try { try {
outputFile = getFileForBlobKey(container, blobKey); Files.createParentDirs(outputFile);
File parentDirectory = outputFile.getParentFile(); if (payload.getRawContent() instanceof File)
if (!parentDirectory.exists()) { Files.copy(File.class.cast(payload.getRawContent()), outputFile);
if (!parentDirectory.mkdirs()) { else
throw new IOException("An error occurred creating directory [" + parentDirectory.getName() + "]."); payload.writeTo(new FileOutputStream(outputFile));
}
}
output = new FileOutputStream(outputFile);
input = payload.getInput();
copy(input, output);
} catch (IOException ex) { } catch (IOException ex) {
if (outputFile != null) { if (outputFile != null) {
outputFile.delete(); outputFile.delete();
} }
throw ex; throw ex;
} finally { } finally {
if (input != null) { Closeables.closeQuietly(output);
try { payload.release();
input.close();
} catch (IOException ex) {
// Does nothing
}
}
if (output != null) {
try {
output.close();
} catch (IOException ex) {
// Does nothing
}
}
} }
} }
@ -494,31 +476,4 @@ public class FilesystemStorageStrategyImpl implements FilesystemStorageStrategy
return result; return result;
} }
/**
* Copy from an InputStream to an OutputStream.
*
* @param input
* The InputStream
* @param output
* The OutputStream
* @return the number of bytes copied
* @throws IOException
* if an error occurs
*/
private long copy(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[COPY_BUFFER_SIZE];
long count = 0;
while (true) {
int read = input.read(buffer);
if (read < 0) {
break;
}
count += read;
output.write(buffer, 0, read);
}
output.flush();
return count;
}
} }

View File

@ -48,6 +48,7 @@ import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.StorageType; import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.blobstore.options.GetOptions; import org.jclouds.blobstore.options.GetOptions;
import org.jclouds.blobstore.options.ListContainerOptions; import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.filesystem.reference.FilesystemConstants; import org.jclouds.filesystem.reference.FilesystemConstants;
import org.jclouds.filesystem.utils.TestUtils; import org.jclouds.filesystem.utils.TestUtils;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
@ -179,9 +180,9 @@ public class FilesystemAsyncBlobStoreTest {
checkForContainerContent(CONTAINER_NAME, null); checkForContainerContent(CONTAINER_NAME, null);
// creates blobs in first container // creates blobs in first container
Set<String> blobsExpected = TestUtils.createBlobsInContainer(CONTAINER_NAME, new String[] { Set<String> blobsExpected = TestUtils.createBlobsInContainer(CONTAINER_NAME, "bbb" + File.separator + "ccc"
"bbb" + File.separator + "ccc" + File.separator + "ddd" + File.separator + "1234.jpg", "4rrr.jpg", + File.separator + "ddd" + File.separator + "1234.jpg", "4rrr.jpg", "rrr" + File.separator + "sss"
"rrr" + File.separator + "sss" + File.separator + "788.jpg", "xdc" + File.separator + "wert.kpg" }); + File.separator + "788.jpg", "xdc" + File.separator + "wert.kpg");
checkForContainerContent(CONTAINER_NAME, blobsExpected); checkForContainerContent(CONTAINER_NAME, blobsExpected);
} }
@ -214,17 +215,17 @@ public class FilesystemAsyncBlobStoreTest {
// creates blobs in first container // creates blobs in first container
Set<String> blobNamesCreatedInContainer1 = TestUtils.createBlobsInContainer(CONTAINER_NAME, Set<String> blobNamesCreatedInContainer1 = TestUtils.createBlobsInContainer(CONTAINER_NAME, "bbb"
new String[] { "bbb" + File.separator + "ccc" + File.separator + "ddd" + File.separator + "1234.jpg", + File.separator + "ccc" + File.separator + "ddd" + File.separator + "1234.jpg",
TestUtils.createRandomBlobKey(), "rrr" + File.separator + "sss" + File.separator + "788.jpg", TestUtils.createRandomBlobKey(), "rrr" + File.separator + "sss" + File.separator + "788.jpg", "xdc"
"xdc" + File.separator + "wert.kpg" }); + File.separator + "wert.kpg");
// creates blobs in second container // creates blobs in second container
blobStore.createContainerInLocation(null, CONTAINER_NAME2); blobStore.createContainerInLocation(null, CONTAINER_NAME2);
Set<String> blobNamesCreatedInContainer2 = TestUtils.createBlobsInContainer(CONTAINER_NAME2, new String[] { Set<String> blobNamesCreatedInContainer2 = TestUtils.createBlobsInContainer(CONTAINER_NAME2, "asd"
"asd" + File.separator + "bbb" + File.separator + "ccc" + File.separator + "ddd" + File.separator + File.separator + "bbb" + File.separator + "ccc" + File.separator + "ddd" + File.separator + "1234.jpg",
+ "1234.jpg", TestUtils.createRandomBlobKey(), TestUtils.createRandomBlobKey(), "rrr" + File.separator + "sss" + File.separator + "788.jpg", "xdc"
"rrr" + File.separator + "sss" + File.separator + "788.jpg", "xdc" + File.separator + "wert.kpg" }); + File.separator + "wert.kpg");
// test blobs in first container // test blobs in first container
checkForContainerContent(CONTAINER_NAME, blobNamesCreatedInContainer1); checkForContainerContent(CONTAINER_NAME, blobNamesCreatedInContainer1);
@ -238,9 +239,9 @@ public class FilesystemAsyncBlobStoreTest {
checkForContainerContent(CONTAINER_NAME, null); checkForContainerContent(CONTAINER_NAME, null);
// creates blobs in first container // creates blobs in first container
Set<String> blobsExpected = TestUtils.createBlobsInContainer(CONTAINER_NAME, new String[] { Set<String> blobsExpected = TestUtils.createBlobsInContainer(CONTAINER_NAME, "bbb" + File.separator + "ccc"
"bbb" + File.separator + "ccc" + File.separator + "ddd" + File.separator + "1234.jpg", "4rrr.jpg", + File.separator + "ddd" + File.separator + "1234.jpg", "4rrr.jpg", "rrr" + File.separator + "sss"
"rrr" + File.separator + "sss" + File.separator + "788.jpg", "rrr" + File.separator + "wert.kpg" }); + File.separator + "788.jpg", "rrr" + File.separator + "wert.kpg");
// remove not expected values // remove not expected values
blobsExpected.remove("bbb" + File.separator + "ccc" + File.separator + "ddd" + File.separator + "1234.jpg"); blobsExpected.remove("bbb" + File.separator + "ccc" + File.separator + "ddd" + File.separator + "1234.jpg");
@ -257,8 +258,8 @@ public class FilesystemAsyncBlobStoreTest {
} }
/** /**
* Integration test, because clearContainer is not redefined in {@link FilesystemAsyncBlobStore} * Integration test, because clearContainer is not redefined in
* class * {@link FilesystemAsyncBlobStore} class
*/ */
public void testClearContainer_NoOptions() throws IOException { public void testClearContainer_NoOptions() throws IOException {
final String CONTAINER_NAME2 = "containerToClear"; final String CONTAINER_NAME2 = "containerToClear";
@ -268,17 +269,17 @@ public class FilesystemAsyncBlobStoreTest {
blobStore.createContainerInLocation(null, CONTAINER_NAME2); blobStore.createContainerInLocation(null, CONTAINER_NAME2);
// creates blobs in first container // creates blobs in first container
Set<String> blobNamesCreatedInContainer1 = TestUtils.createBlobsInContainer(CONTAINER_NAME, Set<String> blobNamesCreatedInContainer1 = TestUtils.createBlobsInContainer(CONTAINER_NAME, "bbb"
new String[] { "bbb" + File.separator + "ccc" + File.separator + "ddd" + File.separator + "1234.jpg", + File.separator + "ccc" + File.separator + "ddd" + File.separator + "1234.jpg",
TestUtils.createRandomBlobKey(), "rrr" + File.separator + "sss" + File.separator + "788.jpg", TestUtils.createRandomBlobKey(), "rrr" + File.separator + "sss" + File.separator + "788.jpg", "xdc"
"xdc" + File.separator + "wert.kpg" }); + File.separator + "wert.kpg");
// creates blobs in second container // creates blobs in second container
blobStore.createContainerInLocation(null, CONTAINER_NAME2); blobStore.createContainerInLocation(null, CONTAINER_NAME2);
Set<String> blobNamesCreatedInContainer2 = TestUtils.createBlobsInContainer(CONTAINER_NAME2, new String[] { Set<String> blobNamesCreatedInContainer2 = TestUtils.createBlobsInContainer(CONTAINER_NAME2, "asd"
"asd" + File.separator + "bbb" + File.separator + "ccc" + File.separator + "ddd" + File.separator + File.separator + "bbb" + File.separator + "ccc" + File.separator + "ddd" + File.separator + "1234.jpg",
+ "1234.jpg", TestUtils.createRandomBlobKey(), TestUtils.createRandomBlobKey(), "rrr" + File.separator + "sss" + File.separator + "788.jpg", "xdc"
"rrr" + File.separator + "sss" + File.separator + "788.jpg", "xdc" + File.separator + "wert.kpg" }); + File.separator + "wert.kpg");
// test blobs in containers // test blobs in containers
checkForContainerContent(CONTAINER_NAME, blobNamesCreatedInContainer1); checkForContainerContent(CONTAINER_NAME, blobNamesCreatedInContainer1);
@ -294,8 +295,8 @@ public class FilesystemAsyncBlobStoreTest {
} }
/** /**
* Integration test, because countBlobs is not redefined in {@link FilesystemAsyncBlobStore} * Integration test, because countBlobs is not redefined in
* class * {@link FilesystemAsyncBlobStore} class
*/ */
public void testCountBlobs_NotExistingContainer() { public void testCountBlobs_NotExistingContainer() {
try { try {
@ -306,8 +307,8 @@ public class FilesystemAsyncBlobStoreTest {
} }
/** /**
* Integration test, because countBlobs is not redefined in {@link FilesystemAsyncBlobStore} * Integration test, because countBlobs is not redefined in
* class * {@link FilesystemAsyncBlobStore} class
*/ */
public void testCountBlobs_NoOptionsEmptyContainer() { public void testCountBlobs_NoOptionsEmptyContainer() {
blobStore.createContainerInLocation(null, CONTAINER_NAME); blobStore.createContainerInLocation(null, CONTAINER_NAME);
@ -319,8 +320,8 @@ public class FilesystemAsyncBlobStoreTest {
} }
/** /**
* Integration test, because countBlobs is not redefined in {@link FilesystemAsyncBlobStore} * Integration test, because countBlobs is not redefined in
* class * {@link FilesystemAsyncBlobStore} class
*/ */
public void testCountBlobs_NoOptions() { public void testCountBlobs_NoOptions() {
blobStore.createContainerInLocation(null, CONTAINER_NAME); blobStore.createContainerInLocation(null, CONTAINER_NAME);
@ -342,7 +343,7 @@ public class FilesystemAsyncBlobStoreTest {
assertFalse(result, "Blob exists"); assertFalse(result, "Blob exists");
// create the blob // create the blob
TestUtils.createBlobsInContainer(CONTAINER_NAME, new String[] { BLOB_KEY }); TestUtils.createBlobsInContainer(CONTAINER_NAME, BLOB_KEY);
result = blobStore.blobExists(CONTAINER_NAME, BLOB_KEY); result = blobStore.blobExists(CONTAINER_NAME, BLOB_KEY);
assertTrue(result, "Blob exists"); assertTrue(result, "Blob exists");
@ -366,7 +367,7 @@ public class FilesystemAsyncBlobStoreTest {
assertFalse(result, "Blob2 exists"); assertFalse(result, "Blob2 exists");
// create the blob // create the blob
TestUtils.createBlobsInContainer(CONTAINER_NAME, new String[] { BLOB_KEY1, BLOB_KEY2 }); TestUtils.createBlobsInContainer(CONTAINER_NAME, BLOB_KEY1, BLOB_KEY2);
result = blobStore.blobExists(CONTAINER_NAME, BLOB_KEY1); result = blobStore.blobExists(CONTAINER_NAME, BLOB_KEY1);
assertTrue(result, "Blob " + BLOB_KEY1 + " doesn't exist"); assertTrue(result, "Blob " + BLOB_KEY1 + " doesn't exist");
result = blobStore.blobExists(CONTAINER_NAME, BLOB_KEY2); result = blobStore.blobExists(CONTAINER_NAME, BLOB_KEY2);
@ -401,7 +402,7 @@ public class FilesystemAsyncBlobStoreTest {
TestUtils.fileExists(TARGET_CONTAINER_NAME + File.separator + BLOB_KEY, false); TestUtils.fileExists(TARGET_CONTAINER_NAME + File.separator + BLOB_KEY, false);
// create the blob // create the blob
TestUtils.createBlobsInContainer(CONTAINER_NAME, new String[] { BLOB_KEY }); TestUtils.createBlobsInContainer(CONTAINER_NAME, BLOB_KEY);
result = blobStore.blobExists(CONTAINER_NAME, BLOB_KEY); result = blobStore.blobExists(CONTAINER_NAME, BLOB_KEY);
assertTrue(result, "Blob doesn't exist"); assertTrue(result, "Blob doesn't exist");
@ -416,8 +417,9 @@ public class FilesystemAsyncBlobStoreTest {
} }
/** /**
* Test of removeBlob method, with two blobs with a complex path as key and when first blob is * Test of removeBlob method, with two blobs with a complex path as key and
* removed, not all of its key's path is removed, because it is shared with the second blob's key * when first blob is removed, not all of its key's path is removed, because
* it is shared with the second blob's key
*/ */
public void testRemoveBlob_TwoComplexBlobKeys() throws IOException { public void testRemoveBlob_TwoComplexBlobKeys() throws IOException {
final String BLOB_KEY1 = TestUtils.createRandomBlobKey("aa/bb/cc/dd/", null); final String BLOB_KEY1 = TestUtils.createRandomBlobKey("aa/bb/cc/dd/", null);
@ -433,7 +435,7 @@ public class FilesystemAsyncBlobStoreTest {
assertFalse(result, "Blob2 exists"); assertFalse(result, "Blob2 exists");
// create the blobs // create the blobs
TestUtils.createBlobsInContainer(CONTAINER_NAME, new String[] { BLOB_KEY1, BLOB_KEY2 }); TestUtils.createBlobsInContainer(CONTAINER_NAME, BLOB_KEY1, BLOB_KEY2);
result = blobStore.blobExists(CONTAINER_NAME, BLOB_KEY1); result = blobStore.blobExists(CONTAINER_NAME, BLOB_KEY1);
assertTrue(result, "Blob " + BLOB_KEY1 + " doesn't exist"); assertTrue(result, "Blob " + BLOB_KEY1 + " doesn't exist");
result = blobStore.blobExists(CONTAINER_NAME, BLOB_KEY2); result = blobStore.blobExists(CONTAINER_NAME, BLOB_KEY2);
@ -476,7 +478,8 @@ public class FilesystemAsyncBlobStoreTest {
} }
/** /**
* Test of createContainerInLocation method, of class FilesystemAsyncBlobStore. * Test of createContainerInLocation method, of class
* FilesystemAsyncBlobStore.
*/ */
public void testCreateContainerInLocation() throws IOException { public void testCreateContainerInLocation() throws IOException {
final String CONTAINER_NAME2 = "funambol-test-2"; final String CONTAINER_NAME2 = "funambol-test-2";
@ -505,8 +508,8 @@ public class FilesystemAsyncBlobStoreTest {
} }
/** /**
* Test of putBlob method, of class FilesystemAsyncBlobStore. with a simple filename - no path in * Test of putBlob method, of class FilesystemAsyncBlobStore. with a simple
* the filename, eg filename.jpg * filename - no path in the filename, eg filename.jpg
*/ */
public void testPutBlobSimpleName() { public void testPutBlobSimpleName() {
blobStore.createContainerInLocation(null, CONTAINER_NAME); blobStore.createContainerInLocation(null, CONTAINER_NAME);
@ -515,7 +518,8 @@ public class FilesystemAsyncBlobStoreTest {
} }
/** /**
* Test of putBlob method with a complex key, with path in the filename, eg picture/filename.jpg * Test of putBlob method with a complex key, with path in the filename, eg
* picture/filename.jpg
*/ */
public void testPutBlobComplexName1() { public void testPutBlobComplexName1() {
blobStore.createContainerInLocation(null, CONTAINER_NAME); blobStore.createContainerInLocation(null, CONTAINER_NAME);
@ -526,7 +530,8 @@ public class FilesystemAsyncBlobStoreTest {
} }
/** /**
* Test of putBlob method with a complex key, with path in the filename, eg picture/filename.jpg * Test of putBlob method with a complex key, with path in the filename, eg
* picture/filename.jpg
*/ */
public void testPutBlobComplexName2() { public void testPutBlobComplexName2() {
blobStore.createContainerInLocation(null, CONTAINER_NAME); blobStore.createContainerInLocation(null, CONTAINER_NAME);
@ -589,7 +594,7 @@ public class FilesystemAsyncBlobStoreTest {
assertNull(resultBlob, "Blob exists"); assertNull(resultBlob, "Blob exists");
// create blob // create blob
TestUtils.createBlobsInContainer(CONTAINER_NAME, new String[] { blobKey }); TestUtils.createBlobsInContainer(CONTAINER_NAME, blobKey);
resultBlob = blobStore.getBlob(CONTAINER_NAME, blobKey, options); resultBlob = blobStore.getBlob(CONTAINER_NAME, blobKey, options);
@ -608,7 +613,7 @@ public class FilesystemAsyncBlobStoreTest {
public void testBlobMetadata_withDefaultMetadata() throws IOException { public void testBlobMetadata_withDefaultMetadata() throws IOException {
String BLOB_KEY = TestUtils.createRandomBlobKey(null, null); String BLOB_KEY = TestUtils.createRandomBlobKey(null, null);
// create the blob // create the blob
TestUtils.createBlobsInContainer(CONTAINER_NAME, new String[] { BLOB_KEY }); TestUtils.createBlobsInContainer(CONTAINER_NAME, BLOB_KEY);
BlobMetadata metadata = blobStore.blobMetadata(CONTAINER_NAME, BLOB_KEY); BlobMetadata metadata = blobStore.blobMetadata(CONTAINER_NAME, BLOB_KEY);
assertNotNull(metadata, "Metadata null"); assertNotNull(metadata, "Metadata null");
@ -616,7 +621,8 @@ public class FilesystemAsyncBlobStoreTest {
assertEquals(metadata.getName(), BLOB_KEY, "Wrong blob name"); assertEquals(metadata.getName(), BLOB_KEY, "Wrong blob name");
assertEquals(metadata.getType(), StorageType.BLOB, "Wrong blob type"); assertEquals(metadata.getType(), StorageType.BLOB, "Wrong blob type");
assertEquals(metadata.getContentMetadata().getContentType(), "application/unknown", "Wrong blob content-type"); assertEquals(metadata.getContentMetadata().getContentType(), "application/unknown", "Wrong blob content-type");
assertEquals(metadata.getContentMetadata().getContentMD5(), null, "Wrong blob MD5"); assertEquals(CryptoStreams.hex(metadata.getContentMetadata().getContentMD5()), metadata.getETag(),
"Wrong blob MD5");
assertEquals(metadata.getLocation(), null, "Wrong blob location"); assertEquals(metadata.getLocation(), null, "Wrong blob location");
assertEquals(metadata.getProviderId(), null, "Wrong blob provider id"); assertEquals(metadata.getProviderId(), null, "Wrong blob provider id");
assertEquals(metadata.getUri(), null, "Wrong blob URI"); assertEquals(metadata.getUri(), null, "Wrong blob URI");
@ -625,8 +631,6 @@ public class FilesystemAsyncBlobStoreTest {
// metadata.getLastModified() // metadata.getLastModified()
File file = new File(TARGET_CONTAINER_NAME + File.separator + BLOB_KEY); File file = new File(TARGET_CONTAINER_NAME + File.separator + BLOB_KEY);
assertEquals(metadata.getContentMetadata().getContentLength(), new Long(file.length()), "Wrong blob size"); assertEquals(metadata.getContentMetadata().getContentLength(), new Long(file.length()), "Wrong blob size");
// don't know how to calculate ETAG
// assertEquals(metadata.getETag(), "105cf4e6c052d65352dabd20028ff102", "Wrong blob ETag");
} }
public void testDeleteContainer_NotExistingContainer() { public void testDeleteContainer_NotExistingContainer() {
@ -667,15 +671,13 @@ public class FilesystemAsyncBlobStoreTest {
TestUtils.directoryExists(TARGET_CONTAINER_NAME2, true); TestUtils.directoryExists(TARGET_CONTAINER_NAME2, true);
// create blobs inside container // create blobs inside container
TestUtils.createBlobsInContainer(CONTAINER_NAME, new String[] { TestUtils.createBlobsInContainer(CONTAINER_NAME, TestUtils.createRandomBlobKey("testutils-", null),
TestUtils.createRandomBlobKey("testutils-", null), TestUtils.createRandomBlobKey("testutils-", null), TestUtils.createRandomBlobKey("testutils-", null),
TestUtils.createRandomBlobKey("ab123s" + File.separator + "testutils-", null), }); TestUtils.createRandomBlobKey("ab123s" + File.separator + "testutils-", null));
TestUtils.createBlobsInContainer( TestUtils.createBlobsInContainer(CONTAINER_NAME, TestUtils.createRandomBlobKey("testutils-", null),
CONTAINER_NAME, TestUtils.createRandomBlobKey("testutils-", null),
new String[] { TestUtils.createRandomBlobKey("testutils-", null), TestUtils.createRandomBlobKey("asda123s" + File.separator + "testutils-", null),
TestUtils.createRandomBlobKey("testutils-", null), TestUtils.createRandomBlobKey("123-_3s" + File.separator + "testutils-", null));
TestUtils.createRandomBlobKey("asda123s" + File.separator + "testutils-", null),
TestUtils.createRandomBlobKey("123-_3s" + File.separator + "testutils-", null), });
// delete first container // delete first container
blobStore.deleteContainer(CONTAINER_NAME); blobStore.deleteContainer(CONTAINER_NAME);

View File

@ -76,7 +76,7 @@ public class TestUtils {
* @return a Set with all blobs created * @return a Set with all blobs created
* @throws IOException * @throws IOException
*/ */
public static Set<String> createBlobsInContainer(String containerName, String[] blobNames) throws IOException { public static Set<String> createBlobsInContainer(String containerName, String... blobNames) throws IOException {
Set<String> blobNamesCreatedInContainer = new HashSet<String>(); Set<String> blobNamesCreatedInContainer = new HashSet<String>();
for (String blobName : blobNames) { for (String blobName : blobNames) {
createBlobAsFile(containerName, blobName, getImageForBlobPayload()); createBlobAsFile(containerName, blobName, getImageForBlobPayload());