mirror of https://github.com/apache/jclouds.git
Merge pull request #738 from andrewgaul/local-blobstore-move-helper-method
Move helper method to TransientStorageStrategy
This commit is contained in:
commit
b890765e9e
|
@ -70,9 +70,6 @@ import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy;
|
||||||
import org.jclouds.blobstore.util.BlobStoreUtils;
|
import org.jclouds.blobstore.util.BlobStoreUtils;
|
||||||
import org.jclouds.blobstore.util.BlobUtils;
|
import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.collect.Memoized;
|
import org.jclouds.collect.Memoized;
|
||||||
import org.jclouds.crypto.Crypto;
|
|
||||||
import org.jclouds.crypto.CryptoStreams;
|
|
||||||
import org.jclouds.date.DateService;
|
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.filesystem.predicates.validators.FilesystemContainerNameValidator;
|
import org.jclouds.filesystem.predicates.validators.FilesystemContainerNameValidator;
|
||||||
import org.jclouds.http.HttpCommand;
|
import org.jclouds.http.HttpCommand;
|
||||||
|
@ -83,7 +80,6 @@ import org.jclouds.http.HttpUtils;
|
||||||
import org.jclouds.io.ContentMetadata;
|
import org.jclouds.io.ContentMetadata;
|
||||||
import org.jclouds.io.ContentMetadataCodec;
|
import org.jclouds.io.ContentMetadataCodec;
|
||||||
import org.jclouds.io.Payload;
|
import org.jclouds.io.Payload;
|
||||||
import org.jclouds.io.Payloads;
|
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.annotations.ParamValidators;
|
import org.jclouds.rest.annotations.ParamValidators;
|
||||||
|
|
||||||
|
@ -106,8 +102,6 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
@Resource
|
@Resource
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
protected final DateService dateService;
|
|
||||||
protected final Crypto crypto;
|
|
||||||
protected final ContentMetadataCodec contentMetadataCodec;
|
protected final ContentMetadataCodec contentMetadataCodec;
|
||||||
protected final IfDirectoryReturnNameStrategy ifDirectoryReturnName;
|
protected final IfDirectoryReturnNameStrategy ifDirectoryReturnName;
|
||||||
protected final Factory blobFactory;
|
protected final Factory blobFactory;
|
||||||
|
@ -119,14 +113,11 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
@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,
|
||||||
DateService dateService, Crypto crypto,
|
|
||||||
ContentMetadataCodec contentMetadataCodec,
|
ContentMetadataCodec contentMetadataCodec,
|
||||||
IfDirectoryReturnNameStrategy ifDirectoryReturnName,
|
IfDirectoryReturnNameStrategy ifDirectoryReturnName,
|
||||||
Factory blobFactory, LocalStorageStrategy storageStrategy) {
|
Factory blobFactory, LocalStorageStrategy storageStrategy) {
|
||||||
super(context, blobUtils, service, defaultLocation, locations);
|
super(context, blobUtils, service, defaultLocation, locations);
|
||||||
this.blobFactory = blobFactory;
|
this.blobFactory = blobFactory;
|
||||||
this.dateService = dateService;
|
|
||||||
this.crypto = crypto;
|
|
||||||
this.contentMetadataCodec = contentMetadataCodec;
|
this.contentMetadataCodec = contentMetadataCodec;
|
||||||
this.ifDirectoryReturnName = ifDirectoryReturnName;
|
this.ifDirectoryReturnName = ifDirectoryReturnName;
|
||||||
this.storageStrategy = storageStrategy;
|
this.storageStrategy = storageStrategy;
|
||||||
|
@ -419,15 +410,12 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
storageStrategy.putBlob(containerName, blob);
|
return immediateFuture(storageStrategy.putBlob(containerName, blob));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.error(e, "An error occurred storing the new blob with name [%s] to container [%s].", blobKey,
|
logger.error(e, "An error occurred storing the new blob with name [%s] to container [%s].", blobKey,
|
||||||
containerName);
|
containerName);
|
||||||
Throwables.propagate(e);
|
throw Throwables.propagate(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
String eTag = getEtag(blob);
|
|
||||||
return immediateFuture(eTag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void copyPayloadHeadersToBlob(Payload payload, Blob blob) {
|
private void copyPayloadHeadersToBlob(Payload payload, Blob blob) {
|
||||||
|
@ -550,24 +538,6 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the object MD5 and returns it as eTag
|
|
||||||
*
|
|
||||||
* @param object
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private String getEtag(Blob object) {
|
|
||||||
try {
|
|
||||||
Payloads.calculateMD5(object, crypto.md5());
|
|
||||||
} catch (IOException ex) {
|
|
||||||
logger.error(ex, "An error occurred calculating MD5 for object with name %s.", object.getMetadata().getName());
|
|
||||||
Throwables.propagate(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
String eTag = CryptoStreams.hex(object.getPayload().getContentMetadata().getContentMD5());
|
|
||||||
return eTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Blob copyBlob(Blob blob) {
|
private Blob copyBlob(Blob blob) {
|
||||||
Blob returnVal = blobFactory.create(BlobStoreUtils.copy(blob.getMetadata()));
|
Blob returnVal = blobFactory.create(BlobStoreUtils.copy(blob.getMetadata()));
|
||||||
returnVal.setPayload(blob.getPayload());
|
returnVal.setPayload(blob.getPayload());
|
||||||
|
|
|
@ -39,12 +39,14 @@ import org.jclouds.blobstore.LocalStorageStrategy;
|
||||||
import org.jclouds.blobstore.domain.Blob;
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
import org.jclouds.blobstore.domain.BlobBuilder;
|
import org.jclouds.blobstore.domain.BlobBuilder;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
|
import org.jclouds.crypto.Crypto;
|
||||||
import org.jclouds.crypto.CryptoStreams;
|
import org.jclouds.crypto.CryptoStreams;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.filesystem.predicates.validators.FilesystemBlobKeyValidator;
|
import org.jclouds.filesystem.predicates.validators.FilesystemBlobKeyValidator;
|
||||||
import org.jclouds.filesystem.predicates.validators.FilesystemContainerNameValidator;
|
import org.jclouds.filesystem.predicates.validators.FilesystemContainerNameValidator;
|
||||||
import org.jclouds.filesystem.reference.FilesystemConstants;
|
import org.jclouds.filesystem.reference.FilesystemConstants;
|
||||||
import org.jclouds.io.Payload;
|
import org.jclouds.io.Payload;
|
||||||
|
import org.jclouds.io.Payloads;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.annotations.ParamValidators;
|
import org.jclouds.rest.annotations.ParamValidators;
|
||||||
|
|
||||||
|
@ -67,17 +69,20 @@ public class FilesystemStorageStrategyImpl implements LocalStorageStrategy {
|
||||||
protected final String baseDirectory;
|
protected final String baseDirectory;
|
||||||
protected final FilesystemContainerNameValidator filesystemContainerNameValidator;
|
protected final FilesystemContainerNameValidator filesystemContainerNameValidator;
|
||||||
protected final FilesystemBlobKeyValidator filesystemBlobKeyValidator;
|
protected final FilesystemBlobKeyValidator filesystemBlobKeyValidator;
|
||||||
|
private final Crypto crypto;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected FilesystemStorageStrategyImpl(Provider<BlobBuilder> blobBuilders,
|
protected FilesystemStorageStrategyImpl(Provider<BlobBuilder> blobBuilders,
|
||||||
@Named(FilesystemConstants.PROPERTY_BASEDIR) String baseDir,
|
@Named(FilesystemConstants.PROPERTY_BASEDIR) String baseDir,
|
||||||
FilesystemContainerNameValidator filesystemContainerNameValidator,
|
FilesystemContainerNameValidator filesystemContainerNameValidator,
|
||||||
FilesystemBlobKeyValidator filesystemBlobKeyValidator) {
|
FilesystemBlobKeyValidator filesystemBlobKeyValidator,
|
||||||
|
Crypto crypto) {
|
||||||
this.blobBuilders = checkNotNull(blobBuilders, "filesystem storage strategy blobBuilders");
|
this.blobBuilders = checkNotNull(blobBuilders, "filesystem storage strategy blobBuilders");
|
||||||
this.baseDirectory = checkNotNull(baseDir, "filesystem storage strategy base directory");
|
this.baseDirectory = checkNotNull(baseDir, "filesystem storage strategy base directory");
|
||||||
this.filesystemContainerNameValidator = checkNotNull(filesystemContainerNameValidator,
|
this.filesystemContainerNameValidator = checkNotNull(filesystemContainerNameValidator,
|
||||||
"filesystem container name validator");
|
"filesystem container name validator");
|
||||||
this.filesystemBlobKeyValidator = checkNotNull(filesystemBlobKeyValidator, "filesystem blob key validator");
|
this.filesystemBlobKeyValidator = checkNotNull(filesystemBlobKeyValidator, "filesystem blob key validator");
|
||||||
|
this.crypto = crypto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -209,7 +214,7 @@ public class FilesystemStorageStrategyImpl implements LocalStorageStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putBlob(final String containerName, final Blob blob) throws IOException {
|
public String putBlob(final String containerName, final Blob blob) throws IOException {
|
||||||
String blobKey = blob.getMetadata().getName();
|
String blobKey = blob.getMetadata().getName();
|
||||||
Payload payload = blob.getPayload();
|
Payload payload = blob.getPayload();
|
||||||
filesystemContainerNameValidator.validate(containerName);
|
filesystemContainerNameValidator.validate(containerName);
|
||||||
|
@ -224,6 +229,9 @@ public class FilesystemStorageStrategyImpl implements LocalStorageStrategy {
|
||||||
output = new FileOutputStream(outputFile);
|
output = new FileOutputStream(outputFile);
|
||||||
payload.writeTo(output);
|
payload.writeTo(output);
|
||||||
}
|
}
|
||||||
|
Payloads.calculateMD5(payload, crypto.md5());
|
||||||
|
String eTag = CryptoStreams.hex(payload.getContentMetadata().getContentMD5());
|
||||||
|
return eTag;
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
if (outputFile != null) {
|
if (outputFile != null) {
|
||||||
outputFile.delete();
|
outputFile.delete();
|
||||||
|
|
|
@ -86,7 +86,7 @@ public class FilesystemStorageStrategyImplTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}, TestUtils.TARGET_BASE_DIR, new FilesystemContainerNameValidatorImpl(), new FilesystemBlobKeyValidatorImpl());
|
}, TestUtils.TARGET_BASE_DIR, new FilesystemContainerNameValidatorImpl(), new FilesystemBlobKeyValidatorImpl(), new JCECrypto());
|
||||||
TestUtils.cleanDirectoryContent(TestUtils.TARGET_BASE_DIR);
|
TestUtils.cleanDirectoryContent(TestUtils.TARGET_BASE_DIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +408,7 @@ public class FilesystemStorageStrategyImplTest {
|
||||||
assertEquals(fileForPayload.getAbsolutePath(), fullPath + blobKey, "Wrong file path");
|
assertEquals(fileForPayload.getAbsolutePath(), fullPath + blobKey, "Wrong file path");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetFileForBlobKey_AbsolutePath() throws IOException {
|
public void testGetFileForBlobKey_AbsolutePath() throws Exception {
|
||||||
String absoluteBasePath = (new File(getAbsoluteDirectory(), "basedir")).getAbsolutePath() + FS;
|
String absoluteBasePath = (new File(getAbsoluteDirectory(), "basedir")).getAbsolutePath() + FS;
|
||||||
String absoluteContainerPath = absoluteBasePath + CONTAINER_NAME + FS;
|
String absoluteContainerPath = absoluteBasePath + CONTAINER_NAME + FS;
|
||||||
|
|
||||||
|
@ -423,7 +423,7 @@ public class FilesystemStorageStrategyImplTest {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, absoluteBasePath, new FilesystemContainerNameValidatorImpl(), new FilesystemBlobKeyValidatorImpl());
|
}, absoluteBasePath, new FilesystemContainerNameValidatorImpl(), new FilesystemBlobKeyValidatorImpl(), new JCECrypto());
|
||||||
TestUtils.cleanDirectoryContent(absoluteContainerPath);
|
TestUtils.cleanDirectoryContent(absoluteContainerPath);
|
||||||
|
|
||||||
String blobKey;
|
String blobKey;
|
||||||
|
|
|
@ -117,9 +117,10 @@ public interface LocalStorageStrategy {
|
||||||
* Write a {@link Blob} into a file
|
* Write a {@link Blob} into a file
|
||||||
* @param container
|
* @param container
|
||||||
* @param blob
|
* @param blob
|
||||||
|
* @return etag of blob
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
void putBlob(String containerName, Blob blob) throws IOException;
|
String putBlob(String containerName, Blob blob) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param containerName name of container
|
* @param containerName name of container
|
||||||
|
|
|
@ -34,7 +34,6 @@ import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
@ -43,9 +42,6 @@ import java.util.concurrent.ExecutorService;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Provider;
|
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
|
||||||
import javax.ws.rs.core.UriBuilder;
|
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.blobstore.domain.Blob;
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
@ -67,9 +63,6 @@ import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy;
|
||||||
import org.jclouds.blobstore.util.BlobStoreUtils;
|
import org.jclouds.blobstore.util.BlobStoreUtils;
|
||||||
import org.jclouds.blobstore.util.BlobUtils;
|
import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.collect.Memoized;
|
import org.jclouds.collect.Memoized;
|
||||||
import org.jclouds.crypto.Crypto;
|
|
||||||
import org.jclouds.crypto.CryptoStreams;
|
|
||||||
import org.jclouds.date.DateService;
|
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.http.HttpCommand;
|
import org.jclouds.http.HttpCommand;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
|
@ -78,11 +71,7 @@ import org.jclouds.http.HttpResponseException;
|
||||||
import org.jclouds.http.HttpUtils;
|
import org.jclouds.http.HttpUtils;
|
||||||
import org.jclouds.io.ContentMetadata;
|
import org.jclouds.io.ContentMetadata;
|
||||||
import org.jclouds.io.ContentMetadataCodec;
|
import org.jclouds.io.ContentMetadataCodec;
|
||||||
import org.jclouds.io.MutableContentMetadata;
|
|
||||||
import org.jclouds.io.Payload;
|
import org.jclouds.io.Payload;
|
||||||
import org.jclouds.io.Payloads;
|
|
||||||
import org.jclouds.io.payloads.ByteArrayPayload;
|
|
||||||
import org.jclouds.io.payloads.DelegatingPayload;
|
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
@ -90,7 +79,6 @@ import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Multimaps;
|
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
@ -105,13 +93,10 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
@Resource
|
@Resource
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
protected final DateService dateService;
|
|
||||||
protected final Crypto crypto;
|
|
||||||
protected final ContentMetadataCodec contentMetadataCodec;
|
protected final ContentMetadataCodec contentMetadataCodec;
|
||||||
protected final IfDirectoryReturnNameStrategy ifDirectoryReturnName;
|
protected final IfDirectoryReturnNameStrategy ifDirectoryReturnName;
|
||||||
protected final Factory blobFactory;
|
protected final Factory blobFactory;
|
||||||
protected final LocalStorageStrategy storageStrategy;
|
protected final LocalStorageStrategy storageStrategy;
|
||||||
protected final Provider<UriBuilder> uriBuilders;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected TransientAsyncBlobStore(BlobStoreContext context,
|
protected TransientAsyncBlobStore(BlobStoreContext context,
|
||||||
|
@ -119,19 +104,14 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
@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,
|
||||||
DateService dateService, Crypto crypto,
|
|
||||||
ContentMetadataCodec contentMetadataCodec,
|
ContentMetadataCodec contentMetadataCodec,
|
||||||
IfDirectoryReturnNameStrategy ifDirectoryReturnName,
|
IfDirectoryReturnNameStrategy ifDirectoryReturnName,
|
||||||
Factory blobFactory, LocalStorageStrategy storageStrategy,
|
Factory blobFactory, LocalStorageStrategy storageStrategy) {
|
||||||
Provider<UriBuilder> uriBuilders) {
|
|
||||||
super(context, blobUtils, service, defaultLocation, locations);
|
super(context, blobUtils, service, defaultLocation, locations);
|
||||||
this.blobFactory = blobFactory;
|
this.blobFactory = blobFactory;
|
||||||
this.dateService = dateService;
|
|
||||||
this.crypto = crypto;
|
|
||||||
this.contentMetadataCodec = contentMetadataCodec;
|
this.contentMetadataCodec = contentMetadataCodec;
|
||||||
this.ifDirectoryReturnName = ifDirectoryReturnName;
|
this.ifDirectoryReturnName = ifDirectoryReturnName;
|
||||||
this.storageStrategy = storageStrategy;
|
this.storageStrategy = storageStrategy;
|
||||||
this.uriBuilders = uriBuilders;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -439,58 +419,13 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
return Futures.immediateFailedFuture(new IllegalStateException("containerName not found: " + containerName));
|
return Futures.immediateFailedFuture(new IllegalStateException("containerName not found: " + containerName));
|
||||||
}
|
}
|
||||||
|
|
||||||
blob = createUpdatedCopyOfBlobInContainer(containerName, blob);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
storageStrategy.putBlob(containerName, blob);
|
return immediateFuture(storageStrategy.putBlob(containerName, blob));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.error(e, "An error occurred storing the new blob with name [%s] to container [%s].", blobKey,
|
logger.error(e, "An error occurred storing the new blob with name [%s] to container [%s].", blobKey,
|
||||||
containerName);
|
containerName);
|
||||||
Throwables.propagate(e);
|
throw Throwables.propagate(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
String eTag = getEtag(blob);
|
|
||||||
return immediateFuture(eTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Blob createUpdatedCopyOfBlobInContainer(String containerName, Blob in) {
|
|
||||||
checkNotNull(in, "blob");
|
|
||||||
checkNotNull(in.getPayload(), "blob.payload");
|
|
||||||
ByteArrayPayload payload = (in.getPayload() instanceof ByteArrayPayload) ? ByteArrayPayload.class.cast(in
|
|
||||||
.getPayload()) : null;
|
|
||||||
if (payload == null)
|
|
||||||
payload = (in.getPayload() instanceof DelegatingPayload) ? (DelegatingPayload.class.cast(in.getPayload())
|
|
||||||
.getDelegate() instanceof ByteArrayPayload) ? ByteArrayPayload.class.cast(DelegatingPayload.class
|
|
||||||
.cast(in.getPayload()).getDelegate()) : null : null;
|
|
||||||
try {
|
|
||||||
if (payload == null || !(payload instanceof ByteArrayPayload)) {
|
|
||||||
MutableContentMetadata oldMd = in.getPayload().getContentMetadata();
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
||||||
in.getPayload().writeTo(out);
|
|
||||||
payload = (ByteArrayPayload) Payloads.calculateMD5(Payloads.newPayload(out.toByteArray()));
|
|
||||||
HttpUtils.copy(oldMd, payload.getContentMetadata());
|
|
||||||
} else {
|
|
||||||
if (payload.getContentMetadata().getContentMD5() == null)
|
|
||||||
Payloads.calculateMD5(in, crypto.md5());
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
Throwables.propagate(e);
|
|
||||||
}
|
|
||||||
Blob blob = blobFactory.create(BlobStoreUtils.copy(in.getMetadata()));
|
|
||||||
blob.setPayload(payload);
|
|
||||||
blob.getMetadata().setContainer(containerName);
|
|
||||||
blob.getMetadata().setUri(
|
|
||||||
uriBuilders.get().scheme("mem").host(containerName).path(in.getMetadata().getName()).build());
|
|
||||||
blob.getMetadata().setLastModified(new Date());
|
|
||||||
String eTag = CryptoStreams.hex(payload.getContentMetadata().getContentMD5());
|
|
||||||
blob.getMetadata().setETag(eTag);
|
|
||||||
// Set HTTP headers to match metadata
|
|
||||||
blob.getAllHeaders().replaceValues(HttpHeaders.LAST_MODIFIED,
|
|
||||||
Collections.singleton(dateService.rfc822DateFormat(blob.getMetadata().getLastModified())));
|
|
||||||
blob.getAllHeaders().replaceValues(HttpHeaders.ETAG, Collections.singleton(eTag));
|
|
||||||
copyPayloadHeadersToBlob(payload, blob);
|
|
||||||
blob.getAllHeaders().putAll(Multimaps.forMap(blob.getMetadata().getUserMetadata()));
|
|
||||||
return blob;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void copyPayloadHeadersToBlob(Payload payload, Blob blob) {
|
private void copyPayloadHeadersToBlob(Payload payload, Blob blob) {
|
||||||
|
@ -613,24 +548,6 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the object MD5 and returns it as eTag
|
|
||||||
*
|
|
||||||
* @param object
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private String getEtag(Blob object) {
|
|
||||||
try {
|
|
||||||
Payloads.calculateMD5(object, crypto.md5());
|
|
||||||
} catch (IOException ex) {
|
|
||||||
logger.error(ex, "An error occurred calculating MD5 for object with name %s.", object.getMetadata().getName());
|
|
||||||
Throwables.propagate(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
String eTag = CryptoStreams.hex(object.getPayload().getContentMetadata().getContentMD5());
|
|
||||||
return eTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Blob copyBlob(Blob blob) {
|
private Blob copyBlob(Blob blob) {
|
||||||
Blob returnVal = blobFactory.create(BlobStoreUtils.copy(blob.getMetadata()));
|
Blob returnVal = blobFactory.create(BlobStoreUtils.copy(blob.getMetadata()));
|
||||||
returnVal.setPayload(blob.getPayload());
|
returnVal.setPayload(blob.getPayload());
|
||||||
|
|
|
@ -18,26 +18,63 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.blobstore;
|
package org.jclouds.blobstore;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import javax.inject.Provider;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
import javax.ws.rs.core.UriBuilder;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.collect.Multimaps;
|
||||||
|
|
||||||
import org.jclouds.blobstore.domain.Blob;
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.blobstore.domain.Blob.Factory;
|
||||||
|
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
|
import org.jclouds.blobstore.util.BlobStoreUtils;
|
||||||
|
import org.jclouds.crypto.Crypto;
|
||||||
|
import org.jclouds.crypto.CryptoStreams;
|
||||||
|
import org.jclouds.date.DateService;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.http.HttpUtils;
|
||||||
|
import org.jclouds.io.ContentMetadataCodec;
|
||||||
|
import org.jclouds.io.MutableContentMetadata;
|
||||||
|
import org.jclouds.io.Payload;
|
||||||
|
import org.jclouds.io.Payloads;
|
||||||
|
import org.jclouds.io.payloads.ByteArrayPayload;
|
||||||
|
import org.jclouds.io.payloads.DelegatingPayload;
|
||||||
|
|
||||||
public class TransientStorageStrategy implements LocalStorageStrategy {
|
public class TransientStorageStrategy implements LocalStorageStrategy {
|
||||||
private final ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs = new ConcurrentHashMap<String, ConcurrentMap<String, Blob>>();
|
private final ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs = new ConcurrentHashMap<String, ConcurrentMap<String, Blob>>();
|
||||||
private final ConcurrentMap<String, Location> containerToLocation = new ConcurrentHashMap<String, Location>();
|
private final ConcurrentMap<String, Location> containerToLocation = new ConcurrentHashMap<String, Location>();
|
||||||
private final Supplier<Location> defaultLocation;
|
private final Supplier<Location> defaultLocation;
|
||||||
|
private final DateService dateService;
|
||||||
|
private final Factory blobFactory;
|
||||||
|
private final Crypto crypto;
|
||||||
|
private final ContentMetadataCodec contentMetadataCodec;
|
||||||
|
private final Provider<UriBuilder> uriBuilders;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
TransientStorageStrategy(final Supplier<Location> defaultLocation) {
|
TransientStorageStrategy(final Supplier<Location> defaultLocation,
|
||||||
|
DateService dateService, Factory blobFactory, Crypto crypto,
|
||||||
|
ContentMetadataCodec contentMetadataCodec,
|
||||||
|
Provider<UriBuilder> uriBuilders) {
|
||||||
this.defaultLocation = defaultLocation;
|
this.defaultLocation = defaultLocation;
|
||||||
|
this.dateService = dateService;
|
||||||
|
this.blobFactory = blobFactory;
|
||||||
|
this.crypto = crypto;
|
||||||
|
this.contentMetadataCodec = contentMetadataCodec;
|
||||||
|
this.uriBuilders = uriBuilders;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterable<String> getAllContainerNames() {
|
public Iterable<String> getAllContainerNames() {
|
||||||
|
@ -82,9 +119,13 @@ public class TransientStorageStrategy implements LocalStorageStrategy {
|
||||||
return map == null ? null : map.get(blobName);
|
return map == null ? null : map.get(blobName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putBlob(final String containerName, final Blob blob) {
|
public String putBlob(final String containerName, final Blob blob) throws IOException {
|
||||||
|
Blob newBlob = createUpdatedCopyOfBlobInContainer(containerName, blob);
|
||||||
Map<String, Blob> map = containerToBlobs.get(containerName);
|
Map<String, Blob> map = containerToBlobs.get(containerName);
|
||||||
map.put(blob.getMetadata().getName(), blob);
|
map.put(newBlob.getMetadata().getName(), newBlob);
|
||||||
|
Payloads.calculateMD5(newBlob, crypto.md5());
|
||||||
|
String eTag = CryptoStreams.hex(newBlob.getPayload().getContentMetadata().getContentMD5());
|
||||||
|
return eTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeBlob(final String containerName, final String blobName) {
|
public void removeBlob(final String containerName, final String blobName) {
|
||||||
|
@ -101,4 +142,48 @@ public class TransientStorageStrategy implements LocalStorageStrategy {
|
||||||
public Location getLocation(final String containerName) {
|
public Location getLocation(final String containerName) {
|
||||||
return containerToLocation.get(containerName);
|
return containerToLocation.get(containerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Blob createUpdatedCopyOfBlobInContainer(String containerName, Blob in) {
|
||||||
|
checkNotNull(in, "blob");
|
||||||
|
checkNotNull(in.getPayload(), "blob.payload");
|
||||||
|
ByteArrayPayload payload = (in.getPayload() instanceof ByteArrayPayload) ? ByteArrayPayload.class.cast(in
|
||||||
|
.getPayload()) : null;
|
||||||
|
if (payload == null)
|
||||||
|
payload = (in.getPayload() instanceof DelegatingPayload) ? (DelegatingPayload.class.cast(in.getPayload())
|
||||||
|
.getDelegate() instanceof ByteArrayPayload) ? ByteArrayPayload.class.cast(DelegatingPayload.class
|
||||||
|
.cast(in.getPayload()).getDelegate()) : null : null;
|
||||||
|
try {
|
||||||
|
if (payload == null || !(payload instanceof ByteArrayPayload)) {
|
||||||
|
MutableContentMetadata oldMd = in.getPayload().getContentMetadata();
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
in.getPayload().writeTo(out);
|
||||||
|
payload = (ByteArrayPayload) Payloads.calculateMD5(Payloads.newPayload(out.toByteArray()));
|
||||||
|
HttpUtils.copy(oldMd, payload.getContentMetadata());
|
||||||
|
} else {
|
||||||
|
if (payload.getContentMetadata().getContentMD5() == null)
|
||||||
|
Payloads.calculateMD5(in, crypto.md5());
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
}
|
||||||
|
Blob blob = blobFactory.create(BlobStoreUtils.copy(in.getMetadata()));
|
||||||
|
blob.setPayload(payload);
|
||||||
|
blob.getMetadata().setContainer(containerName);
|
||||||
|
blob.getMetadata().setUri(
|
||||||
|
uriBuilders.get().scheme("mem").host(containerName).path(in.getMetadata().getName()).build());
|
||||||
|
blob.getMetadata().setLastModified(new Date());
|
||||||
|
String eTag = CryptoStreams.hex(payload.getContentMetadata().getContentMD5());
|
||||||
|
blob.getMetadata().setETag(eTag);
|
||||||
|
// Set HTTP headers to match metadata
|
||||||
|
blob.getAllHeaders().replaceValues(HttpHeaders.LAST_MODIFIED,
|
||||||
|
Collections.singleton(dateService.rfc822DateFormat(blob.getMetadata().getLastModified())));
|
||||||
|
blob.getAllHeaders().replaceValues(HttpHeaders.ETAG, Collections.singleton(eTag));
|
||||||
|
copyPayloadHeadersToBlob(payload, blob);
|
||||||
|
blob.getAllHeaders().putAll(Multimaps.forMap(blob.getMetadata().getUserMetadata()));
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copyPayloadHeadersToBlob(Payload payload, Blob blob) {
|
||||||
|
blob.getAllHeaders().putAll(contentMetadataCodec.toHeaders(payload.getContentMetadata()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue