Issue 353: refactored payload/blob so that contentMetadata is a type.

This commit is contained in:
Adrian Cole 2010-09-19 02:15:03 -07:00
parent 546630ba52
commit 3639af0f12
151 changed files with 1742 additions and 3196 deletions

View File

@ -22,7 +22,10 @@ package org.jclouds.atmosonline.saas.blobstore.functions;
import javax.inject.Singleton;
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
import org.jclouds.atmosonline.saas.domain.internal.DelegatingMutableContentMetadata;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.http.HttpUtils;
import com.google.common.base.Function;
@ -32,13 +35,9 @@ import com.google.common.base.Function;
@Singleton
public class BlobToContentMetadata implements Function<BlobMetadata, MutableContentMetadata> {
public MutableContentMetadata apply(BlobMetadata base) {
MutableContentMetadata to = new MutableContentMetadata();
to.setContentType(base.getContentType());
to.setContentMD5(base.getContentMD5());
to.setName(base.getName());
if (base.getSize() != null)
to.setContentLength(base.getSize());
return to;
MutableBlobMetadataImpl to = new MutableBlobMetadataImpl();
HttpUtils.copy(base.getContentMetadata(), to.getContentMetadata());
return new DelegatingMutableContentMetadata(base.getName(), to.getContentMetadata());
}
}

View File

@ -33,9 +33,9 @@ import com.google.common.base.Function;
@Singleton
public class BlobToSystemMetadata implements Function<BlobMetadata, SystemMetadata> {
public SystemMetadata apply(BlobMetadata base) {
return new SystemMetadata(base.getContentMD5(), null, base.getLastModified(), null, null,
null, 1, null, base.getName(), null, (base.getSize() != null) ? base.getSize() : 0,
FileType.REGULAR, "root");
return new SystemMetadata(base.getContentMetadata().getContentMD5(), null, base.getLastModified(), null, null,
null, 1, null, base.getName(), null, (base.getContentMetadata().getContentLength() != null) ? base
.getContentMetadata().getContentLength() : 0, FileType.REGULAR, "root");
}
}

View File

@ -32,6 +32,7 @@ import org.jclouds.blobstore.domain.internal.BlobMetadataImpl;
import org.jclouds.blobstore.domain.internal.PageSetImpl;
import org.jclouds.blobstore.domain.internal.StorageMetadataImpl;
import org.jclouds.domain.Location;
import org.jclouds.io.payloads.BaseMutableContentMetadata;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
@ -59,11 +60,11 @@ public class DirectoryEntryListToResourceMetadataList implements
public StorageMetadata apply(DirectoryEntry from) {
StorageType type = from.getType() == FileType.DIRECTORY ? StorageType.FOLDER : StorageType.BLOB;
if (type == StorageType.FOLDER)
return new StorageMetadataImpl(type, from.getObjectID(), from.getObjectName(), defaultLocation.get(),
null, null, null, null, Maps.<String, String> newHashMap());
return new StorageMetadataImpl(type, from.getObjectID(), from.getObjectName(), defaultLocation
.get(), null, null, null, Maps.<String, String> newHashMap());
else
return new BlobMetadataImpl(from.getObjectID(), from.getObjectName(), defaultLocation.get(), null,
null, null, null, Maps.<String, String> newHashMap(), null, null, null, null, null);
return new BlobMetadataImpl(from.getObjectID(), from.getObjectName(), defaultLocation.get(),
null, null, null, Maps.<String, String> newHashMap(), new BaseMutableContentMetadata());
}
}), from.getToken());

View File

@ -27,6 +27,7 @@ import javax.inject.Singleton;
import org.jclouds.atmosonline.saas.domain.AtmosObject;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.Blob.Factory;
import org.jclouds.http.HttpUtils;
import com.google.common.base.Function;
@ -49,9 +50,7 @@ public class ObjectToBlob implements Function<AtmosObject, Blob> {
return null;
Blob blob = blobFactory.create(object2BlobMd.apply(from));
blob.setPayload(checkNotNull(from.getPayload(), "payload: " + from));
if (from.getContentMetadata().getContentLength() != null)
blob.getMetadata().setSize(from.getContentMetadata().getContentLength());
blob.getMetadata().setContentMD5(from.getSystemMetadata().getContentMD5());
HttpUtils.copy(from.getContentMetadata(), blob.getPayload().getContentMetadata());
blob.setAllHeaders(from.getAllHeaders());
return blob;
}

View File

@ -32,6 +32,7 @@ import org.jclouds.atmosonline.saas.functions.AtmosObjectName;
import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.http.HttpUtils;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
@ -58,11 +59,8 @@ public class ObjectToBlobMetadata implements Function<AtmosObject, MutableBlobMe
MutableBlobMetadata to = new MutableBlobMetadataImpl();
to.setId(from.getSystemMetadata().getObjectID());
to.setLastModified(from.getSystemMetadata().getLastUserDataModification());
to.setContentMD5(from.getSystemMetadata().getContentMD5());
if (from.getContentMetadata().getContentType() != null)
to.setContentType(from.getContentMetadata().getContentType());
HttpUtils.copy(from.getContentMetadata(), to.getContentMetadata());
to.setName(objectName.apply(from));
to.setSize(from.getSystemMetadata().getSize());
if (from.getSystemMetadata().getType() == FileType.DIRECTORY) {
to.setType(StorageType.FOLDER);
} else {

View File

@ -19,83 +19,20 @@
package org.jclouds.atmosonline.saas.domain;
import javax.ws.rs.core.MediaType;
import org.jclouds.atmosonline.saas.domain.internal.DelegatingMutableContentMetadata;
import com.google.inject.ImplementedBy;
/**
* metadata of the object
*
* @author Adrian Cole
*/
public class MutableContentMetadata {
@ImplementedBy(DelegatingMutableContentMetadata.class)
public interface MutableContentMetadata extends org.jclouds.io.MutableContentMetadata {
private String name;
private Long contentLength;
private String contentType = MediaType.APPLICATION_OCTET_STREAM;
private byte[] contentMD5;
public String getName();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 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 #getInput()}
* @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
* @see GetObjectOptions
*/
public Long getContentLength() {
return contentLength;
}
/**
* @see #getContentLength
*/
public void setContentLength(Long contentLength) {
this.contentLength = contentLength;
}
/**
*
* 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 contentType;
}
/**
* @see #getContentType
*/
public void setContentType(String contentType) {
this.contentType = contentType;
}
/**
* The 128-bit MD5 digest of the message (without the headers) according to RFC 1864. This header
* can be used as a message integrity check to verify that the data is the same data that was
* originally sent. Although it is optional, we recommend using the Content-MD5 mechanism as an
* end-to-end integrity check.
*
*/
public byte[] getContentMD5() {
return contentMD5;
}
/**
* @see #getContentMD5
*/
public void setContentMD5(byte[] contentMD5) {
this.contentMD5 = contentMD5;
}
public void setName(String name);
}

View File

@ -29,8 +29,6 @@ import org.jclouds.atmosonline.saas.domain.SystemMetadata;
import org.jclouds.atmosonline.saas.domain.UserMetadata;
import org.jclouds.http.internal.PayloadEnclosingImpl;
import org.jclouds.io.Payload;
import org.jclouds.io.PayloadEnclosing;
import org.jclouds.io.payloads.DelegatingPayload;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
@ -40,8 +38,7 @@ import com.google.common.collect.Multimap;
*
* @author Adrian Cole
*/
public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject,
Comparable<AtmosObject> {
public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject, Comparable<AtmosObject> {
private final UserMetadata userMetadata;
private final SystemMetadata systemMetadata;
@ -53,15 +50,13 @@ public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject
return userMetadata;
}
private final MutableContentMetadata _contentMetadata;
private final SetPayloadPropertiesMutableContentMetadata contentMetadata;
private MutableContentMetadata contentMetadata;
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
public AtmosObjectImpl(MutableContentMetadata contentMetadata, SystemMetadata systemMetadata,
UserMetadata userMetadata) {
super();
this.contentMetadata = linkMetadataToThis(contentMetadata);
this._contentMetadata = this.contentMetadata.getDelegate();
this.contentMetadata = contentMetadata;
this.systemMetadata = systemMetadata;
this.userMetadata = userMetadata;
}
@ -102,15 +97,16 @@ public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject
public int compareTo(AtmosObject o) {
if (getContentMetadata().getName() == null)
return -1;
return (this == o) ? 0 : getContentMetadata().getName().compareTo(
o.getContentMetadata().getName());
return (this == o) ? 0 : getContentMetadata().getName().compareTo(o.getContentMetadata().getName());
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((_contentMetadata == null) ? 0 : _contentMetadata.hashCode());
result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.hashCode());
result = prime * result + ((systemMetadata == null) ? 0 : systemMetadata.hashCode());
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode());
return result;
}
@ -123,85 +119,32 @@ public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject
if (getClass() != obj.getClass())
return false;
AtmosObjectImpl other = (AtmosObjectImpl) obj;
if (_contentMetadata == null) {
if (other._contentMetadata != null)
if (contentMetadata == null) {
if (other.contentMetadata != null)
return false;
} else if (!_contentMetadata.equals(other._contentMetadata))
} else if (!contentMetadata.equals(other.contentMetadata))
return false;
if (systemMetadata == null) {
if (other.systemMetadata != null)
return false;
} else if (!systemMetadata.equals(other.systemMetadata))
return false;
if (userMetadata == null) {
if (other.userMetadata != null)
return false;
} else if (!userMetadata.equals(other.userMetadata))
return false;
return true;
}
@Override
public String toString() {
return "[contentMetadata=" + _contentMetadata + "]";
return "[contentMetadata=" + contentMetadata + "]";
}
@Override
public void setPayload(Payload data) {
linkPayloadToMetadata(data);
}
/**
* link the new payload to the contentMetadata object so that when content-related
* contentMetadata is updated on the payload, it is also copied the contentMetadata object.
*/
void linkPayloadToMetadata(Payload data) {
if (data instanceof DelegatingPayload)
super.setPayload(new SetMetadataPropertiesPayload(DelegatingPayload.class.cast(data)
.getDelegate(), _contentMetadata));
else
super.setPayload(new SetMetadataPropertiesPayload(data, _contentMetadata));
}
static class SetMetadataPropertiesPayload extends DelegatingPayload {
private transient final MutableContentMetadata contentMetadata;
public SetMetadataPropertiesPayload(Payload delegate, MutableContentMetadata contentMetadata) {
super(delegate);
this.contentMetadata = contentMetadata;
setContentType(contentMetadata.getContentType());
}
@Override
public void setContentType(String md5) {
super.setContentType(md5);
contentMetadata.setContentType(md5);
}
}
/**
* link the contentMetadata object to this so that when content-related contentMetadata is
* updated, it is also copied the currentpayload object.
*/
SetPayloadPropertiesMutableContentMetadata linkMetadataToThis(
MutableContentMetadata contentMetadata) {
return contentMetadata instanceof DelegatingMutableContentMetadata ? new SetPayloadPropertiesMutableContentMetadata(
DelegatingMutableContentMetadata.class.cast(contentMetadata).getDelegate(), this)
: new SetPayloadPropertiesMutableContentMetadata(contentMetadata, this);
}
static class SetPayloadPropertiesMutableContentMetadata extends DelegatingMutableContentMetadata {
/** The serialVersionUID */
private static final long serialVersionUID = -5072270546219814521L;
private transient final PayloadEnclosing object;
public SetPayloadPropertiesMutableContentMetadata(MutableContentMetadata delegate,
PayloadEnclosing object) {
super(delegate);
this.object = object;
}
@Override
public void setContentType(String type) {
super.setContentType(type);
if (canSetPayload())
object.getPayload().setContentType(type);
}
private boolean canSetPayload() {
return object != null && object.getPayload() != null;
}
this.payload = data;
this.contentMetadata = new DelegatingMutableContentMetadata(contentMetadata.getName(), payload.getContentMetadata());
}
}

View File

@ -20,15 +20,22 @@
package org.jclouds.atmosonline.saas.domain.internal;
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
import org.jclouds.io.payloads.BaseMutableContentMetadata;
/**
*
* @author Adrian Cole
*/
public class DelegatingMutableContentMetadata extends MutableContentMetadata {
private final MutableContentMetadata delegate;
public class DelegatingMutableContentMetadata implements MutableContentMetadata {
private String name;
private final org.jclouds.io.MutableContentMetadata delegate;
public DelegatingMutableContentMetadata(MutableContentMetadata delegate) {
public DelegatingMutableContentMetadata() {
this(null, new BaseMutableContentMetadata());
}
public DelegatingMutableContentMetadata(String name, org.jclouds.io.MutableContentMetadata delegate) {
this.name = name;
this.delegate = delegate;
}
@ -49,7 +56,7 @@ public class DelegatingMutableContentMetadata extends MutableContentMetadata {
@Override
public String getName() {
return delegate.getName();
return name;
}
@Override
@ -69,26 +76,78 @@ public class DelegatingMutableContentMetadata extends MutableContentMetadata {
@Override
public void setName(String name) {
delegate.setName(name);
this.name = name;
}
@Override
public boolean equals(Object obj) {
return delegate.equals(obj);
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DelegatingMutableContentMetadata other = (DelegatingMutableContentMetadata) obj;
if (delegate == null) {
if (other.delegate != null)
return false;
} else if (!delegate.equals(other.delegate))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public int hashCode() {
return delegate.hashCode();
final int prime = 31;
int result = 1;
result = prime * result + ((delegate == null) ? 0 : delegate.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public String toString() {
return delegate.toString();
return "[name=" + name + ", delegate=" + delegate + "]";
}
public MutableContentMetadata getDelegate() {
public org.jclouds.io.MutableContentMetadata getDelegate() {
return delegate;
}
@Override
public void setContentDisposition(String contentDisposition) {
delegate.setContentDisposition(contentDisposition);
}
@Override
public void setContentEncoding(String contentEncoding) {
delegate.setContentEncoding(contentEncoding);
}
@Override
public void setContentLanguage(String contentLanguage) {
delegate.setContentLanguage(contentLanguage);
}
@Override
public String getContentDisposition() {
return delegate.getContentDisposition();
}
@Override
public String getContentEncoding() {
return delegate.getContentEncoding();
}
@Override
public String getContentLanguage() {
return delegate.getContentLanguage();
}
}

View File

@ -171,7 +171,7 @@ public class SignRequest implements HttpRequestFilter {
}
private void appendPayloadMetadata(HttpRequest request, StringBuilder buffer) {
buffer.append(utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentType()))
buffer.append(utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata().getContentType()))
.append("\n");
}

View File

@ -32,7 +32,6 @@ import org.jclouds.atmosonline.saas.filters.SignRequest;
import org.jclouds.atmosonline.saas.xml.ErrorHandler;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.crypto.Crypto;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse;
@ -72,8 +71,6 @@ public class AtmosStorageUtils {
String container, Blob blob) {
final String path = container + "/" + blob.getMetadata().getName();
deleteAndEnsureGone(sync, path);
if (blob.getMetadata().getContentMD5() != null)
blob.getMetadata().getUserMetadata().put("content-md5", CryptoStreams.hex(blob.getMetadata().getContentMD5()));
sync.createFile(container, blob2Object.apply(blob));
return path;
}

View File

@ -33,7 +33,6 @@ import org.jclouds.blobstore.domain.Blob.Factory;
import org.jclouds.date.TimeStamp;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.RequiresHttp;
import org.jclouds.io.payloads.PhantomPayload;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.RestContextFactory;
@ -83,8 +82,10 @@ public class AtmosBlobRequestSignerTest extends RestClientTest<AtmosStorageAsync
NoSuchMethodException, IOException {
Blob blob = blobFactory.create(null);
blob.getMetadata().setName("name");
blob.setPayload(new PhantomPayload(2l, new byte[] { 0, 2, 4, 8 }));
blob.getPayload().setContentType("text/plain");
blob.setPayload("");
blob.getPayload().getContentMetadata().setContentLength(2l);
blob.getPayload().getContentMetadata().setContentMD5(new byte[] { 0, 2, 4, 8 });
blob.getPayload().getContentMetadata().setContentType("text/plain");
HttpRequest request = signer.signPutBlob("container", blob);

View File

@ -110,8 +110,8 @@ public class SignRequestTest {
public HttpRequest newRequest() {
HttpRequest request = new HttpRequest("POST", URI.create("http://localhost/rest/objects"));
request.setPayload("");
request.getPayload().setContentLength(4286l);
request.getPayload().setContentType(MediaType.APPLICATION_OCTET_STREAM);
request.getPayload().getContentMetadata().setContentLength(4286l);
request.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_OCTET_STREAM);
request.getHeaders().put(AtmosStorageHeaders.LISTABLE_META, "part4/part7/part8=quick");
request.getHeaders().put(AtmosStorageHeaders.META, "part1=buy");

View File

@ -103,7 +103,7 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
public URI apply(Boolean from) {
if (path != null) {
Blob blob = blobStore.newBlob(path + "/");
blob.getMetadata().setContentType("application/directory");
blob.getMetadata().getContentMetadata().setContentType("application/directory");
blob.setPayload("");
blobStore.putBlob(container, blob);
}

View File

@ -134,7 +134,7 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
return o1.getKey().compareTo(o2.getKey());
}
}));
request.getPayload().setContentType("application/x-www-form-urlencoded");
request.getPayload().getContentMetadata().setContentType("application/x-www-form-urlencoded");
}
@VisibleForTesting

View File

@ -71,9 +71,9 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
AWSError error = null;
String message = null;
if (response.getPayload() != null) {
if (response.getPayload().getContentType() != null
&& (response.getPayload().getContentType().indexOf("xml") != -1 || response.getPayload()
.getContentType().indexOf("unknown") != -1)) {
String contentType = response.getPayload().getContentMetadata().getContentType();
if (contentType != null
&& (contentType.indexOf("xml") != -1 || contentType.indexOf("unknown") != -1)) {
error = utils.parseAWSErrorFromContent(request, response);
if (error != null) {
message = error.getMessage();

View File

@ -52,7 +52,7 @@ public class BindACLToXMLPayload implements Binder {
try {
String stringPayload = generateBuilder(from).asString(outputProperties);
request.setPayload(stringPayload);
request.getPayload().setContentType(MediaType.TEXT_XML);
request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_XML);
} catch (Exception e) {
Throwables.propagateIfPossible(e);
throw new RuntimeException("error transforming acl: " + from, e);

View File

@ -52,7 +52,7 @@ public class BindBucketLoggingToXmlPayload implements Binder {
try {
String stringPayload = generateBuilder(from).asString(outputProperties);
request.setPayload(stringPayload);
request.getPayload().setContentType(MediaType.TEXT_XML);
request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_XML);
} catch (Exception e) {
Throwables.propagateIfPossible(e);
throw new RuntimeException("error transforming bucketLogging: " + from, e);

View File

@ -45,6 +45,6 @@ public class BindPayerToXmlPayload implements Binder {
"<RequestPaymentConfiguration xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Payer>%s</Payer></RequestPaymentConfiguration>",
((Payer) toBind).value());
request.setPayload(text);
request.getPayload().setContentType(MediaType.TEXT_XML);
request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_XML);
}
}

View File

@ -20,7 +20,6 @@
package org.jclouds.aws.s3.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -42,32 +41,21 @@ public class BindS3ObjectToPayload implements Binder {
private final ObjectToBlob object2Blob;
@Inject
public BindS3ObjectToPayload(ObjectToBlob object2Blob,
BindUserMetadataToHeadersWithPrefix blobBinder) {
public BindS3ObjectToPayload(ObjectToBlob object2Blob, BindUserMetadataToHeadersWithPrefix blobBinder) {
this.blobBinder = blobBinder;
this.object2Blob = object2Blob;
}
public void bindToRequest(HttpRequest request, Object payload) {
S3Object s3Object = (S3Object) payload;
checkNotNull(s3Object.getPayload().getContentLength(), "contentLength");
checkArgument(s3Object.getPayload().getContentLength() <= 5l * 1024 * 1024 * 1024,
checkArgument(s3Object.getPayload().getContentMetadata().getContentLength() != null,
"contentLength must be set, streaming not supported");
checkArgument(s3Object.getPayload().getContentMetadata().getContentLength() <= 5l * 1024 * 1024 * 1024,
"maximum size for put object is 5GB");
blobBinder.bindToRequest(request, object2Blob.apply(s3Object));
if (s3Object.getMetadata().getCacheControl() != null) {
request.getHeaders().put(HttpHeaders.CACHE_CONTROL,
s3Object.getMetadata().getCacheControl());
}
if (s3Object.getMetadata().getContentDisposition() != null) {
request.getHeaders().put("Content-Disposition",
s3Object.getMetadata().getContentDisposition());
}
if (s3Object.getMetadata().getContentEncoding() != null) {
request.getHeaders().put(HttpHeaders.CONTENT_ENCODING,
s3Object.getMetadata().getContentEncoding());
request.getHeaders().put(HttpHeaders.CACHE_CONTROL, s3Object.getMetadata().getCacheControl());
}
}

View File

@ -26,6 +26,7 @@ import javax.inject.Singleton;
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
import org.jclouds.aws.s3.domain.internal.MutableObjectMetadataImpl;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.http.HttpUtils;
import com.google.common.base.Function;
@ -38,18 +39,14 @@ public class BlobToObjectMetadata implements Function<BlobMetadata, MutableObjec
if (from == null)
return null;
MutableObjectMetadata to = new MutableObjectMetadataImpl();
to.setContentType(from.getContentType());
HttpUtils.copy(from.getContentMetadata(), to.getContentMetadata());
to.setETag(from.getETag());
to.setContentMD5(from.getContentMD5());
to.setKey(from.getName());
to.setLastModified(from.getLastModified());
if (from.getSize() != null)
to.setSize(from.getSize());
if (from.getUserMetadata() != null) {
for (Entry<String, String> entry : from.getUserMetadata().entrySet())
to.getUserMetadata().put(entry.getKey().toLowerCase(), entry.getValue());
}
return to;
}
}

View File

@ -27,6 +27,7 @@ import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy;
import org.jclouds.http.HttpUtils;
import com.google.common.base.Function;
@ -46,13 +47,9 @@ public class ObjectToBlobMetadata implements Function<ObjectMetadata, MutableBlo
if (from == null)
return null;
MutableBlobMetadata to = new MutableBlobMetadataImpl();
if (from.getContentMD5() != null)
to.setContentMD5(from.getContentMD5());
if (from.getContentType() != null)
to.setContentType(from.getContentType());
HttpUtils.copy(from.getContentMetadata(), to.getContentMetadata());
to.setETag(from.getETag());
to.setName(from.getKey());
to.setSize(from.getSize());
to.setLastModified(from.getLastModified());
to.setUserMetadata(from.getUserMetadata());
String directoryName = ifDirectoryReturnName.execute(to);

View File

@ -23,6 +23,7 @@ import java.util.Date;
import java.util.Map;
import org.jclouds.aws.s3.domain.internal.MutableObjectMetadataImpl;
import org.jclouds.io.MutableContentMetadata;
import com.google.inject.ImplementedBy;
@ -68,47 +69,14 @@ public interface MutableObjectMetadata extends ObjectMetadata {
*/
void setCacheControl(String cacheControl);
/**
* Specifies presentational information for the object.
*
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html?sec19.5.1."/>
*/
void setContentDisposition(String contentDisposition);
MutableContentMetadata getContentMetadata();
/**
* Specifies what content encodings have been applied to the object and thus what decoding
* mechanisms must be applied in order to obtain the media-type referenced by the Content-Type
* header field.
*
* @see <a href= "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.11" />
*/
void setContentEncoding(String encoding);
/**
*
* 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"/>
*/
void setContentType(String type);
/**
* The base64 decoded 128-bit MD5 digest of the message (without the headers) according to RFC
* 1864. This header can be used as a message integrity check to verify that the data is the same
* data that was originally sent. Although it is optional, we recommend using the Content-MD5
* mechanism as an end-to-end integrity check.
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTAuthentication.html"/>
*/
void setContentMD5(byte[] md5);
void setContentMetadata(MutableContentMetadata md);
void setLastModified(Date lastModified);
void setETag(String eTag);
void setSize(Long size);
void setUserMetadata(Map<String, String> userMetadata);
}

View File

@ -22,6 +22,8 @@ package org.jclouds.aws.s3.domain;
import java.util.Date;
import java.util.Map;
import org.jclouds.io.ContentMetadata;
/**
* /** Amazon S3 is designed to store objects. Objects are stored in {@link S3BucketListing buckets}
* and consist of a {@link org.jclouds.aws.s3.domain.S3Object#getData() value}, a
@ -67,47 +69,12 @@ public interface ObjectMetadata extends Comparable<ObjectMetadata> {
*/
String getCacheControl();
/**
* Specifies presentational information for the object.
*
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html?sec19.5.1."/>
*/
String getContentDisposition();
/**
* Specifies what content encodings have been applied to the object and thus what decoding
* mechanisms must be applied in order to obtain the media-type referenced by the Content-Type
* header field.
*
* @see <a href= "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.11" />
*/
String getContentEncoding();
/**
*
* 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"/>
*/
String getContentType();
/**
* The base64 decoded 128-bit MD5 digest of the message (without the headers) according to RFC
* 1864. This header can be used as a message integrity check to verify that the data is the same
* data that was originally sent. Although it is optional, we recommend using the Content-MD5
* mechanism as an end-to-end integrity check.
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTAuthentication.html"/>
*/
byte[] getContentMD5();
Date getLastModified();
String getETag();
Long getSize();
Map<String, String> getUserMetadata();
ContentMetadata getContentMetadata();
}

View File

@ -20,12 +20,13 @@
package org.jclouds.aws.s3.domain.internal;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import org.jclouds.aws.s3.domain.CanonicalUser;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.io.ContentMetadata;
import org.jclouds.io.payloads.BaseImmutableContentMetadata;
import com.google.common.collect.Maps;
@ -42,29 +43,21 @@ public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
private final String key;
private final Date lastModified;
private final String eTag;
private final long size;
private final CanonicalUser owner;
private final StorageClass storageClass;
private final String contentType;
private final byte[] contentMD5;
private final String cacheControl;
private final String contentDisposition;
private final String contentEncoding;
private final Map<String, String> userMetadata;
private final ContentMetadata contentMetadata;
public BucketListObjectMetadata(String key, Date lastModified, String eTag, byte[] md5,
long size, CanonicalUser owner, StorageClass storageClass) {
public BucketListObjectMetadata(String key, Date lastModified, String eTag, byte[] md5, long contentLength,
CanonicalUser owner, StorageClass storageClass) {
this.key = key;
this.lastModified = lastModified;
this.eTag = eTag;
this.size = size;
this.owner = owner;
this.contentMD5 = md5;
this.contentMetadata = new BaseImmutableContentMetadata(null, contentLength, md5, null, null, null);
this.storageClass = storageClass;
this.contentType = null;
this.cacheControl = null;
this.contentDisposition = null;
this.contentEncoding = null;
this.userMetadata = Maps.newHashMap();
}
@ -96,27 +89,6 @@ public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
return cacheControl;
}
/**
*{@inheritDoc}
*/
public String getContentDisposition() {
return contentDisposition;
}
/**
*{@inheritDoc}
*/
public String getContentEncoding() {
return contentEncoding;
}
/**
*{@inheritDoc}
*/
public String getContentType() {
return contentType;
}
/**
*{@inheritDoc}
*/
@ -131,13 +103,6 @@ public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
return eTag;
}
/**
*{@inheritDoc}
*/
public Long getSize() {
return size;
}
/**
*{@inheritDoc}
*/
@ -155,8 +120,9 @@ public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
/**
*{@inheritDoc}
*/
public byte[] getContentMD5() {
return contentMD5;
@Override
public ContentMetadata getContentMetadata() {
return contentMetadata;
}
@Override
@ -164,15 +130,11 @@ public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
final int prime = 31;
int result = 1;
result = prime * result + ((cacheControl == null) ? 0 : cacheControl.hashCode());
result = prime * result + ((contentDisposition == null) ? 0 : contentDisposition.hashCode());
result = prime * result + ((contentEncoding == null) ? 0 : contentEncoding.hashCode());
result = prime * result + Arrays.hashCode(contentMD5);
result = prime * result + ((contentType == null) ? 0 : contentType.hashCode());
result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.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 + ((owner == null) ? 0 : owner.hashCode());
result = prime * result + (int) (size ^ (size >>> 32));
result = prime * result + ((storageClass == null) ? 0 : storageClass.hashCode());
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode());
return result;
@ -192,22 +154,10 @@ public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
return false;
} else if (!cacheControl.equals(other.cacheControl))
return false;
if (contentDisposition == null) {
if (other.contentDisposition != null)
if (contentMetadata == null) {
if (other.contentMetadata != null)
return false;
} else if (!contentDisposition.equals(other.contentDisposition))
return false;
if (contentEncoding == null) {
if (other.contentEncoding != null)
return false;
} else if (!contentEncoding.equals(other.contentEncoding))
return false;
if (!Arrays.equals(contentMD5, other.contentMD5))
return false;
if (contentType == null) {
if (other.contentType != null)
return false;
} else if (!contentType.equals(other.contentType))
} else if (!contentMetadata.equals(other.contentMetadata))
return false;
if (eTag == null) {
if (other.eTag != null)
@ -229,8 +179,6 @@ public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
return false;
} else if (!owner.equals(other.owner))
return false;
if (size != other.size)
return false;
if (storageClass == null) {
if (other.storageClass != null)
return false;

View File

@ -20,12 +20,13 @@
package org.jclouds.aws.s3.domain.internal;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import org.jclouds.aws.s3.domain.CanonicalUser;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.io.ContentMetadata;
import org.jclouds.io.payloads.BaseImmutableContentMetadata;
/**
* Returns the metadata parsable from a bucket listing
@ -40,28 +41,20 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
private final String key;
private final Date lastModified;
private final String eTag;
private final Long size;
private final CanonicalUser owner;
private final StorageClass storageClass;
private final String contentType;
private final byte[] contentMD5;
private final String cacheControl;
private final String contentDisposition;
private final String contentEncoding;
private final Map<String, String> userMetadata;
private final BaseImmutableContentMetadata contentMetadata;
public CopyObjectResult(Date lastModified, String eTag) {
this.key = null;
this.lastModified = lastModified;
this.eTag = eTag;
this.size = null;
this.owner = null;
this.storageClass = StorageClass.STANDARD;
this.contentType = null;
this.contentMD5 = null;
this.contentMetadata = new BaseImmutableContentMetadata(null, null, null, null, null, null);
this.cacheControl = null;
this.contentDisposition = null;
this.contentEncoding = null;
this.userMetadata = null;
}
@ -93,27 +86,6 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
return cacheControl;
}
/**
*{@inheritDoc}
*/
public String getContentDisposition() {
return contentDisposition;
}
/**
*{@inheritDoc}
*/
public String getContentEncoding() {
return contentEncoding;
}
/**
*{@inheritDoc}
*/
public String getContentType() {
return contentType;
}
/**
*{@inheritDoc}
*/
@ -128,13 +100,6 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
return eTag;
}
/**
*{@inheritDoc}
*/
public Long getSize() {
return size;
}
/**
*{@inheritDoc}
*/
@ -152,8 +117,9 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
/**
*{@inheritDoc}
*/
public byte[] getContentMD5() {
return contentMD5;
@Override
public ContentMetadata getContentMetadata() {
return contentMetadata;
}
@Override
@ -161,15 +127,11 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
final int prime = 31;
int result = 1;
result = prime * result + ((cacheControl == null) ? 0 : cacheControl.hashCode());
result = prime * result + ((contentDisposition == null) ? 0 : contentDisposition.hashCode());
result = prime * result + ((contentEncoding == null) ? 0 : contentEncoding.hashCode());
result = prime * result + Arrays.hashCode(contentMD5);
result = prime * result + ((contentType == null) ? 0 : contentType.hashCode());
result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.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 + ((owner == null) ? 0 : owner.hashCode());
result = prime * result + ((size == null) ? 0 : size.hashCode());
result = prime * result + ((storageClass == null) ? 0 : storageClass.hashCode());
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode());
return result;
@ -189,22 +151,10 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
return false;
} else if (!cacheControl.equals(other.cacheControl))
return false;
if (contentDisposition == null) {
if (other.contentDisposition != null)
if (contentMetadata == null) {
if (other.contentMetadata != null)
return false;
} else if (!contentDisposition.equals(other.contentDisposition))
return false;
if (contentEncoding == null) {
if (other.contentEncoding != null)
return false;
} else if (!contentEncoding.equals(other.contentEncoding))
return false;
if (!Arrays.equals(contentMD5, other.contentMD5))
return false;
if (contentType == null) {
if (other.contentType != null)
return false;
} else if (!contentType.equals(other.contentType))
} else if (!contentMetadata.equals(other.contentMetadata))
return false;
if (eTag == null) {
if (other.eTag != null)
@ -226,11 +176,6 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
return false;
} else if (!owner.equals(other.owner))
return false;
if (size == null) {
if (other.size != null)
return false;
} else if (!size.equals(other.size))
return false;
if (storageClass == null) {
if (other.storageClass != null)
return false;

View File

@ -1,184 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.aws.s3.domain.internal;
import java.util.Date;
import java.util.Map;
import org.jclouds.aws.s3.domain.CanonicalUser;
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata;
/**
*
* @author Adrian Cole
*/
public class DelegatingMutableObjectMetadata implements MutableObjectMetadata {
private final MutableObjectMetadata delegate;
public DelegatingMutableObjectMetadata(MutableObjectMetadata delegate) {
this.delegate = delegate;
}
@Override
public int compareTo(ObjectMetadata o) {
return delegate.compareTo(o);
}
@Override
public boolean equals(Object obj) {
return delegate.equals(obj);
}
@Override
public String getCacheControl() {
return delegate.getCacheControl();
}
@Override
public String getContentDisposition() {
return delegate.getContentDisposition();
}
@Override
public String getContentEncoding() {
return delegate.getContentEncoding();
}
@Override
public byte[] getContentMD5() {
return delegate.getContentMD5();
}
@Override
public String getContentType() {
return delegate.getContentType();
}
@Override
public String getETag() {
return delegate.getETag();
}
@Override
public String getKey() {
return delegate.getKey();
}
@Override
public Date getLastModified() {
return delegate.getLastModified();
}
@Override
public CanonicalUser getOwner() {
return delegate.getOwner();
}
@Override
public Long getSize() {
return delegate.getSize();
}
@Override
public StorageClass getStorageClass() {
return delegate.getStorageClass();
}
@Override
public Map<String, String> getUserMetadata() {
return delegate.getUserMetadata();
}
@Override
public int hashCode() {
return delegate.hashCode();
}
@Override
public void setCacheControl(String cacheControl) {
delegate.setCacheControl(cacheControl);
}
@Override
public void setContentDisposition(String contentDisposition) {
delegate.setContentDisposition(contentDisposition);
}
@Override
public void setContentEncoding(String encoding) {
delegate.setContentEncoding(encoding);
}
@Override
public void setContentMD5(byte[] md5) {
delegate.setContentMD5(md5);
}
@Override
public void setContentType(String contentType) {
delegate.setContentType(contentType);
}
@Override
public void setETag(String eTag) {
delegate.setETag(eTag);
}
@Override
public void setKey(String key) {
delegate.setKey(key);
}
@Override
public void setLastModified(Date lastModified) {
delegate.setLastModified(lastModified);
}
@Override
public void setOwner(CanonicalUser owner) {
delegate.setOwner(owner);
}
@Override
public void setSize(Long size) {
delegate.setSize(size);
}
@Override
public void setStorageClass(StorageClass storageClass) {
delegate.setStorageClass(storageClass);
}
@Override
public void setUserMetadata(Map<String, String> userMetadata) {
delegate.setUserMetadata(userMetadata);
}
@Override
public String toString() {
return delegate.toString();
}
public MutableObjectMetadata getDelegate() {
return delegate;
}
}

View File

@ -20,13 +20,15 @@
package org.jclouds.aws.s3.domain.internal;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import org.jclouds.aws.s3.domain.CanonicalUser;
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.http.HttpUtils;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.payloads.BaseMutableContentMetadata;
import com.google.common.collect.Maps;
@ -43,18 +45,21 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
private String key;
private Date lastModified;
private String eTag;
private Long size;
private CanonicalUser owner;
private StorageClass storageClass;
private String contentType;
private byte[] contentMD5;
private String cacheControl;
private String contentDisposition;
private String contentEncoding;
private Map<String, String> userMetadata = Maps.newHashMap();
private MutableContentMetadata contentMetadata;
public MutableObjectMetadataImpl() {
this.storageClass = StorageClass.STANDARD;
this.contentMetadata = new BaseMutableContentMetadata();
}
public MutableObjectMetadataImpl(ObjectMetadata from) {
this.storageClass = StorageClass.STANDARD;
this.contentMetadata = new BaseMutableContentMetadata();
HttpUtils.copy(from.getContentMetadata(), this.contentMetadata);
}
/**
@ -85,27 +90,6 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
return cacheControl;
}
/**
*{@inheritDoc}
*/
public String getContentDisposition() {
return contentDisposition;
}
/**
*{@inheritDoc}
*/
public String getContentEncoding() {
return contentEncoding;
}
/**
*{@inheritDoc}
*/
public String getContentType() {
return contentType;
}
/**
*{@inheritDoc}
*/
@ -120,13 +104,6 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
return eTag;
}
/**
*{@inheritDoc}
*/
public Long getSize() {
return size;
}
/**
*{@inheritDoc}
*/
@ -141,19 +118,6 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
return userMetadata;
}
/**
*{@inheritDoc}
*/
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;
}
}
/**
*{@inheritDoc}
*/
@ -161,38 +125,6 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
this.cacheControl = cacheControl;
}
/**
*{@inheritDoc}
*/
public void setContentDisposition(String contentDisposition) {
this.contentDisposition = contentDisposition;
}
/**
*{@inheritDoc}
*/
public void setContentEncoding(String encoding) {
this.contentEncoding = encoding;
}
/**
*{@inheritDoc}
*/
public void setContentMD5(byte[] md5) {
if (md5 != null) {
byte[] retval = new byte[md5.length];
System.arraycopy(md5, 0, retval, 0, md5.length);
this.contentMD5 = md5;
}
}
/**
*{@inheritDoc}
*/
public void setContentType(String contentType) {
this.contentType = contentType;
}
/**
*{@inheritDoc}
*/
@ -221,13 +153,6 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
this.owner = owner;
}
/**
*{@inheritDoc}
*/
public void setSize(Long size) {
this.size = size;
}
/**
*{@inheritDoc}
*/
@ -242,20 +167,32 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
this.userMetadata = userMetadata;
}
/**
* {@inheritDoc}
*/
@Override
public MutableContentMetadata getContentMetadata() {
return contentMetadata;
}
/**
* {@inheritDoc}
*/
@Override
public void setContentMetadata(MutableContentMetadata contentMetadata) {
this.contentMetadata = contentMetadata;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((cacheControl == null) ? 0 : cacheControl.hashCode());
result = prime * result + ((contentDisposition == null) ? 0 : contentDisposition.hashCode());
result = prime * result + ((contentEncoding == null) ? 0 : contentEncoding.hashCode());
result = prime * result + Arrays.hashCode(contentMD5);
result = prime * result + ((contentType == null) ? 0 : contentType.hashCode());
result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.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 + ((owner == null) ? 0 : owner.hashCode());
result = prime * result + ((size == null) ? 0 : size.hashCode());
result = prime * result + ((storageClass == null) ? 0 : storageClass.hashCode());
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode());
return result;
@ -275,22 +212,10 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
return false;
} else if (!cacheControl.equals(other.cacheControl))
return false;
if (contentDisposition == null) {
if (other.contentDisposition != null)
if (contentMetadata == null) {
if (other.contentMetadata != null)
return false;
} else if (!contentDisposition.equals(other.contentDisposition))
return false;
if (contentEncoding == null) {
if (other.contentEncoding != null)
return false;
} else if (!contentEncoding.equals(other.contentEncoding))
return false;
if (!Arrays.equals(contentMD5, other.contentMD5))
return false;
if (contentType == null) {
if (other.contentType != null)
return false;
} else if (!contentType.equals(other.contentType))
} else if (!contentMetadata.equals(other.contentMetadata))
return false;
if (eTag == null) {
if (other.eTag != null)
@ -312,11 +237,6 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
return false;
} else if (!owner.equals(other.owner))
return false;
if (size == null) {
if (other.size != null)
return false;
} else if (!size.equals(other.size))
return false;
if (storageClass == null) {
if (other.storageClass != null)
return false;
@ -332,12 +252,9 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
@Override
public String toString() {
return "MutableObjectMetadataImpl [key=" + key + ", cacheControl=" + cacheControl
+ ", contentDisposition=" + contentDisposition + ", contentEncoding="
+ contentEncoding + ", contentMD5=" + Arrays.toString(contentMD5) + ", contentType="
+ contentType + ", eTag=" + eTag + ", lastModified=" + lastModified + ", owner="
+ owner + ", size=" + size + ", storageClass=" + storageClass + ", userMetadata="
+ userMetadata + "]";
return "[key=" + key + ", cacheControl=" + cacheControl + ", contentMetadata=" + contentMetadata + ", eTag="
+ eTag + ", lastModified=" + lastModified + ", owner=" + owner + ", storageClass=" + storageClass
+ ", userMetadata=" + userMetadata + "]";
}
}

View File

@ -28,8 +28,6 @@ import org.jclouds.aws.s3.domain.MutableObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.http.internal.PayloadEnclosingImpl;
import org.jclouds.io.Payload;
import org.jclouds.io.PayloadEnclosing;
import org.jclouds.io.payloads.DelegatingPayload;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
@ -59,15 +57,13 @@ public class S3ObjectImpl extends PayloadEnclosingImpl implements S3Object, Comp
return this.accessControlList;
}
private final MutableObjectMetadata _metadata;
private final SetPayloadPropertiesMutableObjectMetadata metadata;
private final MutableObjectMetadata metadata;
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
@Inject
public S3ObjectImpl(MutableObjectMetadata metadata) {
super();
this.metadata = linkMetadataToThis(metadata);
this._metadata = this.metadata.getDelegate();
this.metadata = metadata;
}
/**
@ -108,7 +104,7 @@ public class S3ObjectImpl extends PayloadEnclosingImpl implements S3Object, Comp
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((_metadata == null) ? 0 : _metadata.hashCode());
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
return result;
}
@ -121,85 +117,23 @@ public class S3ObjectImpl extends PayloadEnclosingImpl implements S3Object, Comp
if (getClass() != obj.getClass())
return false;
S3ObjectImpl other = (S3ObjectImpl) obj;
if (_metadata == null) {
if (other._metadata != null)
if (metadata == null) {
if (other.metadata != null)
return false;
} else if (!_metadata.equals(other._metadata))
} else if (!metadata.equals(other.metadata))
return false;
return true;
}
@Override
public String toString() {
return "[metadata=" + _metadata + "]";
return "[metadata=" + metadata + "]";
}
@Override
public void setPayload(Payload data) {
linkPayloadToMetadata(data);
}
/**
* metadata link the new payload to the metadata object so that when content-related metadata is
* updated on the payload, it is also copied the metadata object.
*/
void linkPayloadToMetadata(Payload data) {
if (data instanceof DelegatingPayload)
super.setPayload(new SetMetadataPropertiesPayload(DelegatingPayload.class.cast(data)
.getDelegate(), _metadata));
else
super.setPayload(new SetMetadataPropertiesPayload(data, _metadata));
}
static class SetMetadataPropertiesPayload extends DelegatingPayload {
private transient final MutableObjectMetadata metadata;
public SetMetadataPropertiesPayload(Payload delegate, MutableObjectMetadata metadata) {
super(delegate);
this.metadata = checkNotNull(metadata, "metadata");
setContentType(metadata.getContentType());
}
@Override
public void setContentType(String md5) {
super.setContentType(md5);
metadata.setContentType(md5);
}
}
/**
* link the metadata object to this so that when content-related metadata is updated, it is also
* copied the currentpayload object.
*/
SetPayloadPropertiesMutableObjectMetadata linkMetadataToThis(MutableObjectMetadata metadata) {
return metadata instanceof DelegatingMutableObjectMetadata ? new SetPayloadPropertiesMutableObjectMetadata(
DelegatingMutableObjectMetadata.class.cast(metadata).getDelegate(), this)
: new SetPayloadPropertiesMutableObjectMetadata(metadata, this);
}
static class SetPayloadPropertiesMutableObjectMetadata extends DelegatingMutableObjectMetadata {
/** The serialVersionUID */
private static final long serialVersionUID = -5072270546219814521L;
private transient final PayloadEnclosing object;
public SetPayloadPropertiesMutableObjectMetadata(MutableObjectMetadata delegate,
PayloadEnclosing object) {
super(delegate);
this.object = object;
}
@Override
public void setContentType(String type) {
super.setContentType(type);
if (canSetPayload())
object.getPayload().setContentType(type);
}
private boolean canSetPayload() {
return object != null && object.getPayload() != null;
}
super.setPayload(data);
metadata.setContentMetadata(data.getContentMetadata());
}
}

View File

@ -175,10 +175,12 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
}
void appendPayloadMetadata(HttpRequest request, StringBuilder buffer) {
buffer.append(utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentMD5()))
.append("\n");
buffer.append(utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentType()))
.append("\n");
buffer.append(
utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata()
.getContentMD5())).append("\n");
buffer.append(
utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata()
.getContentType())).append("\n");
}
void appendHttpHeaders(HttpRequest request, StringBuilder toSign) {

View File

@ -74,6 +74,6 @@ public class BindRegionToXmlPayload extends BindToStringPayload {
"<CreateBucketConfiguration><LocationConstraint>%s</LocationConstraint></CreateBucketConfiguration>",
value);
super.bindToRequest(request, payload);
request.getPayload().setContentType(MediaType.TEXT_XML);
request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_XML);
}
}

View File

@ -50,8 +50,6 @@ public class ParseObjectFromHeadersAndHttpContent implements Function<HttpRespon
public S3Object apply(HttpResponse from) {
MutableObjectMetadata metadata = metadataParser.apply(from);
if (metadata.getContentMD5() != null)
from.getPayload().setContentMD5(metadata.getContentMD5());
S3Object object = objectProvider.create(metadata);
object.getAllHeaders().putAll(from.getHeaders());
object.setPayload(from.getPayload());

View File

@ -20,7 +20,6 @@
package org.jclouds.aws.s3.functions;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.jclouds.http.HttpUtils.attemptToParseSizeAndRangeFromHeaders;
import javax.inject.Inject;
import javax.inject.Named;
@ -30,11 +29,9 @@ import org.jclouds.aws.s3.blobstore.functions.BlobToObjectMetadata;
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.functions.ParseSystemAndUserMetadataFromHeaders;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.rest.InvocationContext;
import org.jclouds.util.Utils;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
@ -67,11 +64,7 @@ public class ParseObjectMetadataFromHeaders implements Function<HttpResponse, Mu
BlobMetadata base = blobMetadataParser.apply(from);
MutableObjectMetadata to = blobToObjectMetadata.apply(base);
addETagTo(from, to);
to.setSize(attemptToParseSizeAndRangeFromHeaders(from));
to.setContentMD5(CryptoStreams.hex(Utils.replaceAll(to.getETag(), '"', "")));
to.setCacheControl(from.getFirstHeaderOrNull(HttpHeaders.CACHE_CONTROL));
to.setContentDisposition(from.getFirstHeaderOrNull("Content-Disposition"));
to.setContentEncoding(from.getFirstHeaderOrNull(HttpHeaders.CONTENT_ENCODING));
return to;
}

View File

@ -67,8 +67,8 @@ public class AWSUtils {
if (response.getPayload() == null)
return null;
// Eucalyptus and Walrus occasionally return text/plain
if (response.getPayload().getContentType() != null
&& response.getPayload().getContentType().indexOf("text/plain") != -1)
if (response.getPayload().getContentMetadata().getContentType() != null
&& response.getPayload().getContentMetadata().getContentType().indexOf("text/plain") != -1)
return null;
try {
AWSError error = (AWSError) factory.create(errorHandlerProvider.get()).setContext(request)

View File

@ -90,7 +90,7 @@ public class BlobStoreAndComputeServiceLiveTest {
protected void uploadBlob(String container, String name, String script) {
Blob blob = blobContext.getBlobStore().newBlob(name);
blob.setPayload(script);
blob.getPayload().setContentType("text/plain");
blob.getPayload().getContentMetadata().setContentType("text/plain");
blobContext.getBlobStore().putBlob(container, blob);
}

View File

@ -121,7 +121,7 @@ public class ParseAWSErrorFromXmlContentTest {
HttpRequest request = new HttpRequest(method, uri);
HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Utils
.toInputStream(content)));
response.getPayload().setContentType(contentType);
response.getPayload().getContentMetadata().setContentType(contentType);
expect(command.getRequest()).andReturn(request).atLeastOnce();
command.setException(classEq(expected));

View File

@ -270,7 +270,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest {
protected String addBlobToContainer(String sourceContainer, String key) {
S3Object sourceObject = getApi().newS3Object();
sourceObject.getMetadata().setKey(key);
sourceObject.getMetadata().setContentType("text/xml");
sourceObject.getMetadata().getContentMetadata().setContentType("text/xml");
sourceObject.setPayload(TEST_STRING);
return getApi().putObject(sourceContainer, sourceObject);
}
@ -291,7 +291,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest {
object.getMetadata().setKey(key);
object.setPayload(TEST_STRING);
object.getMetadata().setCacheControl("no-cache");
object.getMetadata().setContentDisposition("attachment; filename=hello.txt");
object.getMetadata().getContentMetadata().setContentDisposition("attachment; filename=hello.txt");
String containerName = getContainerName();
try {
getApi().putObject(containerName, object);
@ -299,7 +299,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest {
S3Object newObject = validateObject(containerName, key);
assertEquals(newObject.getMetadata().getCacheControl(), "no-cache");
assertEquals(newObject.getMetadata().getContentDisposition(),
assertEquals(newObject.getMetadata().getContentMetadata().getContentDisposition(),
"attachment; filename=hello.txt");
} finally {
returnContainer(containerName);
@ -313,13 +313,13 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest {
S3Object object = getApi().newS3Object();
object.getMetadata().setKey(key);
object.setPayload(TEST_STRING);
object.getMetadata().setContentEncoding("x-compress");
object.getMetadata().getContentMetadata().setContentEncoding("x-compress");
String containerName = getContainerName();
try {
getApi().putObject(containerName, object);
S3Object newObject = validateObject(containerName, key);
assertEquals(newObject.getMetadata().getContentEncoding(), "x-compress");
assertEquals(newObject.getMetadata().getContentMetadata().getContentEncoding(), "x-compress");
} finally {
returnContainer(containerName);
}

View File

@ -57,7 +57,7 @@ public class BindBucketLoggingToXmlPayloadTest extends BaseHandlerTest {
.getInstance(BindBucketLoggingToXmlPayload.class);
binder.bindToRequest(request, bucketLogging);
assertEquals(request.getPayload().getContentType(), "text/xml");
assertEquals(request.getPayload().getContentMetadata().getContentType(), "text/xml");
assertEquals(request.getPayload().getRawContent(), expected);
}

View File

@ -30,6 +30,7 @@ import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.binders.BindUserMetadataToHeadersWithPrefix;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.Payload;
import org.testng.annotations.Test;
@ -52,17 +53,19 @@ public class BindS3ObjectToPayloadTest {
Payload payload = createMock(Payload.class);
Blob blob = createMock(Blob.class);
MutableObjectMetadata md = createMock(MutableObjectMetadata.class);
MutableContentMetadata content = createMock(MutableContentMetadata.class);
expect(object.getPayload()).andReturn(payload).atLeastOnce();
expect(payload.getContentLength()).andReturn(5368709120l).atLeastOnce();
expect(payload.getContentMetadata()).andReturn(content).atLeastOnce();
expect(content.getContentLength()).andReturn(5368709120l).atLeastOnce();
expect(object2Blob.apply(object)).andReturn(blob);
mdBinder.bindToRequest(request, blob);
expect(object.getMetadata()).andReturn(md).atLeastOnce();
expect(md.getCacheControl()).andReturn(null).atLeastOnce();
expect(md.getContentDisposition()).andReturn(null).atLeastOnce();
expect(md.getContentEncoding()).andReturn(null).atLeastOnce();
replay(payload);
replay(content);
replay(mdBinder);
replay(object2Blob);
replay(request);
@ -75,6 +78,7 @@ public class BindS3ObjectToPayloadTest {
binder.bindToRequest(request, object);
verify(payload);
verify(content);
verify(mdBinder);
verify(object2Blob);
verify(request);
@ -96,9 +100,11 @@ public class BindS3ObjectToPayloadTest {
Blob blob = createMock(Blob.class);
MutableObjectMetadata md = createMock(MutableObjectMetadata.class);
Multimap<String, String> headers = createMock(Multimap.class);
MutableContentMetadata content = createMock(MutableContentMetadata.class);
expect(object.getPayload()).andReturn(payload).atLeastOnce();
expect(payload.getContentLength()).andReturn(5368709120l).atLeastOnce();
expect(payload.getContentMetadata()).andReturn(content).atLeastOnce();
expect(content.getContentLength()).andReturn(5368709120l).atLeastOnce();
expect(object2Blob.apply(object)).andReturn(blob);
mdBinder.bindToRequest(request, blob);
expect(object.getMetadata()).andReturn(md).atLeastOnce();
@ -106,15 +112,9 @@ public class BindS3ObjectToPayloadTest {
expect(md.getCacheControl()).andReturn("no-cache").atLeastOnce();
expect(headers.put("Cache-Control", "no-cache")).andReturn(true);
expect(md.getContentDisposition()).andReturn("attachment; filename=\"fname.ext\"")
.atLeastOnce();
expect(headers.put("Content-Disposition", "attachment; filename=\"fname.ext\"")).andReturn(true);
expect(md.getContentEncoding()).andReturn("gzip").atLeastOnce();
expect(headers.put("Content-Encoding", "gzip")).andReturn(true);
replay(headers);
replay(payload);
replay(content);
replay(mdBinder);
replay(object2Blob);
replay(request);
@ -127,6 +127,7 @@ public class BindS3ObjectToPayloadTest {
binder.bindToRequest(request, object);
verify(headers);
verify(content);
verify(payload);
verify(mdBinder);
verify(object2Blob);
@ -147,17 +148,20 @@ public class BindS3ObjectToPayloadTest {
Payload payload = createMock(Payload.class);
Blob blob = createMock(Blob.class);
MutableObjectMetadata md = createMock(MutableObjectMetadata.class);
MutableContentMetadata content = createMock(MutableContentMetadata.class);
expect(object.getPayload()).andReturn(payload).atLeastOnce();
expect(payload.getContentLength()).andReturn(5368709121l).atLeastOnce();
expect(payload.getContentMetadata()).andReturn(content).atLeastOnce();
expect(content.getContentLength()).andReturn(5368709121l).atLeastOnce();
expect(object2Blob.apply(object)).andReturn(blob);
mdBinder.bindToRequest(request, blob);
expect(object.getMetadata()).andReturn(md).atLeastOnce();
expect(md.getCacheControl()).andReturn(null).atLeastOnce();
expect(md.getContentDisposition()).andReturn(null).atLeastOnce();
expect(md.getContentEncoding()).andReturn(null).atLeastOnce();
expect(content.getContentDisposition()).andReturn(null).atLeastOnce();
expect(content.getContentEncoding()).andReturn(null).atLeastOnce();
replay(payload);
replay(content);
replay(mdBinder);
replay(object2Blob);
replay(request);
@ -170,6 +174,7 @@ public class BindS3ObjectToPayloadTest {
bindS3ObjectToPayload.bindToRequest(request, object);
verify(payload);
verify(content);
verify(mdBinder);
verify(object2Blob);
verify(request);

View File

@ -81,8 +81,10 @@ public class S3BlobRequestSignerTest extends RestClientTest<S3AsyncClient> {
NoSuchMethodException, IOException {
Blob blob = blobFactory.create(null);
blob.getMetadata().setName("name");
blob.setPayload(new PhantomPayload(2l, new byte[] { 0, 2, 4, 8 }));
blob.getPayload().setContentType("text/plain");
blob.setPayload(new PhantomPayload());
blob.getPayload().getContentMetadata().setContentLength(2l);
blob.getPayload().getContentMetadata().setContentMD5(new byte[] { 0, 2, 4, 8 });
blob.getPayload().getContentMetadata().setContentType("text/plain");
HttpRequest request = signer.signPutBlob("container", blob);

View File

@ -53,11 +53,11 @@ public class ParseObjectMetadataFromHeadersTest {
@Test
void testNormal() throws Exception {
HttpResponse http = new HttpResponse(400, "boa", Payloads.newStringPayload(""));
http.getPayload().setContentLength(1025l);
http.getPayload().getContentMetadata().setContentLength(1025l);
http.getHeaders().put(HttpHeaders.CACHE_CONTROL, "cacheControl");
http.getHeaders().put("Content-Disposition", "contentDisposition");
http.getHeaders().put(HttpHeaders.CONTENT_ENCODING, "encoding");
http.getPayload().getContentMetadata().setContentDisposition("contentDisposition");
http.getPayload().getContentMetadata().setContentEncoding("encoding");
ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders(blobParser(http, "\"abcd\""),
blobToObjectMetadata, "x-amz-meta-");
MutableObjectMetadata response = parser.apply(http);
@ -68,11 +68,10 @@ public class ParseObjectMetadataFromHeadersTest {
void testAmzEtag() throws Exception {
HttpResponse http = new HttpResponse(400, "boa", Payloads.newStringPayload(""));
http.getPayload().setContentLength(1025l);
http.getPayload().getContentMetadata().setContentLength(1025l);
http.getPayload().getContentMetadata().setContentDisposition("contentDisposition");
http.getPayload().getContentMetadata().setContentEncoding("encoding");
http.getHeaders().put(HttpHeaders.CACHE_CONTROL, "cacheControl");
http.getHeaders().put("Content-Disposition", "contentDisposition");
http.getHeaders().put(HttpHeaders.CONTENT_ENCODING, "encoding");
http.getHeaders().put("x-amz-meta-object-eTag", "\"abcd\"");
ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders(blobParser(http, null),
blobToObjectMetadata, "x-amz-meta-");
@ -88,11 +87,14 @@ public class ParseObjectMetadataFromHeadersTest {
private ParseSystemAndUserMetadataFromHeaders blobParser(HttpResponse response, String etag) {
ParseSystemAndUserMetadataFromHeaders parser = createMock(ParseSystemAndUserMetadataFromHeaders.class);
MutableBlobMetadata md = new MutableBlobMetadataImpl();
md.setContentType("type");
md.getContentMetadata().setContentType("type");
md.setETag(etag);
md.setName("key");
md.setLastModified(now);
md.setSize(1025l);
md.getContentMetadata().setContentLength(1025l);
md.getContentMetadata().setContentDisposition("contentDisposition");
md.getContentMetadata().setContentEncoding("encoding");
md.getContentMetadata().setContentMD5(CryptoStreams.hex("abcd"));
md.setUserMetadata(userMetadata);
expect(parser.apply(response)).andReturn(md);
replay(parser);
@ -104,15 +106,15 @@ public class ParseObjectMetadataFromHeadersTest {
blobToObjectMetadata = new BlobToObjectMetadata();
expects = new MutableObjectMetadataImpl();
expects.setCacheControl("cacheControl");
expects.setContentDisposition("contentDisposition");
expects.setContentEncoding("encoding");
expects.setContentMD5(CryptoStreams.hex("abcd"));
expects.setContentType("type");
expects.getContentMetadata().setContentDisposition("contentDisposition");
expects.getContentMetadata().setContentEncoding("encoding");
expects.getContentMetadata().setContentMD5(CryptoStreams.hex("abcd"));
expects.getContentMetadata().setContentType("type");
expects.getContentMetadata().setContentLength(1025l);
expects.setETag("\"abcd\"");
expects.setKey("key");
expects.setLastModified(now);
expects.setOwner(null);
expects.setSize(1025l);
expects.setStorageClass(StorageClass.STANDARD);
expects.setUserMetadata(userMetadata);
}

View File

@ -131,7 +131,7 @@ public class S3ParserTest extends PerformanceTest {
assert object.getLastModified().equals(expected) : String.format("expected %1$s, but got %1$s", expected, object
.getLastModified());
assertEquals(object.getETag(), "\"9d7bb64e8e18ee34eec06dd2cf37b766\"");
assert object.getSize() == 136;
assert object.getContentMetadata().getContentLength() == 136;
CanonicalUser owner = new CanonicalUser("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0");
owner.setDisplayName("ferncam");
assert object.getOwner().equals(owner);

View File

@ -73,7 +73,7 @@ public class AWSUtilsTest {
HttpResponse response(InputStream content) {
HttpResponse response = new HttpResponse(400, "boa", Payloads.newInputStreamPayload(content));
response.getPayload().setContentType("text/xml");
response.getPayload().getContentMetadata().setContentType("text/xml");
response.getHeaders().put("x-amz-request-id", "requestid");
response.getHeaders().put("x-amz-id-2", "requesttoken");
return response;

View File

@ -39,40 +39,27 @@ public class BindAzureBlobToPayload implements Binder {
private final BindUserMetadataToHeadersWithPrefix blobBinder;
@Inject
public BindAzureBlobToPayload(AzureBlobToBlob azureBlob2Blob,
BindUserMetadataToHeadersWithPrefix blobBinder) {
public BindAzureBlobToPayload(AzureBlobToBlob azureBlob2Blob, BindUserMetadataToHeadersWithPrefix blobBinder) {
this.azureBlob2Blob = azureBlob2Blob;
this.blobBinder = blobBinder;
}
public void bindToRequest(HttpRequest request, Object payload) {
AzureBlob blob = (AzureBlob) payload;
checkArgument(blob.getPayload().getContentLength() >= 0, "size must be set");
checkArgument(blob.getPayload().getContentMetadata().getContentLength() >= 0, "size must be set");
request.getHeaders().put("x-ms-blob-type", blob.getProperties().getType().toString());
switch (blob.getProperties().getType()) {
case PAGE_BLOB:
request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, "0");
request.getHeaders().put("x-ms-blob-content-length",
blob.getPayload().getContentLength().toString());
blob.getPayload().getContentMetadata().getContentLength().toString());
break;
case BLOCK_BLOB:
checkArgument(checkNotNull(blob.getPayload().getContentLength(),
"blob.getContentLength()") <= 64l * 1024 * 1024,
"maximum size for put Blob is 64MB");
checkArgument(checkNotNull(blob.getPayload().getContentMetadata().getContentLength(),
"blob.getContentLength()") <= 64l * 1024 * 1024, "maximum size for put Blob is 64MB");
break;
}
blobBinder.bindToRequest(request, azureBlob2Blob.apply(blob));
if (blob.getProperties().getContentLanguage() != null) {
request.getHeaders().put(HttpHeaders.CONTENT_LANGUAGE,
blob.getProperties().getContentLanguage());
}
if (blob.getProperties().getContentEncoding() != null) {
request.getHeaders().put(HttpHeaders.CONTENT_ENCODING,
blob.getProperties().getContentEncoding());
}
}
}

View File

@ -26,6 +26,7 @@ import javax.inject.Singleton;
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
import org.jclouds.azure.storage.blob.domain.internal.MutableBlobPropertiesImpl;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.http.HttpUtils;
import com.google.common.base.Function;
@ -38,13 +39,10 @@ public class BlobMetadataToBlobProperties implements Function<BlobMetadata, Muta
if (from == null)
return null;
MutableBlobProperties to = new MutableBlobPropertiesImpl();
to.setContentType(from.getContentType());
HttpUtils.copy(from.getContentMetadata(), to.getContentMetadata());
to.setETag(from.getETag());
to.setContentMD5(from.getContentMD5());
to.setName(from.getName());
to.setLastModified(from.getLastModified());
if (from.getSize() != null)
to.setContentLength(from.getSize());
if (from.getUserMetadata() != null) {
for (Entry<String, String> entry : from.getUserMetadata().entrySet())
to.getMetadata().put(entry.getKey().toLowerCase(), entry.getValue());

View File

@ -27,6 +27,7 @@ import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy;
import org.jclouds.http.HttpUtils;
import com.google.common.base.Function;
@ -46,15 +47,11 @@ public class BlobPropertiesToBlobMetadata implements Function<BlobProperties, Mu
if (from == null)
return null;
MutableBlobMetadata to = new MutableBlobMetadataImpl();
if (from.getContentMD5() != null)
to.setContentMD5(from.getContentMD5());
if (from.getContentType() != null)
to.setContentType(from.getContentType());
HttpUtils.copy(from.getContentMetadata(), to.getContentMetadata());
to.setUserMetadata(from.getMetadata());
to.setETag(from.getETag());
to.setLastModified(from.getLastModified());
to.setName(from.getName());
to.setSize(from.getContentLength());
String directoryName = ifDirectoryReturnName.execute(to);
if (directoryName != null) {
to.setName(directoryName);

View File

@ -60,7 +60,7 @@ public class FindMD5InBlobProperties implements ContainsValueInListStrategy {
byte[] toSearch = objectMD5.apply(value);
for (BlobMetadata metadata : getAllBlobMetadata.execute(containerName, options)) {
BlobProperties properties = client.getBlobProperties(containerName, metadata.getName());
if (Arrays.equals(toSearch, properties.getContentMD5()))
if (Arrays.equals(toSearch, properties.getContentMetadata().getContentMD5()))
return true;
}
return false;

View File

@ -23,6 +23,8 @@ import java.net.URI;
import java.util.Date;
import java.util.Map;
import org.jclouds.io.ContentMetadata;
/**
*
* @author Adrian Cole
@ -47,31 +49,6 @@ public interface BlobProperties extends Comparable<BlobProperties> {
String getETag();
Long getContentLength();
ContentMetadata getContentMetadata();
/**
* This value present in system metadata requests on blobs which were created specifying the
* Content-MD5 header.
*/
byte[] getContentMD5();
/**
*
* 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"/>
*/
String getContentType();
/**
* Specifies what content encodings have been applied to the object and thus what decoding
* mechanisms must be applied in order to obtain the media-type referenced by the Content-Type
* header field.
*
* @see <a href= "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.11" />
*/
public String getContentEncoding();
public String getContentLanguage();
}

View File

@ -24,6 +24,7 @@ import java.util.Date;
import java.util.Map;
import org.jclouds.azure.storage.blob.domain.internal.MutableBlobPropertiesImpl;
import org.jclouds.io.MutableContentMetadata;
import com.google.inject.ImplementedBy;
@ -54,30 +55,9 @@ public interface MutableBlobProperties extends BlobProperties {
*/
void setETag(String eTag);
/**
* @see ListableContainerProperties#getContentLength
*/
void setContentLength(Long size);
MutableContentMetadata getContentMetadata();
/**
* @see ListableContainerProperties#getContentMD5
*/
void setContentMD5(byte[] md5);
/**
* @see ListableContainerProperties#getContentType
*/
void setContentType(String contentType);
/**
* @see ListableContainerProperties#getContentEncoding
*/
void setContentEncoding(String contentEncoding);
/**
* @see ListableContainerProperties#getContentLanguage
*/
void setContentLanguage(String contentLanguage);
void setContentMetadata(MutableContentMetadata md);
/**
* @see ListableContainerProperties#getMetadata

View File

@ -27,8 +27,6 @@ import org.jclouds.azure.storage.blob.domain.AzureBlob;
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
import org.jclouds.http.internal.PayloadEnclosingImpl;
import org.jclouds.io.Payload;
import org.jclouds.io.PayloadEnclosing;
import org.jclouds.io.payloads.DelegatingPayload;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
@ -40,15 +38,13 @@ import com.google.common.collect.Multimap;
*/
public class AzureBlobImpl extends PayloadEnclosingImpl implements AzureBlob, Comparable<AzureBlob> {
private final MutableBlobProperties _properties;
private final SetPayloadPropertiesMutableBlobProperties properties;
private final MutableBlobProperties properties;
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
@Inject
public AzureBlobImpl(MutableBlobProperties properties) {
super();
this.properties = linkMetadataToThis(properties);
this._properties = this.properties.getDelegate();
this.properties = properties;
}
/**
@ -89,7 +85,7 @@ public class AzureBlobImpl extends PayloadEnclosingImpl implements AzureBlob, Co
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((_properties == null) ? 0 : _properties.hashCode());
result = prime * result + ((properties == null) ? 0 : properties.hashCode());
return result;
}
@ -102,83 +98,23 @@ public class AzureBlobImpl extends PayloadEnclosingImpl implements AzureBlob, Co
if (getClass() != obj.getClass())
return false;
AzureBlobImpl other = (AzureBlobImpl) obj;
if (_properties == null) {
if (other._properties != null)
if (properties == null) {
if (other.properties != null)
return false;
} else if (!_properties.equals(other._properties))
} else if (!properties.equals(other.properties))
return false;
return true;
}
@Override
public String toString() {
return "[properties=" + _properties + "]";
return "[properties=" + properties + "]";
}
@Override
public void setPayload(Payload data) {
linkPayloadToMetadata(data);
super.setPayload(data);
properties.setContentMetadata(data.getContentMetadata());
}
/**
* link the new payload to the properties object so that when content-related properties is
* updated on the payload, it is also copied the properties object.
*/
void linkPayloadToMetadata(Payload data) {
if (data instanceof DelegatingPayload)
super.setPayload(new SetMetadataPropertiesPayload(DelegatingPayload.class.cast(data)
.getDelegate(), _properties));
else
super.setPayload(new SetMetadataPropertiesPayload(data, _properties));
}
static class SetMetadataPropertiesPayload extends DelegatingPayload {
private transient final MutableBlobProperties properties;
public SetMetadataPropertiesPayload(Payload delegate, MutableBlobProperties properties) {
super(delegate);
this.properties = properties;
}
@Override
public void setContentType(String md5) {
super.setContentType(md5);
properties.setContentType(md5);
}
}
/**
* link the properties object to this so that when content-related properties is updated, it is
* also copied the currentpayload object.
*/
SetPayloadPropertiesMutableBlobProperties linkMetadataToThis(MutableBlobProperties properties) {
return properties instanceof DelegatingMutableBlobProperties ? new SetPayloadPropertiesMutableBlobProperties(
DelegatingMutableBlobProperties.class.cast(properties).getDelegate(), this)
: new SetPayloadPropertiesMutableBlobProperties(properties, this);
}
static class SetPayloadPropertiesMutableBlobProperties extends DelegatingMutableBlobProperties {
/** The serialVersionUID */
private static final long serialVersionUID = -5072270546219814521L;
private transient final PayloadEnclosing blob;
public SetPayloadPropertiesMutableBlobProperties(MutableBlobProperties delegate,
PayloadEnclosing blob) {
super(delegate);
this.blob = blob;
}
@Override
public void setContentType(String type) {
super.setContentType(type);
if (canSetPayload())
blob.getPayload().setContentType(type);
}
private boolean canSetPayload() {
return blob != null && blob.getPayload() != null;
}
}
}

View File

@ -23,13 +23,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.net.URI;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.BlobType;
import org.jclouds.azure.storage.blob.domain.LeaseStatus;
import org.jclouds.io.ContentMetadata;
import org.jclouds.io.payloads.BaseImmutableContentMetadata;
import com.google.common.collect.Maps;
import com.google.inject.internal.Nullable;
@ -48,40 +49,24 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
private final URI url;
private final Date lastModified;
private final String eTag;
private final long size;
private final String contentType;
private final byte[] contentMD5;
private final String contentEncoding;
private final String contentLanguage;
private final Map<String, String> metadata = Maps.newLinkedHashMap();
private final LeaseStatus leaseStatus;
private final BaseImmutableContentMetadata contentMetadata;
public BlobPropertiesImpl(BlobType type, String name, URI url, Date lastModified, String eTag,
long size, String contentType, @Nullable byte[] contentMD5,
@Nullable String contentEncoding, @Nullable String contentLanguage,
LeaseStatus leaseStatus, Map<String, String> metadata) {
public BlobPropertiesImpl(BlobType type, String name, URI url, Date lastModified, String eTag, long size,
String contentType, @Nullable byte[] contentMD5, @Nullable String contentMetadata,
@Nullable String contentLanguage, LeaseStatus leaseStatus, Map<String, String> metadata) {
this.type = checkNotNull(type, "type");
this.leaseStatus = checkNotNull(leaseStatus, "leaseStatus");
this.name = checkNotNull(name, "name");
this.url = checkNotNull(url, "url");
this.lastModified = checkNotNull(lastModified, "lastModified");
this.eTag = checkNotNull(eTag, "eTag");
this.size = size;
this.contentType = checkNotNull(contentType, "contentType");
this.contentMD5 = contentMD5;
this.contentEncoding = contentEncoding;
this.contentLanguage = contentLanguage;
this.contentMetadata = new BaseImmutableContentMetadata(contentType, size, contentMD5, null, contentLanguage,
contentMetadata);
this.metadata.putAll(checkNotNull(metadata, "metadata"));
}
/**
*{@inheritDoc}
*/
@Override
public byte[] getContentMD5() {
return contentMD5;
}
/**
*{@inheritDoc}
*/
@ -98,22 +83,6 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
return name;
}
/**
*{@inheritDoc}
*/
@Override
public String getContentEncoding() {
return contentEncoding;
}
/**
*{@inheritDoc}
*/
@Override
public String getContentType() {
return contentType;
}
/**
*{@inheritDoc}
*/
@ -130,14 +99,6 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
return eTag;
}
/**
*{@inheritDoc}
*/
@Override
public Long getContentLength() {
return size;
}
/**
*{@inheritDoc}
*/
@ -154,14 +115,6 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
return metadata;
}
/**
*{@inheritDoc}
*/
@Override
public String getContentLanguage() {
return contentLanguage;
}
/**
*{@inheritDoc}
*/
@ -178,20 +131,24 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
return leaseStatus;
}
/**
*{@inheritDoc}
*/
@Override
public ContentMetadata getContentMetadata() {
return contentMetadata;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((contentEncoding == null) ? 0 : contentEncoding.hashCode());
result = prime * result + ((contentLanguage == null) ? 0 : contentLanguage.hashCode());
result = prime * result + Arrays.hashCode(contentMD5);
result = prime * result + ((contentType == null) ? 0 : contentType.hashCode());
result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.hashCode());
result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
result = prime * result + ((leaseStatus == null) ? 0 : leaseStatus.hashCode());
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + (int) (size ^ (size >>> 32));
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((url == null) ? 0 : url.hashCode());
return result;
@ -206,22 +163,10 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
if (getClass() != obj.getClass())
return false;
BlobPropertiesImpl other = (BlobPropertiesImpl) obj;
if (contentEncoding == null) {
if (other.contentEncoding != null)
if (contentMetadata == null) {
if (other.contentMetadata != null)
return false;
} else if (!contentEncoding.equals(other.contentEncoding))
return false;
if (contentLanguage == null) {
if (other.contentLanguage != null)
return false;
} else if (!contentLanguage.equals(other.contentLanguage))
return false;
if (!Arrays.equals(contentMD5, other.contentMD5))
return false;
if (contentType == null) {
if (other.contentType != null)
return false;
} else if (!contentType.equals(other.contentType))
} else if (!contentMetadata.equals(other.contentMetadata))
return false;
if (eTag == null) {
if (other.eTag != null)
@ -248,8 +193,6 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
return false;
} else if (!name.equals(other.name))
return false;
if (size != other.size)
return false;
if (type == null) {
if (other.type != null)
return false;
@ -265,8 +208,8 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
@Override
public String toString() {
return "[name=" + name + ", type=" + type + ", contentType=" + contentType
+ ", eTag=" + eTag + ", lastModified=" + lastModified + ", size=" + size + "]";
return "[name=" + name + ", type=" + type + ", contentMetadata=" + contentMetadata + ", eTag=" + eTag
+ ", lastModified=" + lastModified + "]";
}
}

View File

@ -1,186 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.azure.storage.blob.domain.internal;
import java.io.Serializable;
import java.net.URI;
import java.util.Date;
import java.util.Map;
import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.BlobType;
import org.jclouds.azure.storage.blob.domain.LeaseStatus;
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
/**
* Allows you to manipulate metadata.
*
* @author Adrian Cole
*/
public class DelegatingMutableBlobProperties implements Serializable, MutableBlobProperties {
/** The serialVersionUID */
private static final long serialVersionUID = 9136392820647068818L;
private final MutableBlobProperties delegate;
public DelegatingMutableBlobProperties(MutableBlobProperties delegate) {
this.delegate = delegate;
}
@Override
public int compareTo(BlobProperties o) {
return delegate.compareTo(o);
}
@Override
public boolean equals(Object obj) {
return delegate.equals(obj);
}
@Override
public String getContentEncoding() {
return delegate.getContentEncoding();
}
@Override
public String getContentLanguage() {
return delegate.getContentLanguage();
}
@Override
public Long getContentLength() {
return delegate.getContentLength();
}
@Override
public byte[] getContentMD5() {
return delegate.getContentMD5();
}
@Override
public String getContentType() {
return delegate.getContentType();
}
@Override
public String getETag() {
return delegate.getETag();
}
@Override
public Date getLastModified() {
return delegate.getLastModified();
}
@Override
public LeaseStatus getLeaseStatus() {
return delegate.getLeaseStatus();
}
@Override
public Map<String, String> getMetadata() {
return delegate.getMetadata();
}
@Override
public String getName() {
return delegate.getName();
}
@Override
public BlobType getType() {
return delegate.getType();
}
@Override
public URI getUrl() {
return delegate.getUrl();
}
@Override
public int hashCode() {
return delegate.hashCode();
}
@Override
public void setContentEncoding(String encoding) {
delegate.setContentEncoding(encoding);
}
@Override
public void setContentLanguage(String contentLanguage) {
delegate.setContentLanguage(contentLanguage);
}
@Override
public void setContentLength(Long size) {
delegate.setContentLength(size);
}
@Override
public void setContentMD5(byte[] md5) {
delegate.setContentMD5(md5);
}
@Override
public void setContentType(String contentType) {
delegate.setContentType(contentType);
}
@Override
public void setETag(String eTag) {
delegate.setETag(eTag);
}
@Override
public void setLastModified(Date lastModified) {
delegate.setLastModified(lastModified);
}
@Override
public void setMetadata(Map<String, String> metadata) {
delegate.setMetadata(metadata);
}
@Override
public void setName(String name) {
delegate.setName(name);
}
@Override
public void setUrl(URI url) {
delegate.setUrl(url);
}
@Override
public String toString() {
return delegate.toString();
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public MutableBlobProperties getDelegate() {
return delegate;
}
}

View File

@ -21,7 +21,6 @@ package org.jclouds.azure.storage.blob.domain.internal;
import java.io.Serializable;
import java.net.URI;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
@ -29,6 +28,9 @@ import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.BlobType;
import org.jclouds.azure.storage.blob.domain.LeaseStatus;
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
import org.jclouds.http.HttpUtils;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.payloads.BaseMutableContentMetadata;
import com.google.common.collect.Maps;
@ -49,14 +51,17 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
private URI url;
private Date lastModified;
private String eTag;
private Long size;
private String contentType;
private byte[] contentMD5;
private String contentEncoding;
private String contentLanguage;
private MutableContentMetadata contentMetadata;
private Map<String, String> metadata = Maps.newHashMap();
public MutableBlobPropertiesImpl() {
super();
this.contentMetadata = new BaseMutableContentMetadata();
}
public MutableBlobPropertiesImpl(BlobProperties from) {
this.contentMetadata = new BaseMutableContentMetadata();
HttpUtils.copy(from.getContentMetadata(), this.contentMetadata);
}
/**
@ -80,20 +85,6 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
return name;
}
/**
*{@inheritDoc}
*/
public String getContentEncoding() {
return contentEncoding;
}
/**
*{@inheritDoc}
*/
public String getContentType() {
return contentType;
}
/**
*{@inheritDoc}
*/
@ -108,13 +99,6 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
return eTag;
}
/**
*{@inheritDoc}
*/
public Long getContentLength() {
return size;
}
/**
*{@inheritDoc}
*/
@ -129,37 +113,6 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
return metadata;
}
/**
*{@inheritDoc}
*/
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;
}
}
/**
*{@inheritDoc}
*/
public void setContentEncoding(String encoding) {
this.contentEncoding = encoding;
}
/**
*{@inheritDoc}
*/
public void setContentMD5(byte[] md5) {
if (md5 != null) {
byte[] retval = new byte[md5.length];
System.arraycopy(md5, 0, retval, 0, md5.length);
this.contentMD5 = md5;
}
}
/**
*{@inheritDoc}
*/
@ -168,13 +121,6 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
return leaseStatus;
}
/**
*{@inheritDoc}
*/
public void setContentType(String contentType) {
this.contentType = contentType;
}
/**
*{@inheritDoc}
*/
@ -196,13 +142,6 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
this.lastModified = lastModified;
}
/**
*{@inheritDoc}
*/
public void setContentLength(Long size) {
this.size = size;
}
/**
*{@inheritDoc}
*/
@ -210,18 +149,10 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
this.metadata = metadata;
}
public void setContentLanguage(String contentLanguage) {
this.contentLanguage = contentLanguage;
}
public void setUrl(URI url) {
this.url = url;
}
public String getContentLanguage() {
return contentLanguage;
}
public URI getUrl() {
return url;
}
@ -230,15 +161,11 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((contentEncoding == null) ? 0 : contentEncoding.hashCode());
result = prime * result + ((contentLanguage == null) ? 0 : contentLanguage.hashCode());
result = prime * result + Arrays.hashCode(contentMD5);
result = prime * result + ((contentType == null) ? 0 : contentType.hashCode());
result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.hashCode());
result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + (int) (size ^ (size >>> 32));
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((url == null) ? 0 : url.hashCode());
return result;
@ -253,22 +180,10 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
if (getClass() != obj.getClass())
return false;
MutableBlobPropertiesImpl other = (MutableBlobPropertiesImpl) obj;
if (contentEncoding == null) {
if (other.contentEncoding != null)
if (contentMetadata == null) {
if (other.contentMetadata != null)
return false;
} else if (!contentEncoding.equals(other.contentEncoding))
return false;
if (contentLanguage == null) {
if (other.contentLanguage != null)
return false;
} else if (!contentLanguage.equals(other.contentLanguage))
return false;
if (!Arrays.equals(contentMD5, other.contentMD5))
return false;
if (contentType == null) {
if (other.contentType != null)
return false;
} else if (!contentType.equals(other.contentType))
} else if (!contentMetadata.equals(other.contentMetadata))
return false;
if (eTag == null) {
if (other.eTag != null)
@ -290,8 +205,6 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
return false;
} else if (!name.equals(other.name))
return false;
if (size != other.size)
return false;
if (type == null) {
if (other.type != null)
return false;
@ -310,4 +223,21 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
return "[name=" + name + ", type=" + type + ", lastModified=" + lastModified + "]";
}
/**
* {@inheritDoc}
*/
@Override
public MutableContentMetadata getContentMetadata() {
return contentMetadata;
}
/**
* {@inheritDoc}
*/
@Override
public void setContentMetadata(MutableContentMetadata contentMetadata) {
this.contentMetadata = contentMetadata;
}
}

View File

@ -19,10 +19,7 @@
package org.jclouds.azure.storage.blob.functions;
import static org.jclouds.http.HttpUtils.attemptToParseSizeAndRangeFromHeaders;
import javax.inject.Inject;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.azure.storage.blob.blobstore.functions.BlobMetadataToBlobProperties;
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
@ -41,8 +38,7 @@ import com.google.common.base.Function;
*
* @author Adrian Cole
*/
public class ParseBlobPropertiesFromHeaders implements
Function<HttpResponse, MutableBlobProperties>, InvocationContext {
public class ParseBlobPropertiesFromHeaders implements Function<HttpResponse, MutableBlobProperties>, InvocationContext {
private final ParseSystemAndUserMetadataFromHeaders blobMetadataParser;
private final BlobMetadataToBlobProperties blobToBlobProperties;
@ -59,9 +55,6 @@ public class ParseBlobPropertiesFromHeaders implements
public MutableBlobProperties apply(HttpResponse from) {
BlobMetadata base = blobMetadataParser.apply(from);
MutableBlobProperties to = blobToBlobProperties.apply(base);
to.setContentLength(attemptToParseSizeAndRangeFromHeaders(from));
to.setContentLanguage(from.getFirstHeaderOrNull(HttpHeaders.CONTENT_LANGUAGE));
to.setContentEncoding(from.getFirstHeaderOrNull(HttpHeaders.CONTENT_ENCODING));
return to;
}

View File

@ -103,9 +103,9 @@ public class SharedKeyLiteAuthentication implements HttpRequestFilter {
}
private void appendPayloadMetadata(HttpRequest request, StringBuilder buffer) {
buffer.append(utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentMD5()))
buffer.append(utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata().getContentMD5()))
.append("\n");
buffer.append(utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentType()))
buffer.append(utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata().getContentType()))
.append("\n");
}

View File

@ -229,11 +229,12 @@ public class AzureBlobClientLiveTest {
object.getProperties().setName("object");
object.setPayload(data);
Payloads.calculateMD5(object);
object.getProperties().setContentType("text/plain");
object.getProperties().getContentMetadata().setContentType("text/plain");
object.getProperties().getMetadata().put("mykey", "metadata-value");
byte[] md5 = object.getProperties().getContentMD5();
byte[] md5 = object.getProperties().getContentMetadata().getContentMD5();
String newEtag = client.putBlob(privateContainer, object);
assertEquals(CryptoStreams.hex(md5), CryptoStreams.hex(object.getProperties().getContentMD5()));
assertEquals(CryptoStreams.hex(md5), CryptoStreams.hex(object.getProperties().getContentMetadata()
.getContentMD5()));
// Test HEAD of missing object
assert client.getBlobProperties(privateContainer, "non-existent-object") == null;
@ -247,9 +248,10 @@ public class AzureBlobClientLiveTest {
// inexpensive fashion
// http://code.google.com/p/jclouds/issues/detail?id=92
// assertEquals(metadata.getSize(), data.length());
assertEquals(metadata.getContentType(), "text/plain");
assertEquals(metadata.getContentMetadata().getContentType(), "text/plain");
// Azure doesn't return the Content-MD5 on head request..
assertEquals(CryptoStreams.hex(md5), CryptoStreams.hex(object.getProperties().getContentMD5()));
assertEquals(CryptoStreams.hex(md5), CryptoStreams.hex(object.getProperties().getContentMetadata()
.getContentMD5()));
assertEquals(metadata.getETag(), newEtag);
assertEquals(metadata.getMetadata().entrySet().size(), 1);
assertEquals(metadata.getMetadata().get("mykey"), "metadata-value");
@ -268,9 +270,10 @@ public class AzureBlobClientLiveTest {
AzureBlob getBlob = client.getBlob(privateContainer, object.getProperties().getName());
assertEquals(Utils.toStringAndClose(getBlob.getPayload().getInput()), data);
// TODO assertEquals(getBlob.getName(), object.getProperties().getName());
assertEquals(getBlob.getPayload().getContentLength(), new Long(data.length()));
assertEquals(getBlob.getProperties().getContentType(), "text/plain");
assertEquals(CryptoStreams.hex(md5), CryptoStreams.hex(getBlob.getProperties().getContentMD5()));
assertEquals(getBlob.getPayload().getContentMetadata().getContentLength(), new Long(data.length()));
assertEquals(getBlob.getProperties().getContentMetadata().getContentType(), "text/plain");
assertEquals(CryptoStreams.hex(md5), CryptoStreams.hex(getBlob.getProperties().getContentMetadata()
.getContentMD5()));
assertEquals(newEtag, getBlob.getProperties().getETag());
// wait until we can update metadata
// assertEquals(getBlob.getProperties().getMetadata().entries().size(), 2);
@ -306,9 +309,10 @@ public class AzureBlobClientLiveTest {
object = client.newBlob();
object.getProperties().setName("chunked-object");
object.setPayload(bais);
object.getPayload().setContentLength(new Long(data.getBytes().length));
object.getPayload().getContentMetadata().setContentLength(new Long(data.getBytes().length));
newEtag = client.putBlob(privateContainer, object);
assertEquals(CryptoStreams.hex(md5), CryptoStreams.hex(getBlob.getProperties().getContentMD5()));
assertEquals(CryptoStreams.hex(md5), CryptoStreams.hex(getBlob.getProperties().getContentMetadata()
.getContentMD5()));
// Test GET with options
// Non-matching ETag

View File

@ -31,6 +31,7 @@ import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
import org.jclouds.blobstore.binders.BindUserMetadataToHeadersWithPrefix;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.Payload;
import org.testng.annotations.Test;
@ -55,9 +56,11 @@ public class BindAzureBlobToPayloadTest {
Blob blob = createMock(Blob.class);
MutableBlobProperties md = createMock(MutableBlobProperties.class);
Multimap<String, String> headers = createMock(Multimap.class);
MutableContentMetadata content = createMock(MutableContentMetadata.class);
expect(object.getPayload()).andReturn(payload).atLeastOnce();
expect(payload.getContentLength()).andReturn(1024l).atLeastOnce();
expect(payload.getContentMetadata()).andReturn(content).atLeastOnce();
expect(content.getContentLength()).andReturn(1024l).atLeastOnce();
expect(object2Blob.apply(object)).andReturn(blob);
mdBinder.bindToRequest(request, blob);
expect(object.getProperties()).andReturn(md).atLeastOnce();
@ -65,10 +68,8 @@ public class BindAzureBlobToPayloadTest {
expect(request.getHeaders()).andReturn(headers).atLeastOnce();
expect(headers.put("x-ms-blob-type", "BlockBlob")).andReturn(true);
expect(md.getContentLanguage()).andReturn(null).atLeastOnce();
expect(md.getContentEncoding()).andReturn(null).atLeastOnce();
replay(headers);
replay(content);
replay(payload);
replay(mdBinder);
replay(object2Blob);
@ -82,6 +83,7 @@ public class BindAzureBlobToPayloadTest {
binder.bindToRequest(request, object);
verify(headers);
verify(content);
verify(payload);
verify(mdBinder);
verify(object2Blob);
@ -104,9 +106,11 @@ public class BindAzureBlobToPayloadTest {
Blob blob = createMock(Blob.class);
MutableBlobProperties md = createMock(MutableBlobProperties.class);
Multimap<String, String> headers = createMock(Multimap.class);
MutableContentMetadata content = createMock(MutableContentMetadata.class);
expect(object.getPayload()).andReturn(payload).atLeastOnce();
expect(payload.getContentLength()).andReturn(1024l).atLeastOnce();
expect(payload.getContentMetadata()).andReturn(content).atLeastOnce();
expect(content.getContentLength()).andReturn(1024l).atLeastOnce();
expect(object2Blob.apply(object)).andReturn(blob);
mdBinder.bindToRequest(request, blob);
expect(object.getProperties()).andReturn(md).atLeastOnce();
@ -114,14 +118,9 @@ public class BindAzureBlobToPayloadTest {
expect(request.getHeaders()).andReturn(headers).atLeastOnce();
expect(headers.put("x-ms-blob-type", "BlockBlob")).andReturn(true);
expect(md.getContentLanguage()).andReturn("en").atLeastOnce();
expect(headers.put("Content-Language", "en")).andReturn(true);
expect(md.getContentEncoding()).andReturn("gzip").atLeastOnce();
expect(headers.put("Content-Encoding", "gzip")).andReturn(true);
replay(headers);
replay(payload);
replay(content);
replay(mdBinder);
replay(object2Blob);
replay(request);
@ -135,6 +134,7 @@ public class BindAzureBlobToPayloadTest {
verify(headers);
verify(payload);
verify(content);
verify(mdBinder);
verify(object2Blob);
verify(request);
@ -156,9 +156,11 @@ public class BindAzureBlobToPayloadTest {
Blob blob = createMock(Blob.class);
MutableBlobProperties md = createMock(MutableBlobProperties.class);
Multimap<String, String> headers = createMock(Multimap.class);
MutableContentMetadata content = createMock(MutableContentMetadata.class);
expect(object.getPayload()).andReturn(payload).atLeastOnce();
expect(payload.getContentLength()).andReturn(5368709121l).atLeastOnce();
expect(payload.getContentMetadata()).andReturn(content).atLeastOnce();
expect(content.getContentLength()).andReturn(5368709121l).atLeastOnce();
expect(object2Blob.apply(object)).andReturn(blob);
mdBinder.bindToRequest(request, blob);
expect(object.getProperties()).andReturn(md).atLeastOnce();
@ -166,11 +168,13 @@ public class BindAzureBlobToPayloadTest {
expect(request.getHeaders()).andReturn(headers).atLeastOnce();
expect(headers.put("x-ms-blob-type", "BlockBlob")).andReturn(true);
expect(md.getContentLanguage()).andReturn(null).atLeastOnce();
expect(md.getContentEncoding()).andReturn(null).atLeastOnce();
expect(content.getContentLanguage()).andReturn(null).atLeastOnce();
expect(content.getContentEncoding()).andReturn(null).atLeastOnce();
replay(headers);
replay(payload);
replay(content);
replay(mdBinder);
replay(object2Blob);
replay(request);
@ -178,12 +182,12 @@ public class BindAzureBlobToPayloadTest {
replay(blob);
replay(md);
BindAzureBlobToPayload bindAzureBlobToPayload = new BindAzureBlobToPayload(object2Blob,
mdBinder);
BindAzureBlobToPayload bindAzureBlobToPayload = new BindAzureBlobToPayload(object2Blob, mdBinder);
bindAzureBlobToPayload.bindToRequest(request, object);
verify(headers);
verify(content);
verify(payload);
verify(mdBinder);
verify(object2Blob);

View File

@ -32,7 +32,6 @@ import org.jclouds.blobstore.domain.Blob.Factory;
import org.jclouds.date.TimeStamp;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.RequiresHttp;
import org.jclouds.io.payloads.PhantomPayload;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.RestContextFactory;
@ -46,7 +45,7 @@ import com.google.inject.Module;
import com.google.inject.TypeLiteral;
@Test(groups = "unit", testName = "s3.AzureBlobBlobRequestSignerTest")
public class AzureBlobBlobRequestSignerTest extends RestClientTest<AzureBlobAsyncClient> {
public class AzureBlobRequestSignerTest extends RestClientTest<AzureBlobAsyncClient> {
private BlobRequestSigner signer;
private Factory blobFactory;
@ -81,8 +80,10 @@ public class AzureBlobBlobRequestSignerTest extends RestClientTest<AzureBlobAsyn
NoSuchMethodException, IOException {
Blob blob = blobFactory.create(null);
blob.getMetadata().setName("name");
blob.setPayload(new PhantomPayload(2l, new byte[] { 0, 2, 4, 8 }));
blob.getPayload().setContentType("text/plain");
blob.setPayload("");
blob.getPayload().getContentMetadata().setContentLength(2l);
blob.getPayload().getContentMetadata().setContentMD5(new byte[] { 0, 2, 4, 8 });
blob.getPayload().getContentMetadata().setContentType("text/plain");
HttpRequest request = signer.signPutBlob("container", blob);

View File

@ -239,35 +239,6 @@ Options can also be specified for extension modules
([container-name path #^BlobStore blobstore]
(.getBlob blobstore container-name path)))
(defn sign-get-blob-request
"Get a signed http request for a blob, so that you can retrieve it
in another application. ex. curl"
([container-name path]
(sign-get-blob-request container-name path *blobstore*))
([container-name path #^BlobStore blobstore]
(.signGetBlob (.. blobstore getContext getSigner) container-name path)))
(defn sign-remove-blob-request
"Get a signed http request for deleting a blob in another application.
ex. curl"
([container-name path]
(sign-remove-blob-request container-name path *blobstore*))
([container-name path #^BlobStore blobstore]
(.signRemoveBlob (.. blobstore getContext getSigner) container-name path)))
(defn sign-put-blob-request
"Get a signed http request for uploading a blob in another application.
ex. curl"
([container-name path content-type size]
(sign-put-blob-request container-name path content-type size *blobstore*))
([container-name path content-type size #^BlobStore blobstore]
(.signPutBlob (.. blobstore getContext getSigner) container-name
(doto (.newBlob blobstore path)
(.setPayload (doto
;; until we pass content md5
(PhantomPayload. (long size) nil)
(.setContentType content-type)))))))
(defn sign-blob-request
"Get a signed http request for manipulating a blob in another application.
ex. curl"
@ -278,14 +249,18 @@ in another application. ex. curl"
{:keys [method content-type content-length content-md5]} blobstore]
{:pre [(or content-length (#{:delete :get} method))]}
(case method
:delete (sign-remove-blob-request container-name path blobstore)
:get (sign-get-blob-request container-name path blobstore)
:delete (.signRemoveBlob (.. blobstore getContext getSigner) container-name path)
:get (.signGetBlob (.. blobstore getContext getSigner) container-name path)
:put (.signPutBlob
(.. blobstore getContext getSigner) container-name
(doto (.newBlob blobstore path)
(.setPayload
(doto (PhantomPayload. (long content-length) content-md5)
(.setContentType content-type))))))))
(doto
(PhantomPayload. )
;; TODO look into use of ContentMetadata constructor
(.getContentMetadata (.setContentLength (long content-length)))
(.getContentMetadata (.setContentType content-type))
(.getContentMetadata (.setContentMD5 content-md5)))))))))
(defn get-blob-stream
"Get an inputstream from the blob at a given path"
@ -371,7 +346,7 @@ container, name, string -> etag"
target (.md5(.crypto (.utils (blobstore-context blobstore)))))]
(.writeTo (.getPayload blob) digest-stream)
(let [digest (.digest (.getMessageDigest digest-stream))
metadata-digest (.getContentMD5 (.getPayload blob))]
metadata-digest (.getContentMD5 (.getContentMetadata (.getPayload blob)))]
(when-not (Arrays/equals digest metadata-digest)
(if (<= (or retries 0) *max-retries*)
(recur container-name name target blobstore [(inc (or retries 1))])

View File

@ -86,7 +86,9 @@ import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.options.HttpRequestOptions;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.Payload;
import org.jclouds.io.Payloads;
import org.jclouds.io.payloads.ByteArrayPayload;
@ -103,8 +105,7 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.internal.Nullable;
/**
* Implementation of {@link BaseAsyncBlobStore} which keeps all data in a local
* Map object.
* Implementation of {@link BaseAsyncBlobStore} which keeps all data in a local Map object.
*
* @author Adrian Cole
* @author James Murty
@ -121,11 +122,12 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
@Inject
protected TransientAsyncBlobStore(BlobStoreContext context, DateService dateService, Crypto crypto,
ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
ConcurrentMap<String, Location> containerToLocation, HttpGetOptionsListToGetOptions httpGetOptionsConverter,
IfDirectoryReturnNameStrategy ifDirectoryReturnName, Blob.Factory blobFactory, BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
Supplier<Set<? extends Location>> locations) {
ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
ConcurrentMap<String, Location> containerToLocation,
HttpGetOptionsListToGetOptions httpGetOptionsConverter,
IfDirectoryReturnNameStrategy ifDirectoryReturnName, Blob.Factory blobFactory, BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
Supplier<Set<? extends Location>> locations) {
super(context, blobUtils, service, defaultLocation, locations);
this.blobFactory = blobFactory;
this.dateService = dateService;
@ -149,21 +151,21 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
return immediateFailedFuture(cnfe(container));
SortedSet<StorageMetadata> contents = newTreeSet(transform(realContents.keySet(),
new Function<String, StorageMetadata>() {
public StorageMetadata apply(String key) {
Blob oldBlob = realContents.get(key);
checkState(oldBlob != null, "blob " + key + " is not present although it was in the list of "
+ container);
checkState(oldBlob.getMetadata() != null, "blob " + container + "/" + key + " has no metadata");
MutableBlobMetadata md = copy(oldBlob.getMetadata());
String directoryName = ifDirectoryReturnName.execute(md);
if (directoryName != null) {
md.setName(directoryName);
md.setType(StorageType.RELATIVE_PATH);
new Function<String, StorageMetadata>() {
public StorageMetadata apply(String key) {
Blob oldBlob = realContents.get(key);
checkState(oldBlob != null, "blob " + key + " is not present although it was in the list of "
+ container);
checkState(oldBlob.getMetadata() != null, "blob " + container + "/" + key + " has no metadata");
MutableBlobMetadata md = copy(oldBlob.getMetadata());
String directoryName = ifDirectoryReturnName.execute(md);
if (directoryName != null) {
md.setName(directoryName);
md.setType(StorageType.RELATIVE_PATH);
}
return md;
}
return md;
}
}));
}));
if (options.getMarker() != null) {
final String finalMarker = options.getMarker();
@ -208,14 +210,14 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
contents = newTreeSet(filter(contents, new DelimiterFilter(prefix != null ? prefix : null, delimiter)));
Iterables.<StorageMetadata> addAll(contents, transform(commonPrefixes,
new Function<String, StorageMetadata>() {
public StorageMetadata apply(String o) {
MutableStorageMetadata md = new MutableStorageMetadataImpl();
md.setType(StorageType.RELATIVE_PATH);
md.setName(o);
return md;
}
}));
new Function<String, StorageMetadata>() {
public StorageMetadata apply(String o) {
MutableStorageMetadata md = new MutableStorageMetadataImpl();
md.setType(StorageType.RELATIVE_PATH);
md.setName(o);
return md;
}
}));
}
// trim metadata, if the response isn't supposed to be detailed.
@ -226,13 +228,13 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
}
return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(contents,
marker));
marker));
}
private ContainerNotFoundException cnfe(final String name) {
return new ContainerNotFoundException(name, String.format("container %s not in %s", name, getContainerToBlobs()
.keySet()));
.keySet()));
}
public static MutableBlobMetadata copy(MutableBlobMetadata in) {
@ -242,9 +244,10 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
os = new ObjectOutputStream(bout);
os.writeObject(in);
ObjectInput is = new ObjectInputStream(new ByteArrayInputStream(bout.toByteArray()));
MutableBlobMetadata metadata = (MutableBlobMetadata) is.readObject();
convertUserMetadataKeysToLowercase(metadata);
return metadata;
MutableBlobMetadata out = (MutableBlobMetadata) is.readObject();
convertUserMetadataKeysToLowercase(out);
HttpUtils.copy(in.getContentMetadata(), out.getContentMetadata());
return out;
} catch (Exception e) {
propagate(e);
assert false : "exception should have propagated: " + e;
@ -329,15 +332,15 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
@Override
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(transform(
getContainerToBlobs().keySet(), new Function<String, StorageMetadata>() {
public StorageMetadata apply(String name) {
MutableStorageMetadata cmd = create();
cmd.setName(name);
cmd.setType(StorageType.CONTAINER);
cmd.setLocation(getContainerToLocation().get(name));
return cmd;
}
}), null));
getContainerToBlobs().keySet(), new Function<String, StorageMetadata>() {
public StorageMetadata apply(String name) {
MutableStorageMetadata cmd = create();
cmd.setName(name);
cmd.setType(StorageType.CONTAINER);
cmd.setLocation(getContainerToLocation().get(name));
return cmd;
}
}), null));
}
protected MutableStorageMetadata create() {
@ -361,7 +364,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
*/
public ListenableFuture<Void> createContainerInLocationIfAbsent(final Location location, final String name) {
ConcurrentMap<String, Blob> container = getContainerToBlobs().putIfAbsent(name,
new ConcurrentHashMap<String, Blob>());
new ConcurrentHashMap<String, Blob>());
if (container == null) {
getContainerToLocation().put(name, location != null ? location : defaultLocation.get());
return immediateFuture((Void) null);
@ -506,20 +509,20 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
protected Blob createUpdatedCopyOfBlob(Blob in) {
ByteArrayPayload payload = (in.getPayload() instanceof ByteArrayPayload) ? ByteArrayPayload.class.cast(in
.getPayload()) : null;
.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;
.getDelegate() instanceof ByteArrayPayload) ? ByteArrayPayload.class.cast(DelegatingPayload.class
.cast(in.getPayload()).getDelegate()) : null : null;
try {
if (payload == null || !(payload instanceof ByteArrayPayload)) {
String oldContentType = in.getPayload().getContentType();
MutableContentMetadata oldMd = in.getPayload().getContentMetadata();
ByteArrayOutputStream out = new ByteArrayOutputStream();
in.getPayload().writeTo(out);
payload = (ByteArrayPayload) Payloads.calculateMD5(Payloads.newPayload(out.toByteArray()));
payload.setContentType(oldContentType);
HttpUtils.copy(oldMd, payload.getContentMetadata());
} else {
if (payload.getContentMD5() == null)
if (payload.getContentMetadata().getContentMD5() == null)
Payloads.calculateMD5(in, crypto.md5());
}
} catch (IOException e) {
@ -528,18 +531,11 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
Blob blob = blobFactory.create(copy(in.getMetadata()));
blob.setPayload(payload);
blob.getMetadata().setLastModified(new Date());
blob.getMetadata().setSize(payload.getContentLength());
blob.getMetadata().setContentMD5(payload.getContentMD5());
blob.getMetadata().setContentType(payload.getContentType());
blob.getMetadata().setContentDisposition(payload.getContentDisposition());
blob.getMetadata().setContentEncoding(payload.getContentEncoding());
blob.getMetadata().setContentLanguage(payload.getContentLanguage());
String eTag = CryptoStreams.hex(payload.getContentMD5());
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())));
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()));
@ -547,23 +543,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
}
private void copyPayloadHeadersToBlob(Payload payload, Blob blob) {
if (payload.getContentType() != null)
blob.getAllHeaders().replaceValues(HttpHeaders.CONTENT_TYPE, Collections.singleton(payload.getContentType()));
if (payload.getContentDisposition() != null)
blob.getAllHeaders().replaceValues("Content-Disposition",
Collections.singleton(payload.getContentDisposition()));
if (payload.getContentEncoding() != null)
blob.getAllHeaders().replaceValues(HttpHeaders.CONTENT_ENCODING,
Collections.singleton(payload.getContentEncoding()));
if (payload.getContentEncoding() != null)
blob.getAllHeaders().replaceValues(HttpHeaders.CONTENT_LANGUAGE,
Collections.singleton(payload.getContentLanguage()));
if (payload.getContentLength() != null)
blob.getAllHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH,
Collections.singleton(payload.getContentLength() + ""));
if (payload.getContentMD5() != null)
blob.getAllHeaders().replaceValues("Content-MD5",
Collections.singleton(CryptoStreams.base64(payload.getContentMD5())));
HttpUtils.addContentHeadersFromMetadata(payload.getContentMetadata(), blob.getAllHeaders());
}
/**
@ -603,7 +583,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
if (object.getMetadata().getLastModified().before(modifiedSince)) {
HttpResponse response = new HttpResponse(304, null, null);
return immediateFailedFuture(new HttpResponseException(String.format("%1$s is before %2$s", object
.getMetadata().getLastModified(), modifiedSince), null, response));
.getMetadata().getLastModified(), modifiedSince), null, response));
}
}
@ -612,7 +592,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
if (object.getMetadata().getLastModified().after(unmodifiedSince)) {
HttpResponse response = new HttpResponse(412, null, null);
return immediateFailedFuture(new HttpResponseException(String.format("%1$s is after %2$s", object
.getMetadata().getLastModified(), unmodifiedSince), null, response));
.getMetadata().getLastModified(), unmodifiedSince), null, response));
}
}
Blob returnVal = copyBlob(object);
@ -644,7 +624,6 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
}
returnVal.setPayload(out.toByteArray());
returnVal.getMetadata().setSize(new Long(data.length));
}
checkNotNull(returnVal.getPayload(), "payload " + returnVal);
return immediateFuture(returnVal);

View File

@ -25,11 +25,10 @@ import java.net.URI;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.filters.BasicAuthentication;
/**
@ -57,12 +56,7 @@ public class TransientBlobRequestSigner implements BlobRequestSigner {
public HttpRequest signPutBlob(String container, Blob blob) {
HttpRequest request = new HttpRequest("PUT", URI.create(String.format("http://localhost/%s/%s", container, blob
.getMetadata().getName())));
if (blob.getPayload().getContentLength() != null)
request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, blob.getPayload().getContentLength().toString());
if (blob.getPayload().getContentType() != null)
request.getHeaders().put(HttpHeaders.CONTENT_TYPE, blob.getPayload().getContentType());
if (blob.getPayload().getContentMD5() != null)
request.getHeaders().put("Content-MD5", CryptoStreams.base64(blob.getPayload().getContentMD5()));
HttpUtils.addContentHeadersFromMetadata(blob.getMetadata().getContentMetadata(), request.getHeaders());
request.setPayload(blob.getPayload());
basicAuth.filter(request);
return request;

View File

@ -39,7 +39,7 @@ public class BindBlobToMultipartForm implements Binder {
Blob blob = (Blob) payload;
Part part = Part.create(blob.getMetadata().getName(), blob.getPayload(),
new PartOptions().contentType(blob.getMetadata().getContentType()));
new PartOptions().contentType(blob.getMetadata().getContentMetadata().getContentType()));
request.setPayload(new MultipartForm(part));
}

View File

@ -19,9 +19,8 @@
package org.jclouds.blobstore.domain;
import javax.annotation.Nullable;
import org.jclouds.blobstore.domain.internal.BlobMetadataImpl;
import org.jclouds.io.ContentMetadata;
import com.google.inject.ImplementedBy;
@ -32,40 +31,5 @@ import com.google.inject.ImplementedBy;
*/
@ImplementedBy(BlobMetadataImpl.class)
public interface BlobMetadata extends StorageMetadata {
/**
* 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." />
*/
String getContentType();
byte[] getContentMD5();
/**
* Content-Disposition to set for the blob.
* <p/>
* <b>Attention</b>: Not all provider support it!
*
* @return
*/
String getContentDisposition();
/**
* Get Content Encoding of the blob
* <p/>
* Not all providers may support it
*/
@Nullable
String getContentEncoding();
/**
* Get Content Language of the blob
* <p/>
* Not all providers may support it
*/
@Nullable
String getContentLanguage();
ContentMetadata getContentMetadata();
}

View File

@ -19,9 +19,8 @@
package org.jclouds.blobstore.domain;
import javax.annotation.Nullable;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.io.MutableContentMetadata;
import com.google.inject.ImplementedBy;
@ -32,22 +31,8 @@ import com.google.inject.ImplementedBy;
*/
@ImplementedBy(MutableBlobMetadataImpl.class)
public interface MutableBlobMetadata extends BlobMetadata, MutableStorageMetadata {
MutableContentMetadata getContentMetadata();
/**
* 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." />
*/
void setContentType(@Nullable String type);
void setContentMD5(@Nullable byte[] md5);
void setContentDisposition(@Nullable String contentDisposition);
void setContentEncoding(@Nullable String contentEncoding);
void setContentLanguage(@Nullable String contentLanguage);
void setContentMetadata(MutableContentMetadata md);
}

View File

@ -21,8 +21,6 @@ package org.jclouds.blobstore.domain;
import java.util.Date;
import javax.annotation.Nullable;
import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl;
import org.jclouds.domain.MutableResourceMetadata;
@ -42,10 +40,6 @@ public interface MutableStorageMetadata extends MutableResourceMetadata<StorageT
*/
void setETag(String eTag);
/**
* @see #getSize
*/
void setSize(@Nullable Long size);
/**
* @see #getLastModified

View File

@ -83,14 +83,6 @@ public interface StorageMetadata extends ResourceMetadata<StorageType> {
*/
String getETag();
/**
* Size of the resource in bytes
*
* @see org.jclouds.blobstore.attr.ContainerCapability#CONTAINER_SIZE
* @see org.jclouds.blobstore.attr.ContainerCapability#BLOB_SIZE
*/
Long getSize();
/**
* Last modification time of the resource
*

View File

@ -28,8 +28,6 @@ import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.http.internal.PayloadEnclosingImpl;
import org.jclouds.io.Payload;
import org.jclouds.io.PayloadEnclosing;
import org.jclouds.io.payloads.DelegatingPayload;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
@ -44,15 +42,13 @@ import com.google.common.collect.Multimap;
*/
public class BlobImpl extends PayloadEnclosingImpl implements Blob, Comparable<Blob> {
private final MutableBlobMetadata _metadata;
private final SetPayloadPropertiesMutableBlobMetadata metadata;
private final MutableBlobMetadata metadata;
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
@Inject
public BlobImpl(MutableBlobMetadata metadata) {
super();
this.metadata = linkMetadataToThis(metadata);
this._metadata = this.metadata.getDelegate();
this.metadata = metadata;
}
/**
@ -93,7 +89,7 @@ public class BlobImpl extends PayloadEnclosingImpl implements Blob, Comparable<B
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((_metadata == null) ? 0 : _metadata.hashCode());
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
return result;
}
@ -106,124 +102,23 @@ public class BlobImpl extends PayloadEnclosingImpl implements Blob, Comparable<B
if (getClass() != obj.getClass())
return false;
BlobImpl other = (BlobImpl) obj;
if (_metadata == null) {
if (other._metadata != null)
if (metadata == null) {
if (other.metadata != null)
return false;
} else if (!_metadata.equals(other._metadata))
} else if (!metadata.equals(other.metadata))
return false;
return true;
}
@Override
public String toString() {
return "[metadata=" + _metadata + "]";
return "[metadata=" + metadata + "]";
}
@Override
public void setPayload(Payload data) {
linkPayloadToMetadata(data);
super.setPayload(data);
metadata.setContentMetadata(data.getContentMetadata());
}
/**
* link the new payload to the metadata object so that when content-related
* metadata is updated on the payload, it is also copied the metadata object.
*/
void linkPayloadToMetadata(Payload data) {
if (data instanceof DelegatingPayload)
super
.setPayload(new SetMetadataPropertiesPayload(DelegatingPayload.class.cast(data).getDelegate(), _metadata));
else
super.setPayload(new SetMetadataPropertiesPayload(data, _metadata));
}
static class SetMetadataPropertiesPayload extends DelegatingPayload {
private transient final MutableBlobMetadata metadata;
public SetMetadataPropertiesPayload(Payload delegate, MutableBlobMetadata metadata) {
super(delegate);
this.metadata = metadata;
setContentType(metadata.getContentType());
setContentDisposition(metadata.getContentDisposition());
setContentEncoding(metadata.getContentEncoding());
setContentLanguage(metadata.getContentLanguage());
}
@Override
public void setContentType(String md5) {
super.setContentType(md5);
metadata.setContentType(md5);
}
@Override
public void setContentDisposition(String contentDisposition) {
super.setContentDisposition(contentDisposition);
metadata.setContentDisposition(contentDisposition);
}
@Override
public void setContentEncoding(String contentEncoding) {
super.setContentEncoding(contentEncoding);
metadata.setContentEncoding(contentEncoding);
}
@Override
public void setContentLanguage(String contentLanguage) {
super.setContentLanguage(contentLanguage);
metadata.setContentLanguage(contentLanguage);
}
}
/**
* link the metadata object to this so that when content-related metadata is
* updated, it is also copied the currentpayload object.
*/
SetPayloadPropertiesMutableBlobMetadata linkMetadataToThis(MutableBlobMetadata metadata) {
return metadata instanceof DelegatingMutableBlobMetadata ? new SetPayloadPropertiesMutableBlobMetadata(
DelegatingMutableBlobMetadata.class.cast(metadata).getDelegate(), this)
: new SetPayloadPropertiesMutableBlobMetadata(metadata, this);
}
static class SetPayloadPropertiesMutableBlobMetadata extends DelegatingMutableBlobMetadata {
/** The serialVersionUID */
private static final long serialVersionUID = -5072270546219814521L;
private transient final PayloadEnclosing blob;
public SetPayloadPropertiesMutableBlobMetadata(MutableBlobMetadata delegate, PayloadEnclosing blob) {
super(delegate);
this.blob = blob;
}
@Override
public void setContentType(String type) {
super.setContentType(type);
if (canSetPayload())
blob.getPayload().setContentType(type);
}
@Override
public void setContentDisposition(String Disposition) {
super.setContentDisposition(Disposition);
if (canSetPayload())
blob.getPayload().setContentDisposition(Disposition);
}
@Override
public void setContentEncoding(String Encoding) {
super.setContentEncoding(Encoding);
if (canSetPayload())
blob.getPayload().setContentEncoding(Encoding);
}
@Override
public void setContentLanguage(String Language) {
super.setContentLanguage(Language);
if (canSetPayload())
blob.getPayload().setContentLanguage(Language);
}
private boolean canSetPayload() {
return blob != null && blob.getPayload() != null;
}
}
}

View File

@ -19,6 +19,8 @@
package org.jclouds.blobstore.domain.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.net.URI;
import java.util.Date;
@ -28,6 +30,7 @@ import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.domain.Location;
import org.jclouds.io.ContentMetadata;
import com.google.inject.internal.Nullable;
@ -39,68 +42,20 @@ import com.google.inject.internal.Nullable;
public class BlobMetadataImpl extends StorageMetadataImpl implements Serializable, BlobMetadata {
/** The serialVersionUID */
private static final long serialVersionUID = -5932618957134612231L;
private final ContentMetadata contentMetadata;
private final String contentType;
private final String contentDisposition;
private final String contentEncoding;
private final String contentLanguage;
private final byte[] contentMD5;
public BlobMetadataImpl(String id, String name, @Nullable Location location, URI uri, String eTag, Long size,
Date lastModified, Map<String, String> userMetadata, String contentType, String contentDisposition,
String contentEncoding, String contentLanguage, byte[] contentMD5) {
super(StorageType.BLOB, id, name, location, uri, eTag, size, lastModified, userMetadata);
this.contentType = contentType;
this.contentDisposition = contentDisposition;
this.contentEncoding = contentEncoding;
this.contentLanguage = contentLanguage;
this.contentMD5 = contentMD5;
public BlobMetadataImpl(String id, String name, @Nullable Location location, URI uri, String eTag,
Date lastModified, Map<String, String> userMetadata, ContentMetadata contentMetadata) {
super(StorageType.BLOB, id, name, location, uri, eTag, lastModified, userMetadata);
this.contentMetadata = checkNotNull(contentMetadata, "contentMetadata");
}
/**
* {@inheritDoc}
*/
@Override
public String getContentType() {
return contentType;
}
/**
* {@inheritDoc}
*/
@Override
public String getContentDisposition() {
return contentDisposition;
}
/**
* {@inheritDoc}
*/
@Override
public String getContentEncoding() {
return contentEncoding;
}
/**
* {@inheritDoc}
*/
@Override
public String getContentLanguage() {
return contentLanguage;
}
/**
* {@inheritDoc}
*/
@Override
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 ContentMetadata getContentMetadata() {
return contentMetadata;
}
}

View File

@ -1,209 +0,0 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.domain.internal;
import java.io.Serializable;
import java.net.URI;
import java.util.Date;
import java.util.Map;
import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.domain.Location;
import org.jclouds.domain.ResourceMetadata;
/**
*
* @author Adrian Cole
*/
public class DelegatingMutableBlobMetadata implements MutableBlobMetadata, Serializable {
/** The serialVersionUID */
private static final long serialVersionUID = -2739517840958218727L;
protected final MutableBlobMetadata delegate;
public DelegatingMutableBlobMetadata(MutableBlobMetadata delegate) {
this.delegate = delegate;
}
@Override
public void setContentMD5(byte[] md5) {
delegate.setContentMD5(md5);
}
@Override
public void setContentType(String type) {
delegate.setContentType(type);
}
@Override
public byte[] getContentMD5() {
return delegate.getContentMD5();
}
@Override
public String getContentType() {
return delegate.getContentType();
}
@Override
public void setETag(String eTag) {
delegate.setETag(eTag);
}
@Override
public void setLastModified(Date lastModified) {
delegate.setLastModified(lastModified);
}
@Override
public void setSize(Long size) {
delegate.setSize(size);
}
@Override
public String getETag() {
return delegate.getETag();
}
@Override
public Date getLastModified() {
return delegate.getLastModified();
}
@Override
public String getName() {
return delegate.getName();
}
@Override
public String getProviderId() {
return delegate.getProviderId();
}
@Override
public Long getSize() {
return delegate.getSize();
}
@Override
public StorageType getType() {
return delegate.getType();
}
@Override
public URI getUri() {
return delegate.getUri();
}
@Override
public Map<String, String> getUserMetadata() {
return delegate.getUserMetadata();
}
@Override
public void setId(String id) {
delegate.setId(id);
}
@Override
public void setLocation(Location location) {
delegate.setLocation(location);
}
@Override
public void setName(String name) {
delegate.setName(name);
}
@Override
public void setType(StorageType type) {
delegate.setType(type);
}
@Override
public void setUri(URI url) {
delegate.setUri(url);
}
@Override
public void setUserMetadata(Map<String, String> userMetadata) {
delegate.setUserMetadata(userMetadata);
}
@Override
public Location getLocation() {
return delegate.getLocation();
}
@Override
public int compareTo(ResourceMetadata<StorageType> o) {
return delegate.compareTo(o);
}
@Override
public boolean equals(Object obj) {
return delegate.equals(obj);
}
@Override
public int hashCode() {
return delegate.hashCode();
}
@Override
public String toString() {
return delegate.toString();
}
public MutableBlobMetadata getDelegate() {
return delegate;
}
@Override
public void setContentDisposition(String contentDisposition) {
delegate.setContentDisposition(contentDisposition);
}
@Override
public String getContentDisposition() {
return delegate.getContentDisposition();
}
@Override
public String getContentEncoding() {
return delegate.getContentEncoding();
}
@Override
public String getContentLanguage() {
return delegate.getContentLanguage();
}
@Override
public void setContentEncoding(String contentEncoding) {
delegate.setContentEncoding(contentEncoding);
}
@Override
public void setContentLanguage(String contentLanguage) {
delegate.setContentLanguage(contentLanguage);
}
}

View File

@ -23,6 +23,9 @@ import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.http.HttpUtils;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.payloads.BaseMutableContentMetadata;
/**
* System and user Metadata for the {@link Blob}.
@ -32,115 +35,34 @@ import org.jclouds.blobstore.domain.StorageType;
public class MutableBlobMetadataImpl extends MutableStorageMetadataImpl implements MutableBlobMetadata {
/** The serialVersionUID */
private static final long serialVersionUID = -5932618957134612231L;
private String contentType;
private String contentDisposition;
private String contentEncoding;
private String contentLanguage;
private byte[] contentMD5;
private MutableContentMetadata contentMetadata;
public MutableBlobMetadataImpl() {
super();
this.setType(StorageType.BLOB);
this.contentMetadata = new BaseMutableContentMetadata();
}
public MutableBlobMetadataImpl(BlobMetadata from) {
super(from);
this.contentType = from.getContentType();
this.contentDisposition = from.getContentDisposition();
this.contentEncoding = from.getContentEncoding();
this.contentLanguage = from.getContentLanguage();
this.contentMD5 = from.getContentMD5();
this.contentMetadata = new BaseMutableContentMetadata();
HttpUtils.copy(from.getContentMetadata(), this.contentMetadata);
}
/**
* {@inheritDoc}
*/
@Override
public String getContentType() {
return contentType;
public MutableContentMetadata getContentMetadata() {
return contentMetadata;
}
/**
* {@inheritDoc}
*/
@Override
public void setContentType(String contentType) {
this.contentType = contentType;
}
/**
* {@inheritDoc}
*/
@Override
public String getContentDisposition() {
return contentDisposition;
}
/**
* {@inheritDoc}
*/
@Override
public void setContentDisposition(String contentDisposition) {
this.contentDisposition = contentDisposition;
}
/**
* {@inheritDoc}
*/
@Override
public String getContentEncoding() {
return contentEncoding;
}
/**
* {@inheritDoc}
*/
@Override
public void setContentEncoding(String contentEncoding) {
this.contentEncoding = contentEncoding;
}
/**
* {@inheritDoc}
*/
@Override
public String getContentLanguage() {
return contentLanguage;
}
/**
* {@inheritDoc}
*/
@Override
public void setContentLanguage(String contentLanguage) {
this.contentLanguage = contentLanguage;
}
/**
* {@inheritDoc}
*/
@Override
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;
}
}
/**
* {@inheritDoc}
*/
@Override
public void setContentMD5(byte[] md5) {
if (md5 != null) {
byte[] retval = new byte[md5.length];
System.arraycopy(md5, 0, retval, 0, md5.length);
this.contentMD5 = md5;
}
public void setContentMetadata(MutableContentMetadata contentMetadata) {
this.contentMetadata = contentMetadata;
}
}

View File

@ -39,7 +39,6 @@ public class MutableStorageMetadataImpl extends MutableResourceMetadataImpl<Stor
private static final long serialVersionUID = -280558162576368264L;
private String eTag;
private Long size;
private Date lastModified;
public MutableStorageMetadataImpl() {
@ -49,7 +48,6 @@ public class MutableStorageMetadataImpl extends MutableResourceMetadataImpl<Stor
public MutableStorageMetadataImpl(StorageMetadata from) {
super(from);
this.eTag = from.getETag();
this.size = from.getSize();
this.lastModified = from.getLastModified();
}
@ -61,14 +59,6 @@ public class MutableStorageMetadataImpl extends MutableResourceMetadataImpl<Stor
return eTag;
}
/**
* {@inheritDoc}
*/
@Override
public Long getSize() {
return size;
}
/**
* {@inheritDoc}
*/
@ -85,14 +75,6 @@ public class MutableStorageMetadataImpl extends MutableResourceMetadataImpl<Stor
this.lastModified = lastModified;
}
/**
* {@inheritDoc}
*/
@Override
public void setSize(Long size) {
this.size = size;
}
/**
* {@inheritDoc}
*/

View File

@ -36,25 +36,22 @@ import com.google.inject.internal.Nullable;
*
* @author Adrian Cole
*/
public class StorageMetadataImpl extends ResourceMetadataImpl<StorageType> implements
StorageMetadata, Serializable {
public class StorageMetadataImpl extends ResourceMetadataImpl<StorageType> implements StorageMetadata, Serializable {
/** The serialVersionUID */
private static final long serialVersionUID = -280558162576368264L;
@Nullable
private final String eTag;
@Nullable
private final Long size;
@Nullable
private final Date lastModified;
public StorageMetadataImpl(StorageType type, @Nullable String id, @Nullable String name,
@Nullable Location location, @Nullable URI uri, @Nullable String eTag,
@Nullable Long size, @Nullable Date lastModified, Map<String, String> userMetadata) {
@Nullable Location location, @Nullable URI uri, @Nullable String eTag, @Nullable Date lastModified,
Map<String, String> userMetadata) {
super(type, id, name, location, uri, userMetadata);
this.eTag = eTag;
this.size = size;
this.lastModified = lastModified;
}
@ -66,14 +63,6 @@ public class StorageMetadataImpl extends ResourceMetadataImpl<StorageType> imple
return eTag;
}
/**
* {@inheritDoc}
*/
@Override
public Long getSize() {
return size;
}
/**
* {@inheritDoc}
*/

View File

@ -49,13 +49,13 @@ public class ObjectMD5 implements Function<Object, byte[]> {
object = blobFactory.create(null);
object.setPayload(Payloads.newPayload(from));
}
if (object.getMetadata().getContentMD5() == null)
if (object.getMetadata().getContentMetadata().getContentMD5() == null)
try {
Payloads.calculateMD5(object, crypto.md5());
} catch (IOException e) {
Throwables.propagate(e);
}
return object.getPayload().getContentMD5();
return object.getPayload().getContentMetadata().getContentMD5();
}
}

View File

@ -23,7 +23,6 @@ import static com.google.common.base.Preconditions.checkArgument;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.jclouds.blobstore.util.BlobStoreUtils.getKeyFor;
import static org.jclouds.http.HttpUtils.attemptToParseSizeAndRangeFromHeaders;
import java.util.Map.Entry;
@ -37,6 +36,7 @@ import org.jclouds.date.DateService;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.internal.GeneratedHttpRequest;
@ -47,7 +47,7 @@ import com.google.common.base.Function;
* @author Adrian Cole
*/
public class ParseSystemAndUserMetadataFromHeaders implements Function<HttpResponse, MutableBlobMetadata>,
InvocationContext {
InvocationContext {
private final String metadataPrefix;
private final DateService dateParser;
private final Provider<MutableBlobMetadata> metadataFactory;
@ -57,7 +57,7 @@ public class ParseSystemAndUserMetadataFromHeaders implements Function<HttpRespo
@Inject
public ParseSystemAndUserMetadataFromHeaders(Provider<MutableBlobMetadata> metadataFactory, DateService dateParser,
@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix, @Named(PROPERTY_API_VERSION) String apiVersion) {
@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix, @Named(PROPERTY_API_VERSION) String apiVersion) {
this.metadataFactory = metadataFactory;
this.dateParser = dateParser;
this.metadataPrefix = metadataPrefix;
@ -68,11 +68,9 @@ public class ParseSystemAndUserMetadataFromHeaders implements Function<HttpRespo
String objectKey = getKeyFor(request, from);
MutableBlobMetadata to = metadataFactory.get();
to.setName(objectKey);
setContentTypeOrThrowException(from, to);
HttpUtils.copy(from.getPayload().getContentMetadata(), to.getContentMetadata());
addETagTo(from, to);
addContentMD5To(from, to);
parseLastModifiedOrThrowException(from, to);
setContentLength(from, to);
addUserMetadataTo(from, to);
return to;
}
@ -82,15 +80,10 @@ public class ParseSystemAndUserMetadataFromHeaders implements Function<HttpRespo
for (Entry<String, String> header : from.getHeaders().entries()) {
if (header.getKey() != null && header.getKey().startsWith(metadataPrefix))
metadata.getUserMetadata().put((header.getKey().substring(metadataPrefix.length())).toLowerCase(),
header.getValue());
header.getValue());
}
}
@VisibleForTesting
void setContentLength(HttpResponse from, MutableBlobMetadata metadata) throws HttpException {
metadata.setSize(attemptToParseSizeAndRangeFromHeaders(from));
}
@VisibleForTesting
void parseLastModifiedOrThrowException(HttpResponse from, MutableBlobMetadata metadata) throws HttpException {
String lastModified = from.getFirstHeaderOrNull(HttpHeaders.LAST_MODIFIED);
@ -115,21 +108,6 @@ public class ParseSystemAndUserMetadataFromHeaders implements Function<HttpRespo
}
}
@VisibleForTesting
protected void addContentMD5To(HttpResponse from, MutableBlobMetadata metadata) {
if (from.getPayload() != null)
metadata.setContentMD5(from.getPayload().getContentMD5());
}
@VisibleForTesting
void setContentTypeOrThrowException(HttpResponse from, MutableBlobMetadata metadata) throws HttpException {
if (from.getPayload() != null)
metadata.setContentType(from.getPayload().getContentType());
if (from.getStatusCode() != 204 && (metadata.getContentType() == null
|| "application/unknown".equals(metadata.getContentType())))
throw new HttpException(HttpHeaders.CONTENT_TYPE + " not found in headers");
}
public ParseSystemAndUserMetadataFromHeaders setContext(HttpRequest request) {
checkArgument(request instanceof GeneratedHttpRequest<?>, "note this handler requires a GeneratedHttpRequest");
this.request = (GeneratedHttpRequest<?>) request;

View File

@ -29,8 +29,7 @@ import org.jclouds.blobstore.reference.BlobStoreConstants;
import com.google.common.base.Function;
@Singleton
public class ResourceMetadataToRelativePathResourceMetadata implements
Function<StorageMetadata, StorageMetadata> {
public class ResourceMetadataToRelativePathResourceMetadata implements Function<StorageMetadata, StorageMetadata> {
public StorageMetadata apply(StorageMetadata md) {
String name = md.getName();
@ -38,9 +37,8 @@ public class ResourceMetadataToRelativePathResourceMetadata implements
if (name.endsWith(suffix))
name = name.substring(0, name.length() - suffix.length());
}
return new StorageMetadataImpl(StorageType.RELATIVE_PATH, md.getProviderId(), name, md
.getLocation(), md.getUri(), md.getETag(), md.getSize(), md.getLastModified(), md
.getUserMetadata());
return new StorageMetadataImpl(StorageType.RELATIVE_PATH, md.getProviderId(), name, md.getLocation(),
md.getUri(), md.getETag(), md.getLastModified(), md.getUserMetadata());
}
}

View File

@ -54,7 +54,7 @@ public class FindMD5InList implements ContainsValueInListStrategy {
try {
byte[] toSearch = objectMD5.apply(value);
for (BlobMetadata metadata : getAllBlobMetadata.execute(containerName, options)) {
if (Arrays.equals(toSearch, metadata.getContentMD5()))
if (Arrays.equals(toSearch, metadata.getContentMetadata().getContentMD5()))
return true;
}
return false;

View File

@ -54,7 +54,7 @@ public class MarkerFileMkdirStrategy implements MkdirStrategy {
public void execute(String containerName, String directory) {
Blob blob = connection.newBlob(directory + directorySuffix);
blob.setPayload(Payloads.newByteArrayPayload(new byte[] {}));
blob.getPayload().setContentType("application/directory");
blob.getPayload().getContentMetadata().setContentType("application/directory");
blob.getMetadata().setType(StorageType.RELATIVE_PATH);
connection.putBlob(containerName, blob);
}

View File

@ -65,7 +65,7 @@ public class MarkersGetDirectoryStrategy implements GetDirectoryStrategy {
public StorageMetadata execute(String containerName, String directory) {
BlobMetadata md = connection.blobMetadata(containerName, directory);
if (md != null && md.getContentType().equals("application/directory"))
if (md != null && md.getContentMetadata().getContentType().equals("application/directory"))
return resource2Directory.apply(md);
for (String suffix : BlobStoreConstants.DIRECTORY_SUFFIXES) {
md = connection.blobMetadata(containerName, directory + suffix);

View File

@ -48,8 +48,8 @@ public class MarkersIfDirectoryReturnNameStrategy implements IfDirectoryReturnNa
}
// It is important that this is last, in case there is a file with a known directory
// suffix who also has content type set to application/directory
if (blobMd.getContentType() != null
&& blobMd.getContentType().equals("application/directory"))
if (blobMd.getContentMetadata().getContentType() != null
&& blobMd.getContentMetadata().getContentType().equals("application/directory"))
return metadata.getName();
}
return null;

View File

@ -40,6 +40,7 @@ import org.jclouds.functions.ExceptionToValueOrPropagate;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.common.collect.ImmutableMultimap;
@ -79,8 +80,7 @@ public class BlobStoreUtils {
public static Blob newBlob(BlobStore blobStore, StorageMetadata blobMeta) {
Blob blob = blobStore.newBlob(blobMeta.getName());
if (blobMeta instanceof BlobMetadata) {
blob.getMetadata().setContentMD5(((BlobMetadata) blobMeta).getContentMD5());
blob.getMetadata().setContentType(((BlobMetadata) blobMeta).getContentType());
HttpUtils.copy(((BlobMetadata) blobMeta).getContentMetadata(), blob.getMetadata().getContentMetadata());
}
blob.getMetadata().setETag(blobMeta.getETag());
blob.getMetadata().setId(blobMeta.getProviderId());

View File

@ -109,14 +109,6 @@
(download-blob container-name name data-file)))
(finally (.delete data-file))))))
;; this will fail until somebody fixes it!
#_
(deftest sing-put-blob-request-test
(let [request (sign-put-blob-request "container" "path" "text/plain" 10)]
(is (= "PUT" (.getMethod request)))
(is (= "10" (get "Content-Length" (.getHeaders request))))
(is (= "text/plain" (get "Content-Type" (.getHeaders request))))))
;; this will fail until somebody fixes it!
#_
(deftest sing-blob-request-test

View File

@ -44,7 +44,7 @@ public class TransientBlobRequestSignerTest extends RestClientTest<TransientAsyn
private Factory blobFactory;
public void testSignGetBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
NoSuchMethodException, IOException {
NoSuchMethodException, IOException {
HttpRequest request = signer.signGetBlob("container", "name");
assertRequestLineEquals(request, "GET http://localhost/container/name HTTP/1.1");
@ -55,7 +55,7 @@ public class TransientBlobRequestSignerTest extends RestClientTest<TransientAsyn
}
public void testSignRemoveBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
NoSuchMethodException, IOException {
NoSuchMethodException, IOException {
HttpRequest request = signer.signRemoveBlob("container", "name");
assertRequestLineEquals(request, "DELETE http://localhost/container/name HTTP/1.1");
@ -66,18 +66,20 @@ public class TransientBlobRequestSignerTest extends RestClientTest<TransientAsyn
}
public void testSignPutBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
NoSuchMethodException, IOException {
NoSuchMethodException, IOException {
Blob blob = blobFactory.create(null);
blob.getMetadata().setName("name");
blob.setPayload(new PhantomPayload(2l, new byte[] { 0, 2, 4, 8 }));
blob.getPayload().setContentType("text/plain");
blob.setPayload(new PhantomPayload());
blob.getPayload().getContentMetadata().setContentLength(2l);
blob.getPayload().getContentMetadata().setContentMD5(new byte[] { 0, 2, 4, 8 });
blob.getPayload().getContentMetadata().setContentType("text/plain");
HttpRequest request = signer.signPutBlob("container", blob);
assertRequestLineEquals(request, "PUT http://localhost/container/name HTTP/1.1");
assertNonPayloadHeadersEqual(
request,
"Authorization: Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==\nContent-Length: 2\nContent-MD5: AAIECA==\nContent-Type: text/plain\n");
request,
"Authorization: Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==\nContent-Length: 2\nContent-MD5: AAIECA==\nContent-Type: text/plain\n");
assertContentHeadersEqual(request, "text/plain", null, null, null, (long) 2l, new byte[] { 0, 2, 4, 8 });
assertEquals(request.getFilters().size(), 0);

View File

@ -46,8 +46,8 @@ public class BindBlobToMultipartFormTest {
public static final Blob TEST_BLOB;
static {
blobProvider = new RestContextFactory().createContextBuilder("transient", "identity",
"credential").buildInjector().getInstance(Blob.Factory.class);
blobProvider = new RestContextFactory().createContextBuilder("transient", "identity", "credential")
.buildInjector().getInstance(Blob.Factory.class);
StringBuilder builder = new StringBuilder("--");
addData(BOUNDARY, "hello", builder);
builder.append("--").append(BOUNDARY).append("--").append("\r\n");
@ -55,7 +55,7 @@ public class BindBlobToMultipartFormTest {
TEST_BLOB = blobProvider.create(null);
TEST_BLOB.getMetadata().setName("hello");
TEST_BLOB.setPayload("hello");
TEST_BLOB.getMetadata().setContentType(MediaType.TEXT_PLAIN);
TEST_BLOB.getMetadata().getContentMetadata().setContentType(MediaType.TEXT_PLAIN);
}
public void testSinglePart() throws IOException {
@ -68,16 +68,15 @@ public class BindBlobToMultipartFormTest {
binder.bindToRequest(request, TEST_BLOB);
assertEquals(toStringAndClose(request.getPayload().getInput()), EXPECTS);
assertEquals(request.getPayload().getContentLength(), new Long(113));
assertEquals(request.getPayload().getContentMetadata().getContentLength(), new Long(113));
assertEquals(request.getPayload().getContentType(), "multipart/form-data; boundary="
assertEquals(request.getPayload().getContentMetadata().getContentType(), "multipart/form-data; boundary="
+ BOUNDARY);
}
private static void addData(String boundary, String data, StringBuilder builder) {
builder.append(boundary).append("\r\n");
builder.append("Content-Disposition").append(": ").append("form-data; name=\"hello\"")
.append("\r\n");
builder.append("Content-Disposition").append(": ").append("form-data; name=\"hello\"").append("\r\n");
builder.append("Content-Type").append(": ").append("text/plain").append("\r\n");
builder.append("\r\n");
builder.append(data).append("\r\n");

View File

@ -79,8 +79,8 @@ public class ParseBlobFromHeadersAndHttpContentTest {
metadataParser, blobProvider);
HttpResponse response = new HttpResponse(200, "ok", Payloads.newStringPayload(""));
response.getPayload().setContentType(MediaType.APPLICATION_JSON);
response.getPayload().setContentLength(10485760l);
response.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_JSON);
response.getPayload().getContentMetadata().setContentLength(10485760l);
response.getHeaders().put("Content-Range", "0-10485759/20232760");
MutableBlobMetadata meta = blobMetadataProvider.get();
@ -88,8 +88,7 @@ public class ParseBlobFromHeadersAndHttpContentTest {
replay(metadataParser);
Blob object = callable.apply(response);
assertEquals(object.getPayload().getContentLength(), new Long(10485760));
assertEquals(object.getMetadata().getSize(), null);// TODO
assertEquals(object.getPayload().getContentMetadata().getContentLength(), new Long(10485760));
assertEquals(object.getAllHeaders().get("Content-Range"), Collections
.singletonList("0-10485759/20232760"));

View File

@ -63,7 +63,7 @@ public class ParseSystemAndUserMetadataFromHeadersTest {
void setUp() {
parser = new ParseSystemAndUserMetadataFromHeaders(blobMetadataProvider, new SimpleDateFormatDateService(),
"prefix", "default");
"prefix", "default");
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
@ -75,9 +75,9 @@ public class ParseSystemAndUserMetadataFromHeadersTest {
@Test
public void testApplySetsKey() {
HttpResponse from = new HttpResponse(200, "ok", Payloads.newStringPayload(""));
from.getPayload().setContentType(MediaType.APPLICATION_JSON);
from.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_JSON);
from.getHeaders().put(HttpHeaders.LAST_MODIFIED, "Wed, 09 Sep 2009 19:50:23 GMT");
from.getPayload().setContentLength(100l);
from.getPayload().getContentMetadata().setContentLength(100l);
BlobMetadata metadata = parser.apply(from);
assertEquals(metadata.getName(), "key");
}
@ -89,38 +89,6 @@ public class ParseSystemAndUserMetadataFromHeadersTest {
parser.apply(from);
}
@Test
public void testSetContentLength() {
HttpResponse from = new HttpResponse(200, "ok", Payloads.newStringPayload(""));
from.getPayload().setContentLength(100l);
MutableBlobMetadata metadata = blobMetadataProvider.get();
parser.setContentLength(from, metadata);
assertEquals(metadata.getSize(), new Long(100));
}
public void testSetContentLengthNoHeader() {
HttpResponse from = new HttpResponse(200, "ok", Payloads.newStringPayload(""));
MutableBlobMetadata metadata = blobMetadataProvider.get();
parser.setContentLength(from, metadata);
assertEquals(metadata.getSize(), new Long(0));
}
@Test
public void testSetContentType() {
HttpResponse from = new HttpResponse(200, "ok", Payloads.newStringPayload(""));
from.getPayload().setContentType(MediaType.APPLICATION_JSON);
MutableBlobMetadata metadata = blobMetadataProvider.get();
parser.setContentTypeOrThrowException(from, metadata);
assertEquals(metadata.getContentType(), MediaType.APPLICATION_JSON);
}
@Test(expectedExceptions = HttpException.class)
public void testSetContentTypeException() {
HttpResponse from = new HttpResponse(200, "ok", Payloads.newStringPayload(""));
MutableBlobMetadata metadata = blobMetadataProvider.get();
parser.setContentTypeOrThrowException(from, metadata);
}
@Test
public void testSetLastModified() {
HttpResponse from = new HttpResponse(200, "ok", Payloads.newStringPayload(""));
@ -128,7 +96,7 @@ public class ParseSystemAndUserMetadataFromHeadersTest {
MutableBlobMetadata metadata = blobMetadataProvider.get();
parser.parseLastModifiedOrThrowException(from, metadata);
assertEquals(metadata.getLastModified(), new SimpleDateFormatDateService()
.rfc822DateParse("Wed, 09 Sep 2009 19:50:23 GMT"));
.rfc822DateParse("Wed, 09 Sep 2009 19:50:23 GMT"));
}
@Test(expectedExceptions = HttpException.class)

View File

@ -47,8 +47,7 @@ public class TransientContainerIntegrationTest extends BaseContainerIntegrationT
Blob object = context.getBlobStore().newBlob(key);
object.setPayload(TEST_STRING);
object.getMetadata().setContentType(MediaType.TEXT_PLAIN);
object.getMetadata().setSize(new Long(TEST_STRING.length()));
object.getMetadata().getContentMetadata().setContentType(MediaType.TEXT_PLAIN);
// NOTE all metadata in jclouds comes out as lowercase, in an effort to normalize the
// providers.
object.getMetadata().getUserMetadata().put("Adrian", "powderpuff");

View File

@ -97,7 +97,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
@SuppressWarnings("unchecked")
public static InputSupplier<InputStream> getTestDataSupplier() throws IOException {
byte[] oneConstitution = ByteStreams.toByteArray(new GZIPInputStream(BaseJettyTest.class
.getResourceAsStream("/const.txt.gz")));
.getResourceAsStream("/const.txt.gz")));
InputSupplier<ByteArrayInputStream> constitutionSupplier = ByteStreams.newInputStreamSupplier(oneConstitution);
InputSupplier<InputStream> temp = ByteStreams.join(constitutionSupplier);
@ -120,23 +120,23 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
for (int i = 0; i < 10; i++) {
responses.put(i, Futures.compose(context.getAsyncBlobStore().getBlob(containerName, key),
new Function<Blob, Void>() {
new Function<Blob, Void>() {
@Override
public Void apply(Blob from) {
try {
assertEquals(CryptoStreams.md5(from.getPayload()), oneHundredOneConstitutionsMD5);
checkContentDispostion(from, expectedContentDisposition);
} catch (IOException e) {
Throwables.propagate(e);
@Override
public Void apply(Blob from) {
try {
assertEquals(CryptoStreams.md5(from.getPayload()), oneHundredOneConstitutionsMD5);
checkContentDispostion(from, expectedContentDisposition);
} catch (IOException e) {
Throwables.propagate(e);
}
return null;
}
return null;
}
}, this.exec));
}, this.exec));
}
Map<Integer, Exception> exceptions = awaitCompletion(responses, exec, 30000l, Logger.CONSOLE,
"get constitution");
"get constitution");
assert exceptions.size() == 0 : exceptions;
} finally {
@ -147,23 +147,22 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
private void uploadConstitution(String containerName, String key, String contentDisposition) throws IOException {
Blob sourceObject = context.getBlobStore().newBlob(key);
sourceObject.getMetadata().setContentType("text/plain");
sourceObject.getMetadata().setContentMD5(oneHundredOneConstitutionsMD5);
sourceObject.getMetadata().setContentDisposition(contentDisposition);
sourceObject.setPayload(oneHundredOneConstitutions.getInput());
sourceObject.getMetadata().getContentMetadata().setContentType("text/plain");
sourceObject.getMetadata().getContentMetadata().setContentMD5(oneHundredOneConstitutionsMD5);
sourceObject.getMetadata().getContentMetadata().setContentDisposition(contentDisposition);
context.getBlobStore().putBlob(containerName, sourceObject);
}
/**
* Methods for checking Content-Disposition. In this way, in implementations
* that do not support the new field, it is easy to override with empty, and
* allow the rest of the test to work.
* Methods for checking Content-Disposition. In this way, in implementations that do not support
* the new field, it is easy to override with empty, and allow the rest of the test to work.
*
* @param blob
* @param expected
*/
protected void checkContentDispostion(Blob blob, String expected) {
assertEquals(blob.getPayload().getContentDisposition(), expected);
assertEquals(blob.getPayload().getContentMetadata().getContentDisposition(), expected);
}
@Test(groups = { "integration", "live" })
@ -374,8 +373,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
@DataProvider(name = "delete")
public Object[][] createData() {
return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" },
{ "colon:" }, { "asteri*k" }, { "quote\"" }, { "{great<r}" }, { "lesst>en" }, { "p|pe" } };
return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" }, { "colon:" },
{ "asteri*k" }, { "quote\"" }, { "{great<r}" }, { "lesst>en" }, { "p|pe" } };
}
@Test(groups = { "integration", "live" }, dataProvider = "delete")
@ -392,17 +391,17 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
private void assertContainerEmptyDeleting(String containerName, String key) {
Iterable<? extends StorageMetadata> listing = Iterables.filter(context.getBlobStore().list(containerName),
new Predicate<StorageMetadata>() {
new Predicate<StorageMetadata>() {
@Override
public boolean apply(StorageMetadata input) {
return input.getType() == StorageType.BLOB;
}
@Override
public boolean apply(StorageMetadata input) {
return input.getType() == StorageType.BLOB;
}
});
});
assertEquals(Iterables.size(listing), 0, String.format(
"deleting %s, we still have %s blobs left in container %s, using encoding %s", key,
Iterables.size(listing), containerName, LOCAL_ENCODING));
"deleting %s, we still have %s blobs left in container %s, using encoding %s", key, Iterables
.size(listing), containerName, LOCAL_ENCODING));
}
@Test(groups = { "integration", "live" })
@ -422,16 +421,18 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
String realObject = Utils.toStringAndClose(new FileInputStream("pom.xml"));
return new Object[][] { { "file", "text/xml", new File("pom.xml"), realObject },
{ "string", "text/xml", realObject, realObject },
{ "bytes", "application/octet-stream", realObject.getBytes(), realObject } };
{ "string", "text/xml", realObject, realObject },
{ "bytes", "application/octet-stream", realObject.getBytes(), realObject } };
}
@Test(groups = { "integration", "live" }, dataProvider = "putTests")
public void testPutObject(String key, String type, Object content, Object realObject) throws InterruptedException,
IOException {
IOException {
Blob blob = context.getBlobStore().newBlob(key);
blob.getMetadata().setContentType(type);
blob.setPayload(Payloads.newPayload(content));
blob.getMetadata().getContentMetadata().setContentType(type);
addContentMetadata(blob);
if (content instanceof InputStream) {
Payloads.calculateMD5(blob, context.utils().crypto().md5());
}
@ -439,6 +440,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
try {
assertNotNull(context.getBlobStore().putBlob(containerName, blob));
blob = context.getBlobStore().getBlob(containerName, blob.getMetadata().getName());
checkContentMetadata(blob);
String returnedString = getContentAsStringOrNullAndClose(blob);
assertEquals(returnedString, realObject);
PageSet<? extends StorageMetadata> set = context.getBlobStore().list(containerName);
@ -457,10 +460,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
outstream.write("foo".getBytes());
}
}));
blob.getMetadata().setContentType("text/csv");
blob.getMetadata().setContentDisposition("attachment; filename=photo.jpg");
blob.getMetadata().setContentEncoding("gzip");
blob.getMetadata().setContentLanguage("en");
addContentMetadata(blob);
String containerName = getContainerName();
try {
@ -470,10 +470,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
blob = context.getBlobStore().getBlob(containerName, blob.getMetadata().getName());
String returnedString = getContentAsStringOrNullAndClose(blob);
assertEquals(returnedString, "foo");
checkContentType(blob, "text/csv");
checkContentDisposition(blob, "attachment; filename=photo.jpg");
checkContentEncoding(blob, "gzip");
checkContentLanguage(blob, "en");
checkContentMetadata(blob);
PageSet<? extends StorageMetadata> set = context.getBlobStore().list(containerName);
assert set.size() == 1 : set;
} finally {
@ -481,38 +478,51 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
}
}
private void checkContentMetadata(Blob blob) {
checkContentType(blob, "text/csv");
checkContentDisposition(blob, "attachment; filename=photo.jpg");
checkContentEncoding(blob, "gzip");
checkContentLanguage(blob, "en");
}
private void addContentMetadata(Blob blob) {
blob.getMetadata().getContentMetadata().setContentType("text/csv");
blob.getMetadata().getContentMetadata().setContentDisposition("attachment; filename=photo.jpg");
blob.getMetadata().getContentMetadata().setContentEncoding("gzip");
blob.getMetadata().getContentMetadata().setContentLanguage("en");
}
protected void checkContentType(Blob blob, String contentType) {
assert blob.getPayload().getContentType().startsWith(contentType) : blob.getPayload().getContentType();
assert blob.getMetadata().getContentType().startsWith(contentType) : blob.getMetadata().getContentType();
assert blob.getPayload().getContentMetadata().getContentType().startsWith(contentType) : blob.getPayload()
.getContentMetadata().getContentType();
assert blob.getMetadata().getContentMetadata().getContentType().startsWith(contentType) : blob.getMetadata()
.getContentMetadata().getContentType();
assert Iterables.getOnlyElement(blob.getAllHeaders().get(HttpHeaders.CONTENT_TYPE)).startsWith(contentType) : blob
.getAllHeaders().get(HttpHeaders.CONTENT_TYPE);
.getAllHeaders().get(HttpHeaders.CONTENT_TYPE);
}
protected void checkContentDisposition(Blob blob, String contentDisposition) {
assert blob.getPayload().getContentDisposition().startsWith(contentDisposition) : blob.getPayload()
.getContentDisposition();
assert blob.getMetadata().getContentDisposition().startsWith(contentDisposition) : blob.getMetadata()
.getContentDisposition();
assert Iterables.getOnlyElement(blob.getAllHeaders().get("Content-Disposition")).startsWith(contentDisposition) : blob
.getAllHeaders().get("Content-Disposition");
assert blob.getPayload().getContentMetadata().getContentDisposition().startsWith(contentDisposition) : blob
.getPayload().getContentMetadata().getContentDisposition();
assert blob.getMetadata().getContentMetadata().getContentDisposition().startsWith(contentDisposition) : blob
.getMetadata().getContentMetadata().getContentDisposition();
}
protected void checkContentEncoding(Blob blob, String contentEncoding) {
assert blob.getPayload().getContentEncoding().startsWith(contentEncoding) : blob.getPayload()
.getContentEncoding();
assert blob.getMetadata().getContentEncoding().startsWith(contentEncoding) : blob.getMetadata()
.getContentEncoding();
assert Iterables.getOnlyElement(blob.getAllHeaders().get(HttpHeaders.CONTENT_ENCODING)).startsWith(
contentEncoding) : blob.getAllHeaders().get(HttpHeaders.CONTENT_ENCODING);
assert blob.getPayload().getContentMetadata().getContentEncoding().startsWith(contentEncoding) : blob
.getPayload().getContentMetadata().getContentEncoding();
assert blob.getMetadata().getContentMetadata().getContentEncoding().startsWith(contentEncoding) : blob
.getMetadata().getContentMetadata().getContentEncoding();
}
protected void checkContentLanguage(Blob blob, String contentLanguage) {
assert blob.getPayload().getContentLanguage().startsWith(contentLanguage) : blob.getPayload()
.getContentLanguage();
assert blob.getMetadata().getContentLanguage().startsWith(contentLanguage) : blob.getMetadata()
.getContentLanguage();
assert Iterables.getOnlyElement(blob.getAllHeaders().get(HttpHeaders.CONTENT_LANGUAGE)).startsWith(
contentLanguage) : blob.getAllHeaders().get(HttpHeaders.CONTENT_LANGUAGE);
assert blob.getPayload().getContentMetadata().getContentLanguage().startsWith(contentLanguage) : blob
.getPayload().getContentMetadata().getContentLanguage();
assert blob.getMetadata().getContentMetadata().getContentLanguage().startsWith(contentLanguage) : blob
.getMetadata().getContentMetadata().getContentLanguage();
}
protected volatile static Crypto crypto;
@ -532,8 +542,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
Blob blob = context.getBlobStore().newBlob(key);
blob.setPayload(TEST_STRING);
blob.getMetadata().setContentType(MediaType.TEXT_PLAIN);
blob.getMetadata().setSize(new Long(TEST_STRING.length()));
blob.getMetadata().getContentMetadata().setContentType(MediaType.TEXT_PLAIN);
// NOTE all metadata in jclouds comes out as lowercase, in an effort to
// normalize the
// providers.
@ -565,10 +574,11 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
}
protected void validateMetadata(BlobMetadata metadata) throws IOException {
assert metadata.getContentType().startsWith("text/plain") : metadata.getContentType();
assertEquals(metadata.getSize(), new Long(TEST_STRING.length()));
assert metadata.getContentMetadata().getContentType().startsWith("text/plain") : metadata.getContentMetadata()
.getContentType();
assertEquals(metadata.getContentMetadata().getContentLength(), new Long(TEST_STRING.length()));
assertEquals(metadata.getUserMetadata().get("adrian"), "powderpuff");
assertEquals(metadata.getContentMD5(), CryptoStreams.md5(InputSuppliers.of(TEST_STRING)));
assertEquals(metadata.getContentMetadata().getContentMD5(), CryptoStreams.md5(InputSuppliers.of(TEST_STRING)));
}
}

View File

@ -63,12 +63,12 @@ public class BaseBlobLiveTest extends BaseBlobStoreIntegrationTest {
Blob blob = context.getBlobStore().newBlob(name);
blob.setPayload(input);
blob.getPayload().setContentLength(length);
blob.getPayload().setContentMD5(md5);
blob.getPayload().getContentMetadata().setContentLength(length);
blob.getPayload().getContentMetadata().setContentMD5(md5);
String container = getContainerName();
try {
context.getBlobStore().putBlob(container, blob);
assertEquals(context.getBlobStore().blobMetadata(container, name).getContentMD5(), md5);
assertEquals(context.getBlobStore().blobMetadata(container, name).getContentMetadata().getContentMD5(), md5);
} finally {
returnContainer(container);
}

View File

@ -197,7 +197,7 @@ public abstract class BaseBlobMapIntegrationTest extends BaseMapIntegrationTest<
for (String key : fiveInputs.keySet()) {
Blob blob = context.getBlobStore().newBlob(key);
blob.setPayload(fiveInputs.get(key));
blob.getPayload().setContentLength((long) fiveBytes.get(key).length);
blob.getPayload().getContentMetadata().setContentLength((long) fiveBytes.get(key).length);
newMap.put(key, blob);
}
map.putAll(newMap);

View File

@ -43,7 +43,7 @@ public class BaseBlobSignerLiveTest extends BaseBlobStoreIntegrationTest {
Blob blob = context.getBlobStore().newBlob(name);
blob.setPayload(text);
blob.getPayload().setContentType("text/plain");
blob.getPayload().getContentMetadata().setContentType("text/plain");
String container = getContainerName();
try {
context.getBlobStore().putBlob(container, blob);
@ -63,7 +63,7 @@ public class BaseBlobSignerLiveTest extends BaseBlobStoreIntegrationTest {
Blob blob = context.getBlobStore().newBlob(name);
blob.setPayload(text);
blob.getPayload().setContentType("text/plain");
blob.getPayload().getContentMetadata().setContentType("text/plain");
String container = getContainerName();
try {
context.getBlobStore().putBlob(container, blob);
@ -82,7 +82,7 @@ public class BaseBlobSignerLiveTest extends BaseBlobStoreIntegrationTest {
Blob blob = context.getBlobStore().newBlob(name);
blob.setPayload(text);
blob.getPayload().setContentType("text/plain");
blob.getPayload().getContentMetadata().setContentType("text/plain");
String container = getContainerName();
try {
HttpRequest request = context.getSigner().signPutBlob(container, blob);

View File

@ -240,15 +240,15 @@ public class BaseBlobStoreIntegrationTest {
protected String addBlobToContainer(String sourceContainer, String key) {
Blob sourceObject = context.getBlobStore().newBlob(key);
sourceObject.setPayload(TEST_STRING);
sourceObject.getMetadata().setContentType("text/xml");
sourceObject.getMetadata().getContentMetadata().setContentType("text/xml");
return addBlobToContainer(sourceContainer, sourceObject);
}
protected void add5BlobsUnderPathAnd5UnderRootToContainer(String sourceContainer) {
for (Entry<String, String> entry : Iterables.concat(fiveStrings.entrySet(), fiveStringsUnderPath.entrySet())) {
Blob sourceObject = context.getBlobStore().newBlob(entry.getKey());
sourceObject.getMetadata().setContentType("text/xml");
sourceObject.setPayload(entry.getValue());
sourceObject.getMetadata().getContentMetadata().setContentType("text/xml");
addBlobToContainer(sourceContainer, sourceObject);
}
}

View File

@ -77,8 +77,7 @@ public class BaseContainerIntegrationTest extends BaseBlobStoreIntegrationTest {
Blob object = context.getBlobStore().newBlob(key);
object.setPayload(TEST_STRING);
object.getMetadata().setContentType(MediaType.TEXT_PLAIN);
object.getMetadata().setSize(new Long(TEST_STRING.length()));
object.getMetadata().getContentMetadata().setContentType(MediaType.TEXT_PLAIN);
// NOTE all metadata in jclouds comes out as lowercase, in an effort to
// normalize the
// providers.
@ -94,10 +93,10 @@ public class BaseContainerIntegrationTest extends BaseBlobStoreIntegrationTest {
BlobMetadata metadata = BlobMetadata.class.cast(get(container, 0));
assert metadata.getContentType().startsWith("text/plain") : metadata.getContentType();
assertEquals(metadata.getSize(), new Long(TEST_STRING.length()));
assert metadata.getContentMetadata().getContentType().startsWith("text/plain") : metadata.getContentMetadata().getContentType();
assertEquals(metadata.getContentMetadata().getContentLength(), new Long(TEST_STRING.length()));
assertEquals(metadata.getUserMetadata().get("adrian"), "powderpuff");
assertEquals(metadata.getContentMD5(), CryptoStreams.md5(InputSuppliers.of(TEST_STRING)));
assertEquals(metadata.getContentMetadata().getContentMD5(), CryptoStreams.md5(InputSuppliers.of(TEST_STRING)));
} finally {
returnContainer(containerName);
}

View File

@ -257,7 +257,7 @@ public class TemplateOptions {
checkArgument(checkNotNull(privateKey, "privateKey").startsWith("-----BEGIN RSA PRIVATE KEY-----"),
"key should start with -----BEGIN RSA PRIVATE KEY-----");
Payload payload = newStringPayload(privateKey);
payload.setContentType("text/plain");
payload.getContentMetadata().setContentType("text/plain");
return installPrivateKey(payload);
}
@ -300,7 +300,7 @@ public class TemplateOptions {
public TemplateOptions authorizePublicKey(String publicKey) {
checkArgument(checkNotNull(publicKey, "publicKey").startsWith("ssh-rsa"), "key should start with ssh-rsa");
Payload payload = newStringPayload(publicKey);
payload.setContentType("text/plain");
payload.getContentMetadata().setContentType("text/plain");
return authorizePublicKey(payload);
}

View File

@ -32,6 +32,8 @@ import static com.google.common.collect.Sets.newTreeSet;
import static com.google.common.io.ByteStreams.toByteArray;
import static com.google.common.io.Closeables.closeQuietly;
import static java.util.Collections.singletonList;
import static javax.ws.rs.core.HttpHeaders.CONTENT_ENCODING;
import static javax.ws.rs.core.HttpHeaders.CONTENT_LANGUAGE;
import static javax.ws.rs.core.HttpHeaders.CONTENT_LENGTH;
import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE;
import static javax.ws.rs.core.HttpHeaders.HOST;
@ -52,6 +54,7 @@ import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
@ -69,7 +72,9 @@ import javax.ws.rs.core.UriBuilder;
import org.jclouds.Constants;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.io.ContentMetadata;
import org.jclouds.io.InputSuppliers;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.Payload;
import org.jclouds.io.PayloadEnclosing;
import org.jclouds.io.Payloads;
@ -200,6 +205,21 @@ public class HttpUtils {
}
}
public static void addContentHeadersFromMetadata(ContentMetadata md, Multimap<String, String> allHeaders) {
if (md.getContentType() != null)
allHeaders.replaceValues(HttpHeaders.CONTENT_TYPE, Collections.singleton(md.getContentType()));
if (md.getContentDisposition() != null)
allHeaders.replaceValues("Content-Disposition", Collections.singleton(md.getContentDisposition()));
if (md.getContentEncoding() != null)
allHeaders.replaceValues(HttpHeaders.CONTENT_ENCODING, Collections.singleton(md.getContentEncoding()));
if (md.getContentEncoding() != null)
allHeaders.replaceValues(HttpHeaders.CONTENT_LANGUAGE, Collections.singleton(md.getContentLanguage()));
if (md.getContentLength() != null)
allHeaders.replaceValues(HttpHeaders.CONTENT_LENGTH, Collections.singleton(md.getContentLength() + ""));
if (md.getContentMD5() != null)
allHeaders.replaceValues("Content-MD5", Collections.singleton(CryptoStreams.base64(md.getContentMD5())));
}
/**
* Web browsers do not always handle '+' characters well, use the well-supported '%20' instead.
*/
@ -255,13 +275,23 @@ public class HttpUtils {
byte[] returnVal = toByteArrayOrNull(response);
if (returnVal != null && !response.getPayload().isRepeatable()) {
Payload newPayload = Payloads.newByteArrayPayload(returnVal);
newPayload.setContentMD5(response.getPayload().getContentMD5());
newPayload.setContentType(response.getPayload().getContentType());
MutableContentMetadata fromMd = response.getPayload().getContentMetadata();
MutableContentMetadata toMd = newPayload.getContentMetadata();
copy(fromMd, toMd);
response.setPayload(newPayload);
}
return returnVal;
}
public static void copy(ContentMetadata fromMd, MutableContentMetadata toMd) {
toMd.setContentLength(fromMd.getContentLength());
toMd.setContentMD5(fromMd.getContentMD5());
toMd.setContentType(fromMd.getContentType());
toMd.setContentDisposition(fromMd.getContentDisposition());
toMd.setContentEncoding(fromMd.getContentEncoding());
toMd.setContentLanguage(fromMd.getContentLanguage());
}
public static URI parseEndPoint(String hostHeader) {
URI redirectURI = URI.create(hostHeader);
String scheme = redirectURI.getScheme();
@ -338,17 +368,27 @@ public class HttpUtils {
logger.debug("%s %s: %s", prefix, header.getKey(), header.getValue());
}
if (message.getPayload() != null) {
if (message.getPayload().getContentType() != null)
logger.debug("%s %s: %s", prefix, HttpHeaders.CONTENT_TYPE, message.getPayload().getContentType());
if (message.getPayload().getContentLength() != null)
logger.debug("%s %s: %s", prefix, HttpHeaders.CONTENT_LENGTH, message.getPayload().getContentLength());
if (message.getPayload().getContentMD5() != null)
if (message.getPayload().getContentMetadata().getContentType() != null)
logger.debug("%s %s: %s", prefix, CONTENT_TYPE, message.getPayload().getContentMetadata().getContentType());
if (message.getPayload().getContentMetadata().getContentLength() != null)
logger.debug("%s %s: %s", prefix, CONTENT_LENGTH, message.getPayload().getContentMetadata()
.getContentLength());
if (message.getPayload().getContentMetadata().getContentMD5() != null)
try {
logger.debug("%s %s: %s", prefix, "Content-MD5", CryptoStreams.base64Encode(InputSuppliers.of(message
.getPayload().getContentMD5())));
.getPayload().getContentMetadata().getContentMD5())));
} catch (IOException e) {
logger.warn(e, " error getting md5 for %s", message);
}
if (message.getPayload().getContentMetadata().getContentDisposition() != null)
logger.debug("%s %s: %s", prefix, "Content-Disposition", message.getPayload().getContentMetadata()
.getContentDisposition());
if (message.getPayload().getContentMetadata().getContentEncoding() != null)
logger.debug("%s %s: %s", prefix, CONTENT_ENCODING, message.getPayload().getContentMetadata()
.getContentEncoding());
if (message.getPayload().getContentMetadata().getContentLanguage() != null)
logger.debug("%s %s: %s", prefix, CONTENT_LANGUAGE, message.getPayload().getContentMetadata()
.getContentLanguage());
}
}
@ -503,16 +543,22 @@ public class HttpUtils {
for (Entry<String, String> header : headers.entries()) {
if (!chunked && CONTENT_LENGTH.equalsIgnoreCase(header.getKey())) {
if (payload != null)
payload.setContentLength(new Long(header.getValue()));
payload.getContentMetadata().setContentLength(new Long(header.getValue()));
} else if ("Content-MD5".equalsIgnoreCase(header.getKey())) {
if (payload != null)
payload.setContentMD5(CryptoStreams.base64(header.getValue()));
payload.getContentMetadata().setContentMD5(CryptoStreams.base64(header.getValue()));
} else if (CONTENT_TYPE.equalsIgnoreCase(header.getKey())) {
if (payload != null)
payload.setContentType(header.getValue());
payload.getContentMetadata().setContentType(header.getValue());
} else if ("Content-Disposition".equalsIgnoreCase(header.getKey())) {
if (payload != null)
payload.setContentDisposition(header.getValue());
payload.getContentMetadata().setContentDisposition(header.getValue());
} else if ("Content-Encoding".equalsIgnoreCase(header.getKey())) {
if (payload != null)
payload.getContentMetadata().setContentEncoding(header.getValue());
} else if ("Content-Language".equalsIgnoreCase(header.getKey())) {
if (payload != null)
payload.getContentMetadata().setContentLanguage(header.getValue());
} else {
message.getHeaders().put(header.getKey(), header.getValue());
}
@ -521,19 +567,34 @@ public class HttpUtils {
if (message instanceof HttpRequest) {
checkArgument(
message.getPayload() == null || message.getFirstHeaderOrNull(CONTENT_TYPE) == null,
"configuration error please use request.getPayload().setContentType(value) as opposed to adding a content type header: "
"configuration error please use request.getPayload().getContentMetadata().setContentType(value) as opposed to adding a content type header: "
+ message);
checkArgument(
message.getPayload() == null || message.getFirstHeaderOrNull(CONTENT_LENGTH) == null,
"configuration error please use request.getPayload().setContentLength(value) as opposed to adding a content length header: "
"configuration error please use request.getPayload().getContentMetadata().setContentLength(value) as opposed to adding a content length header: "
+ message);
checkArgument(message.getPayload() == null || message.getPayload().getContentLength() != null
checkArgument(message.getPayload() == null
|| message.getPayload().getContentMetadata().getContentLength() != null
|| "chunked".equalsIgnoreCase(message.getFirstHeaderOrNull("Transfer-Encoding")),
"either chunked encoding must be set on the http request or contentlength set on the payload: "
+ message);
checkArgument(message.getPayload() == null || message.getFirstHeaderOrNull("Content-MD5") == null,
"configuration error please use request.getPayload().setContentMD5(value) as opposed to adding a content md5 header: "
checkArgument(
message.getPayload() == null || message.getFirstHeaderOrNull("Content-MD5") == null,
"configuration error please use request.getPayload().getContentMetadata().setContentMD5(value) as opposed to adding a content md5 header: "
+ message);
checkArgument(
message.getPayload() == null || message.getFirstHeaderOrNull("Content-Disposition") == null,
"configuration error please use request.getPayload().getContentMetadata().setContentDisposition(value) as opposed to adding a content disposition header: "
+ message);
checkArgument(
message.getPayload() == null || message.getFirstHeaderOrNull(CONTENT_ENCODING) == null,
"configuration error please use request.getPayload().getContentMetadata().setContentEncoding(value) as opposed to adding a content encoding header: "
+ message);
checkArgument(
message.getPayload() == null || message.getFirstHeaderOrNull(CONTENT_LANGUAGE) == null,
"configuration error please use request.getPayload().getContentMetadata().setContentLanguage(value) as opposed to adding a content language header: "
+ message);
}
}
@ -557,7 +618,7 @@ public class HttpUtils {
public static Long attemptToParseSizeAndRangeFromHeaders(HttpResponse from) throws HttpException {
String contentRange = from.getFirstHeaderOrNull("Content-Range");
if (contentRange == null && from.getPayload() != null) {
return from.getPayload().getContentLength();
return from.getPayload().getContentMetadata().getContentLength();
} else if (contentRange != null) {
return Long.parseLong(contentRange.substring(contentRange.lastIndexOf('/') + 1));
}
@ -566,7 +627,8 @@ public class HttpUtils {
public static void checkRequestHasContentLengthOrChunkedEncoding(HttpRequest request, String message) {
boolean chunked = "chunked".equals(request.getFirstHeaderOrNull("Transfer-Encoding"));
checkArgument(request.getPayload() == null || chunked || request.getPayload().getContentLength() != null, message);
checkArgument(request.getPayload() == null || chunked
|| request.getPayload().getContentMetadata().getContentLength() != null, message);
}
public static void wirePayloadIfEnabled(Wire wire, HttpRequest request) {

View File

@ -33,8 +33,7 @@ import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
public class ParseContentMD5FromHeaders implements Function<HttpResponse, byte[]>,
InvocationContext {
public class ParseContentMD5FromHeaders implements Function<HttpResponse, byte[]>, InvocationContext {
public static class NoContentMD5Exception extends RuntimeException {
@ -65,7 +64,7 @@ public class ParseContentMD5FromHeaders implements Function<HttpResponse, byte[]
public byte[] apply(HttpResponse from) {
releasePayload(from);
if (from.getPayload() != null) {
return from.getPayload().getContentMD5();
return from.getPayload().getContentMetadata().getContentMD5();
}
throw new NoContentMD5Exception(request, from);
}

View File

@ -58,6 +58,7 @@ import org.jclouds.http.HttpUtils;
import org.jclouds.http.IOExceptionRetryHandler;
import org.jclouds.http.handlers.DelegatingErrorHandler;
import org.jclouds.http.handlers.DelegatingRetryHandler;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.Payload;
import org.jclouds.io.Payloads;
import org.jclouds.logging.Logger;
@ -197,20 +198,21 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
connection.setRequestProperty(HttpHeaders.USER_AGENT, USER_AGENT);
if (request.getPayload() != null) {
if (request.getPayload().getContentMD5() != null)
connection.setRequestProperty("Content-MD5", CryptoStreams.base64(request.getPayload().getContentMD5()));
if (request.getPayload().getContentType() != null)
connection.setRequestProperty(HttpHeaders.CONTENT_TYPE, request.getPayload().getContentType());
if (request.getPayload().getContentDisposition() != null)
connection.setRequestProperty("Content-Disposition", request.getPayload().getContentDisposition());
if (request.getPayload().getContentEncoding() != null)
connection.setRequestProperty("Content-Encoding", request.getPayload().getContentEncoding());
if (request.getPayload().getContentLanguage() != null)
connection.setRequestProperty("Content-Language", request.getPayload().getContentLanguage());
MutableContentMetadata md = request.getPayload().getContentMetadata();
if (md.getContentMD5() != null)
connection.setRequestProperty("Content-MD5", CryptoStreams.base64(md.getContentMD5()));
if (md.getContentType() != null)
connection.setRequestProperty(HttpHeaders.CONTENT_TYPE, md.getContentType());
if (md.getContentDisposition() != null)
connection.setRequestProperty("Content-Disposition", md.getContentDisposition());
if (md.getContentEncoding() != null)
connection.setRequestProperty("Content-Encoding", md.getContentEncoding());
if (md.getContentLanguage() != null)
connection.setRequestProperty("Content-Language", md.getContentLanguage());
if (chunked) {
connection.setChunkedStreamingMode(8196);
} else {
Long length = checkNotNull(request.getPayload().getContentLength(), "payload.getContentLength");
Long length = checkNotNull(md.getContentLength(), "payload.getContentLength");
connection.setRequestProperty(HttpHeaders.CONTENT_LENGTH, length.toString());
connection.setFixedLengthStreamingMode(length.intValue());
}

View File

@ -0,0 +1,81 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.io;
import javax.annotation.Nullable;
/**
* @author Adrian Cole
*/
public interface ContentMetadata {
/**
* Returns the total size of the payload, or the chunk that's available.
* <p/>
* Chunking is only used when {@link 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 #getInput()}
* @see javax.ws.rs.core.HttpHeaders#CONTENT_LENGTH
* @see org.jclouds.http.options.GetOptions
*/
@Nullable
Long getContentLength();
/**
* Specifies presentational information for the object.
*
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html?sec19.5.1."/>
*/
@Nullable
String getContentDisposition();
/**
* Specifies what content encodings have been applied to the object and thus what decoding
* mechanisms must be applied in order to obtain the media-type referenced by the Content-Type
* header field.
*
* @see <a href= "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.11" />
*/
@Nullable
String getContentEncoding();
/**
*
* 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"/>
*/
@Nullable
String getContentType();
@Nullable
byte[] getContentMD5();
/**
* Get Content Language of the payload
* <p/>
* Not all providers may support it
*/
@Nullable
String getContentLanguage();
}

View File

@ -0,0 +1,62 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.io;
import javax.annotation.Nullable;
/**
* @author Adrian Cole
*/
public interface MutableContentMetadata extends ContentMetadata {
void setContentLength(@Nullable Long contentLength);
void setContentMD5(@Nullable byte[] md5);
void setContentType(@Nullable String md5);
/**
* Set Content Disposition of the payload
* <p/>
* Not all providers may support it
*
* @param contentDisposition
*/
void setContentDisposition(@Nullable String contentDisposition);
/**
* Set Content Language of the payload
* <p/>
* Not all providers may support it
*
* @param contentLanguage
*/
void setContentLanguage(@Nullable String contentLanguage);
/**
* Set Content Encoding of the payload
* <p/>
* Not all providers may support it
*
* @param contentEncoding
*/
void setContentEncoding(@Nullable String contentEncoding);
}

View File

@ -22,8 +22,6 @@ package org.jclouds.io;
import java.io.Closeable;
import java.io.InputStream;
import javax.annotation.Nullable;
import com.google.common.io.InputSupplier;
/**
@ -46,86 +44,13 @@ public interface Payload extends InputSupplier<InputStream>, WriteTo, Closeable
*/
boolean isRepeatable();
void setContentLength(@Nullable Long contentLength);
/**
* Returns the total size of the payload, or the chunk that's available.
* <p/>
* Chunking is only used when {@link 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 #getInput()}
* @see javax.ws.rs.core.HttpHeaders#CONTENT_LENGTH
* @see org.jclouds.http.options.GetOptions
*/
@Nullable
Long getContentLength();
void setContentMD5(@Nullable byte[] md5);
@Nullable
byte[] getContentMD5();
void setContentType(@Nullable String md5);
@Nullable
String getContentType();
/**
* Set Content Disposition of the payload
* <p/>
* Not all providers may support it
*
* @param contentDisposition
*/
void setContentDisposition(@Nullable String contentDisposition);
/**
* Get Content Disposition of the payload
* <p/>
* Not all providers may support it
*/
@Nullable
String getContentDisposition();
/**
* Set Content Language of the payload
* <p/>
* Not all providers may support it
*
* @param contentLanguage
*/
void setContentLanguage(@Nullable String contentLanguage);
/**
* Get Content Language of the payload
* <p/>
* Not all providers may support it
*/
@Nullable
String getContentLanguage();
/**
* Set Content Encoding of the payload
* <p/>
* Not all providers may support it
*
* @param contentEncoding
*/
void setContentEncoding(@Nullable String contentEncoding);
/**
* Get Content Encoding of the payload
* <p/>
* Not all providers may support it
*/
@Nullable
String getContentEncoding();
/**
* release resources used by this entity. This should be called when data is
* discarded.
* release resources used by this entity. This should be called when data is discarded.
*/
void release();
MutableContentMetadata getContentMetadata();
void setContentMetadata(MutableContentMetadata in);
}

View File

@ -109,16 +109,16 @@ public class Payloads {
public static Payload calculateMD5(Payload payload, MessageDigest md5) throws IOException {
checkNotNull(payload, "payload");
if (!payload.isRepeatable()) {
String oldContentType = payload.getContentType();
String oldContentType = payload.getContentMetadata().getContentType();
Payload oldPayload = payload;
try {
payload = newByteArrayPayload(toByteArray(payload));
} finally {
oldPayload.release();
}
payload.setContentType(oldContentType);
payload.getContentMetadata().setContentType(oldContentType);
}
payload.setContentMD5(CryptoStreams.digest(payload, md5));
payload.getContentMetadata().setContentMD5(CryptoStreams.digest(payload, md5));
return payload;
}

View File

@ -0,0 +1,164 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.io.payloads;
import java.io.Serializable;
import java.util.Arrays;
import org.jclouds.io.ContentMetadata;
/**
* @author Adrian Cole
*/
public class BaseImmutableContentMetadata implements ContentMetadata, Serializable {
/** The serialVersionUID */
private static final long serialVersionUID = -1445533440795766130L;
protected String contentType;
protected Long contentLength;
protected byte[] contentMD5;
protected String contentDisposition;
protected String contentLanguage;
protected String contentEncoding;
public BaseImmutableContentMetadata(String contentType, Long contentLength, byte[] contentMD5,
String contentDisposition, String contentLanguage, String contentEncoding) {
this.contentType = contentType;
this.contentLength = contentLength;
this.contentMD5 = contentMD5;
this.contentDisposition = contentDisposition;
this.contentLanguage = contentLanguage;
this.contentEncoding = contentEncoding;
}
/**
* {@inheritDoc}
*/
@Override
public Long getContentLength() {
return contentLength;
}
/**
* {@inheritDoc}
*/
@Override
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;
}
}
/**
* {@inheritDoc}
*/
@Override
public String getContentType() {
return contentType;
}
/**
* {@inheritDoc}
*/
@Override
public String getContentDisposition() {
return this.contentDisposition;
}
/**
* {@inheritDoc}
*/
@Override
public String getContentLanguage() {
return this.contentLanguage;
}
/**
* {@inheritDoc}
*/
@Override
public String getContentEncoding() {
return this.contentEncoding;
}
@Override
public String toString() {
return "[contentType=" + contentType + ", contentLength=" + contentLength + ", contentDisposition="
+ contentDisposition + ", contentEncoding=" + contentEncoding + ", contentLanguage=" + contentLanguage
+ ", contentMD5=" + Arrays.toString(contentMD5) + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((contentDisposition == null) ? 0 : contentDisposition.hashCode());
result = prime * result + ((contentEncoding == null) ? 0 : contentEncoding.hashCode());
result = prime * result + ((contentLanguage == null) ? 0 : contentLanguage.hashCode());
result = prime * result + ((contentLength == null) ? 0 : contentLength.hashCode());
result = prime * result + Arrays.hashCode(contentMD5);
result = prime * result + ((contentType == null) ? 0 : contentType.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;
BaseImmutableContentMetadata other = (BaseImmutableContentMetadata) obj;
if (contentDisposition == null) {
if (other.contentDisposition != null)
return false;
} else if (!contentDisposition.equals(other.contentDisposition))
return false;
if (contentEncoding == null) {
if (other.contentEncoding != null)
return false;
} else if (!contentEncoding.equals(other.contentEncoding))
return false;
if (contentLanguage == null) {
if (other.contentLanguage != null)
return false;
} else if (!contentLanguage.equals(other.contentLanguage))
return false;
if (contentLength == null) {
if (other.contentLength != null)
return false;
} else if (!contentLength.equals(other.contentLength))
return false;
if (!Arrays.equals(contentMD5, other.contentMD5))
return false;
if (contentType == null) {
if (other.contentType != null)
return false;
} else if (!contentType.equals(other.contentType))
return false;
return true;
}
}

Some files were not shown because too many files have changed in this diff Show More