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

View File

@ -33,9 +33,9 @@ import com.google.common.base.Function;
@Singleton @Singleton
public class BlobToSystemMetadata implements Function<BlobMetadata, SystemMetadata> { public class BlobToSystemMetadata implements Function<BlobMetadata, SystemMetadata> {
public SystemMetadata apply(BlobMetadata base) { public SystemMetadata apply(BlobMetadata base) {
return new SystemMetadata(base.getContentMD5(), null, base.getLastModified(), null, null, return new SystemMetadata(base.getContentMetadata().getContentMD5(), null, base.getLastModified(), null, null,
null, 1, null, base.getName(), null, (base.getSize() != null) ? base.getSize() : 0, null, 1, null, base.getName(), null, (base.getContentMetadata().getContentLength() != null) ? base
FileType.REGULAR, "root"); .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.PageSetImpl;
import org.jclouds.blobstore.domain.internal.StorageMetadataImpl; import org.jclouds.blobstore.domain.internal.StorageMetadataImpl;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.io.payloads.BaseMutableContentMetadata;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
@ -59,11 +60,11 @@ public class DirectoryEntryListToResourceMetadataList implements
public StorageMetadata apply(DirectoryEntry from) { public StorageMetadata apply(DirectoryEntry from) {
StorageType type = from.getType() == FileType.DIRECTORY ? StorageType.FOLDER : StorageType.BLOB; StorageType type = from.getType() == FileType.DIRECTORY ? StorageType.FOLDER : StorageType.BLOB;
if (type == StorageType.FOLDER) if (type == StorageType.FOLDER)
return new StorageMetadataImpl(type, from.getObjectID(), from.getObjectName(), defaultLocation.get(), return new StorageMetadataImpl(type, from.getObjectID(), from.getObjectName(), defaultLocation
null, null, null, null, Maps.<String, String> newHashMap()); .get(), null, null, null, Maps.<String, String> newHashMap());
else else
return new BlobMetadataImpl(from.getObjectID(), from.getObjectName(), defaultLocation.get(), null, return new BlobMetadataImpl(from.getObjectID(), from.getObjectName(), defaultLocation.get(),
null, null, null, Maps.<String, String> newHashMap(), null, null, null, null, null); null, null, null, Maps.<String, String> newHashMap(), new BaseMutableContentMetadata());
} }
}), from.getToken()); }), from.getToken());

View File

@ -27,6 +27,7 @@ import javax.inject.Singleton;
import org.jclouds.atmosonline.saas.domain.AtmosObject; import org.jclouds.atmosonline.saas.domain.AtmosObject;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.Blob.Factory; import org.jclouds.blobstore.domain.Blob.Factory;
import org.jclouds.http.HttpUtils;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -49,9 +50,7 @@ public class ObjectToBlob implements Function<AtmosObject, Blob> {
return null; return null;
Blob blob = blobFactory.create(object2BlobMd.apply(from)); Blob blob = blobFactory.create(object2BlobMd.apply(from));
blob.setPayload(checkNotNull(from.getPayload(), "payload: " + from)); blob.setPayload(checkNotNull(from.getPayload(), "payload: " + from));
if (from.getContentMetadata().getContentLength() != null) HttpUtils.copy(from.getContentMetadata(), blob.getPayload().getContentMetadata());
blob.getMetadata().setSize(from.getContentMetadata().getContentLength());
blob.getMetadata().setContentMD5(from.getSystemMetadata().getContentMD5());
blob.setAllHeaders(from.getAllHeaders()); blob.setAllHeaders(from.getAllHeaders());
return blob; 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.MutableBlobMetadata;
import org.jclouds.blobstore.domain.StorageType; import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl; import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.http.HttpUtils;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
@ -58,11 +59,8 @@ public class ObjectToBlobMetadata implements Function<AtmosObject, MutableBlobMe
MutableBlobMetadata to = new MutableBlobMetadataImpl(); MutableBlobMetadata to = new MutableBlobMetadataImpl();
to.setId(from.getSystemMetadata().getObjectID()); to.setId(from.getSystemMetadata().getObjectID());
to.setLastModified(from.getSystemMetadata().getLastUserDataModification()); to.setLastModified(from.getSystemMetadata().getLastUserDataModification());
to.setContentMD5(from.getSystemMetadata().getContentMD5()); HttpUtils.copy(from.getContentMetadata(), to.getContentMetadata());
if (from.getContentMetadata().getContentType() != null)
to.setContentType(from.getContentMetadata().getContentType());
to.setName(objectName.apply(from)); to.setName(objectName.apply(from));
to.setSize(from.getSystemMetadata().getSize());
if (from.getSystemMetadata().getType() == FileType.DIRECTORY) { if (from.getSystemMetadata().getType() == FileType.DIRECTORY) {
to.setType(StorageType.FOLDER); to.setType(StorageType.FOLDER);
} else { } else {

View File

@ -19,83 +19,20 @@
package org.jclouds.atmosonline.saas.domain; 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 * metadata of the object
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class MutableContentMetadata { @ImplementedBy(DelegatingMutableContentMetadata.class)
public interface MutableContentMetadata extends org.jclouds.io.MutableContentMetadata {
private String name; public String getName();
private Long contentLength;
private String contentType = MediaType.APPLICATION_OCTET_STREAM;
private byte[] contentMD5;
public String getName() { public void setName(String name);
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;
}
} }

View File

@ -29,8 +29,6 @@ import org.jclouds.atmosonline.saas.domain.SystemMetadata;
import org.jclouds.atmosonline.saas.domain.UserMetadata; import org.jclouds.atmosonline.saas.domain.UserMetadata;
import org.jclouds.http.internal.PayloadEnclosingImpl; import org.jclouds.http.internal.PayloadEnclosingImpl;
import org.jclouds.io.Payload; 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.LinkedHashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
@ -40,8 +38,7 @@ import com.google.common.collect.Multimap;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject, public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject, Comparable<AtmosObject> {
Comparable<AtmosObject> {
private final UserMetadata userMetadata; private final UserMetadata userMetadata;
private final SystemMetadata systemMetadata; private final SystemMetadata systemMetadata;
@ -53,15 +50,13 @@ public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject
return userMetadata; return userMetadata;
} }
private final MutableContentMetadata _contentMetadata; private MutableContentMetadata contentMetadata;
private final SetPayloadPropertiesMutableContentMetadata contentMetadata;
private Multimap<String, String> allHeaders = LinkedHashMultimap.create(); private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
public AtmosObjectImpl(MutableContentMetadata contentMetadata, SystemMetadata systemMetadata, public AtmosObjectImpl(MutableContentMetadata contentMetadata, SystemMetadata systemMetadata,
UserMetadata userMetadata) { UserMetadata userMetadata) {
super(); super();
this.contentMetadata = linkMetadataToThis(contentMetadata); this.contentMetadata = contentMetadata;
this._contentMetadata = this.contentMetadata.getDelegate();
this.systemMetadata = systemMetadata; this.systemMetadata = systemMetadata;
this.userMetadata = userMetadata; this.userMetadata = userMetadata;
} }
@ -102,15 +97,16 @@ public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject
public int compareTo(AtmosObject o) { public int compareTo(AtmosObject o) {
if (getContentMetadata().getName() == null) if (getContentMetadata().getName() == null)
return -1; return -1;
return (this == o) ? 0 : getContentMetadata().getName().compareTo( return (this == o) ? 0 : getContentMetadata().getName().compareTo(o.getContentMetadata().getName());
o.getContentMetadata().getName());
} }
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = super.hashCode(); 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; return result;
} }
@ -123,85 +119,32 @@ public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
AtmosObjectImpl other = (AtmosObjectImpl) obj; AtmosObjectImpl other = (AtmosObjectImpl) obj;
if (_contentMetadata == null) { if (contentMetadata == null) {
if (other._contentMetadata != null) if (other.contentMetadata != null)
return false; 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 false;
return true; return true;
} }
@Override @Override
public String toString() { public String toString() {
return "[contentMetadata=" + _contentMetadata + "]"; return "[contentMetadata=" + contentMetadata + "]";
} }
@Override @Override
public void setPayload(Payload data) { public void setPayload(Payload data) {
linkPayloadToMetadata(data); this.payload = data;
} this.contentMetadata = new DelegatingMutableContentMetadata(contentMetadata.getName(), payload.getContentMetadata());
/**
* 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;
}
} }
} }

View File

@ -20,15 +20,22 @@
package org.jclouds.atmosonline.saas.domain.internal; package org.jclouds.atmosonline.saas.domain.internal;
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata; import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
import org.jclouds.io.payloads.BaseMutableContentMetadata;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class DelegatingMutableContentMetadata extends MutableContentMetadata { public class DelegatingMutableContentMetadata implements MutableContentMetadata {
private final MutableContentMetadata delegate; 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; this.delegate = delegate;
} }
@ -49,7 +56,7 @@ public class DelegatingMutableContentMetadata extends MutableContentMetadata {
@Override @Override
public String getName() { public String getName() {
return delegate.getName(); return name;
} }
@Override @Override
@ -69,26 +76,78 @@ public class DelegatingMutableContentMetadata extends MutableContentMetadata {
@Override @Override
public void setName(String name) { public void setName(String name) {
delegate.setName(name); this.name = name;
} }
@Override @Override
public boolean equals(Object obj) { 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 @Override
public int hashCode() { 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 @Override
public String toString() { public String toString() {
return delegate.toString(); return "[name=" + name + ", delegate=" + delegate + "]";
} }
public MutableContentMetadata getDelegate() { public org.jclouds.io.MutableContentMetadata getDelegate() {
return delegate; 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) { 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"); .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.atmosonline.saas.xml.ErrorHandler;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.crypto.Crypto; import org.jclouds.crypto.Crypto;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
@ -72,8 +71,6 @@ public class AtmosStorageUtils {
String container, Blob blob) { String container, Blob blob) {
final String path = container + "/" + blob.getMetadata().getName(); final String path = container + "/" + blob.getMetadata().getName();
deleteAndEnsureGone(sync, path); 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)); sync.createFile(container, blob2Object.apply(blob));
return path; return path;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -52,7 +52,7 @@ public class BindBucketLoggingToXmlPayload implements Binder {
try { try {
String stringPayload = generateBuilder(from).asString(outputProperties); String stringPayload = generateBuilder(from).asString(outputProperties);
request.setPayload(stringPayload); request.setPayload(stringPayload);
request.getPayload().setContentType(MediaType.TEXT_XML); request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_XML);
} catch (Exception e) { } catch (Exception e) {
Throwables.propagateIfPossible(e); Throwables.propagateIfPossible(e);
throw new RuntimeException("error transforming bucketLogging: " + from, 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>", "<RequestPaymentConfiguration xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Payer>%s</Payer></RequestPaymentConfiguration>",
((Payer) toBind).value()); ((Payer) toBind).value());
request.setPayload(text); 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; package org.jclouds.aws.s3.binders;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -42,32 +41,21 @@ public class BindS3ObjectToPayload implements Binder {
private final ObjectToBlob object2Blob; private final ObjectToBlob object2Blob;
@Inject @Inject
public BindS3ObjectToPayload(ObjectToBlob object2Blob, public BindS3ObjectToPayload(ObjectToBlob object2Blob, BindUserMetadataToHeadersWithPrefix blobBinder) {
BindUserMetadataToHeadersWithPrefix blobBinder) {
this.blobBinder = blobBinder; this.blobBinder = blobBinder;
this.object2Blob = object2Blob; this.object2Blob = object2Blob;
} }
public void bindToRequest(HttpRequest request, Object payload) { public void bindToRequest(HttpRequest request, Object payload) {
S3Object s3Object = (S3Object) payload; S3Object s3Object = (S3Object) payload;
checkNotNull(s3Object.getPayload().getContentLength(), "contentLength"); checkArgument(s3Object.getPayload().getContentMetadata().getContentLength() != null,
checkArgument(s3Object.getPayload().getContentLength() <= 5l * 1024 * 1024 * 1024, "contentLength must be set, streaming not supported");
checkArgument(s3Object.getPayload().getContentMetadata().getContentLength() <= 5l * 1024 * 1024 * 1024,
"maximum size for put object is 5GB"); "maximum size for put object is 5GB");
blobBinder.bindToRequest(request, object2Blob.apply(s3Object)); blobBinder.bindToRequest(request, object2Blob.apply(s3Object));
if (s3Object.getMetadata().getCacheControl() != null) { if (s3Object.getMetadata().getCacheControl() != null) {
request.getHeaders().put(HttpHeaders.CACHE_CONTROL, request.getHeaders().put(HttpHeaders.CACHE_CONTROL, s3Object.getMetadata().getCacheControl());
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());
} }
} }

View File

@ -26,6 +26,7 @@ import javax.inject.Singleton;
import org.jclouds.aws.s3.domain.MutableObjectMetadata; import org.jclouds.aws.s3.domain.MutableObjectMetadata;
import org.jclouds.aws.s3.domain.internal.MutableObjectMetadataImpl; import org.jclouds.aws.s3.domain.internal.MutableObjectMetadataImpl;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.http.HttpUtils;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -38,18 +39,14 @@ public class BlobToObjectMetadata implements Function<BlobMetadata, MutableObjec
if (from == null) if (from == null)
return null; return null;
MutableObjectMetadata to = new MutableObjectMetadataImpl(); MutableObjectMetadata to = new MutableObjectMetadataImpl();
to.setContentType(from.getContentType()); HttpUtils.copy(from.getContentMetadata(), to.getContentMetadata());
to.setETag(from.getETag()); to.setETag(from.getETag());
to.setContentMD5(from.getContentMD5());
to.setKey(from.getName()); to.setKey(from.getName());
to.setLastModified(from.getLastModified()); to.setLastModified(from.getLastModified());
if (from.getSize() != null)
to.setSize(from.getSize());
if (from.getUserMetadata() != null) { if (from.getUserMetadata() != null) {
for (Entry<String, String> entry : from.getUserMetadata().entrySet()) for (Entry<String, String> entry : from.getUserMetadata().entrySet())
to.getUserMetadata().put(entry.getKey().toLowerCase(), entry.getValue()); to.getUserMetadata().put(entry.getKey().toLowerCase(), entry.getValue());
} }
return to; 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.StorageType;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl; import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy; import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy;
import org.jclouds.http.HttpUtils;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -46,13 +47,9 @@ public class ObjectToBlobMetadata implements Function<ObjectMetadata, MutableBlo
if (from == null) if (from == null)
return null; return null;
MutableBlobMetadata to = new MutableBlobMetadataImpl(); MutableBlobMetadata to = new MutableBlobMetadataImpl();
if (from.getContentMD5() != null) HttpUtils.copy(from.getContentMetadata(), to.getContentMetadata());
to.setContentMD5(from.getContentMD5());
if (from.getContentType() != null)
to.setContentType(from.getContentType());
to.setETag(from.getETag()); to.setETag(from.getETag());
to.setName(from.getKey()); to.setName(from.getKey());
to.setSize(from.getSize());
to.setLastModified(from.getLastModified()); to.setLastModified(from.getLastModified());
to.setUserMetadata(from.getUserMetadata()); to.setUserMetadata(from.getUserMetadata());
String directoryName = ifDirectoryReturnName.execute(to); String directoryName = ifDirectoryReturnName.execute(to);

View File

@ -23,6 +23,7 @@ import java.util.Date;
import java.util.Map; import java.util.Map;
import org.jclouds.aws.s3.domain.internal.MutableObjectMetadataImpl; import org.jclouds.aws.s3.domain.internal.MutableObjectMetadataImpl;
import org.jclouds.io.MutableContentMetadata;
import com.google.inject.ImplementedBy; import com.google.inject.ImplementedBy;
@ -68,47 +69,14 @@ public interface MutableObjectMetadata extends ObjectMetadata {
*/ */
void setCacheControl(String cacheControl); void setCacheControl(String cacheControl);
/** MutableContentMetadata getContentMetadata();
* 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);
/** void setContentMetadata(MutableContentMetadata md);
* 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 setLastModified(Date lastModified); void setLastModified(Date lastModified);
void setETag(String eTag); void setETag(String eTag);
void setSize(Long size);
void setUserMetadata(Map<String, String> userMetadata); 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.Date;
import java.util.Map; import java.util.Map;
import org.jclouds.io.ContentMetadata;
/** /**
* /** Amazon S3 is designed to store objects. Objects are stored in {@link S3BucketListing buckets} * /** Amazon S3 is designed to store objects. Objects are stored in {@link S3BucketListing buckets}
* and consist of a {@link org.jclouds.aws.s3.domain.S3Object#getData() value}, a * 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(); 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(); Date getLastModified();
String getETag(); String getETag();
Long getSize();
Map<String, String> getUserMetadata(); Map<String, String> getUserMetadata();
ContentMetadata getContentMetadata();
} }

View File

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

View File

@ -20,12 +20,13 @@
package org.jclouds.aws.s3.domain.internal; package org.jclouds.aws.s3.domain.internal;
import java.io.Serializable; import java.io.Serializable;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import org.jclouds.aws.s3.domain.CanonicalUser; import org.jclouds.aws.s3.domain.CanonicalUser;
import org.jclouds.aws.s3.domain.ObjectMetadata; 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 * Returns the metadata parsable from a bucket listing
@ -40,28 +41,20 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
private final String key; private final String key;
private final Date lastModified; private final Date lastModified;
private final String eTag; private final String eTag;
private final Long size;
private final CanonicalUser owner; private final CanonicalUser owner;
private final StorageClass storageClass; private final StorageClass storageClass;
private final String contentType;
private final byte[] contentMD5;
private final String cacheControl; private final String cacheControl;
private final String contentDisposition;
private final String contentEncoding;
private final Map<String, String> userMetadata; private final Map<String, String> userMetadata;
private final BaseImmutableContentMetadata contentMetadata;
public CopyObjectResult(Date lastModified, String eTag) { public CopyObjectResult(Date lastModified, String eTag) {
this.key = null; this.key = null;
this.lastModified = lastModified; this.lastModified = lastModified;
this.eTag = eTag; this.eTag = eTag;
this.size = null;
this.owner = null; this.owner = null;
this.storageClass = StorageClass.STANDARD; this.storageClass = StorageClass.STANDARD;
this.contentType = null; this.contentMetadata = new BaseImmutableContentMetadata(null, null, null, null, null, null);
this.contentMD5 = null;
this.cacheControl = null; this.cacheControl = null;
this.contentDisposition = null;
this.contentEncoding = null;
this.userMetadata = null; this.userMetadata = null;
} }
@ -93,27 +86,6 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
return cacheControl; return cacheControl;
} }
/**
*{@inheritDoc}
*/
public String getContentDisposition() {
return contentDisposition;
}
/**
*{@inheritDoc}
*/
public String getContentEncoding() {
return contentEncoding;
}
/**
*{@inheritDoc}
*/
public String getContentType() {
return contentType;
}
/** /**
*{@inheritDoc} *{@inheritDoc}
*/ */
@ -128,13 +100,6 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
return eTag; return eTag;
} }
/**
*{@inheritDoc}
*/
public Long getSize() {
return size;
}
/** /**
*{@inheritDoc} *{@inheritDoc}
*/ */
@ -152,8 +117,9 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
/** /**
*{@inheritDoc} *{@inheritDoc}
*/ */
public byte[] getContentMD5() { @Override
return contentMD5; public ContentMetadata getContentMetadata() {
return contentMetadata;
} }
@Override @Override
@ -161,15 +127,11 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + ((cacheControl == null) ? 0 : cacheControl.hashCode()); result = prime * result + ((cacheControl == null) ? 0 : cacheControl.hashCode());
result = prime * result + ((contentDisposition == null) ? 0 : contentDisposition.hashCode()); result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.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 + ((eTag == null) ? 0 : eTag.hashCode()); result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
result = prime * result + ((key == null) ? 0 : key.hashCode()); result = prime * result + ((key == null) ? 0 : key.hashCode());
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode()); result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
result = prime * result + ((owner == null) ? 0 : owner.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 + ((storageClass == null) ? 0 : storageClass.hashCode());
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode()); result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode());
return result; return result;
@ -189,22 +151,10 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
return false; return false;
} else if (!cacheControl.equals(other.cacheControl)) } else if (!cacheControl.equals(other.cacheControl))
return false; return false;
if (contentDisposition == null) { if (contentMetadata == null) {
if (other.contentDisposition != null) if (other.contentMetadata != null)
return false; return false;
} else if (!contentDisposition.equals(other.contentDisposition)) } else if (!contentMetadata.equals(other.contentMetadata))
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))
return false; return false;
if (eTag == null) { if (eTag == null) {
if (other.eTag != null) if (other.eTag != null)
@ -226,11 +176,6 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
return false; return false;
} else if (!owner.equals(other.owner)) } else if (!owner.equals(other.owner))
return false; return false;
if (size == null) {
if (other.size != null)
return false;
} else if (!size.equals(other.size))
return false;
if (storageClass == null) { if (storageClass == null) {
if (other.storageClass != null) if (other.storageClass != null)
return false; 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; package org.jclouds.aws.s3.domain.internal;
import java.io.Serializable; import java.io.Serializable;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import org.jclouds.aws.s3.domain.CanonicalUser; import org.jclouds.aws.s3.domain.CanonicalUser;
import org.jclouds.aws.s3.domain.MutableObjectMetadata; import org.jclouds.aws.s3.domain.MutableObjectMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata; 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; import com.google.common.collect.Maps;
@ -43,18 +45,21 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
private String key; private String key;
private Date lastModified; private Date lastModified;
private String eTag; private String eTag;
private Long size;
private CanonicalUser owner; private CanonicalUser owner;
private StorageClass storageClass; private StorageClass storageClass;
private String contentType;
private byte[] contentMD5;
private String cacheControl; private String cacheControl;
private String contentDisposition;
private String contentEncoding;
private Map<String, String> userMetadata = Maps.newHashMap(); private Map<String, String> userMetadata = Maps.newHashMap();
private MutableContentMetadata contentMetadata;
public MutableObjectMetadataImpl() { public MutableObjectMetadataImpl() {
this.storageClass = StorageClass.STANDARD; 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; return cacheControl;
} }
/**
*{@inheritDoc}
*/
public String getContentDisposition() {
return contentDisposition;
}
/**
*{@inheritDoc}
*/
public String getContentEncoding() {
return contentEncoding;
}
/**
*{@inheritDoc}
*/
public String getContentType() {
return contentType;
}
/** /**
*{@inheritDoc} *{@inheritDoc}
*/ */
@ -120,13 +104,6 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
return eTag; return eTag;
} }
/**
*{@inheritDoc}
*/
public Long getSize() {
return size;
}
/** /**
*{@inheritDoc} *{@inheritDoc}
*/ */
@ -141,19 +118,6 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
return userMetadata; 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} *{@inheritDoc}
*/ */
@ -161,38 +125,6 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
this.cacheControl = cacheControl; 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} *{@inheritDoc}
*/ */
@ -221,13 +153,6 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
this.owner = owner; this.owner = owner;
} }
/**
*{@inheritDoc}
*/
public void setSize(Long size) {
this.size = size;
}
/** /**
*{@inheritDoc} *{@inheritDoc}
*/ */
@ -242,20 +167,32 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
this.userMetadata = userMetadata; this.userMetadata = userMetadata;
} }
/**
* {@inheritDoc}
*/
@Override
public MutableContentMetadata getContentMetadata() {
return contentMetadata;
}
/**
* {@inheritDoc}
*/
@Override
public void setContentMetadata(MutableContentMetadata contentMetadata) {
this.contentMetadata = contentMetadata;
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + ((cacheControl == null) ? 0 : cacheControl.hashCode()); result = prime * result + ((cacheControl == null) ? 0 : cacheControl.hashCode());
result = prime * result + ((contentDisposition == null) ? 0 : contentDisposition.hashCode()); result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.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 + ((eTag == null) ? 0 : eTag.hashCode()); result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
result = prime * result + ((key == null) ? 0 : key.hashCode()); result = prime * result + ((key == null) ? 0 : key.hashCode());
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode()); result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
result = prime * result + ((owner == null) ? 0 : owner.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 + ((storageClass == null) ? 0 : storageClass.hashCode());
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode()); result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode());
return result; return result;
@ -275,22 +212,10 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
return false; return false;
} else if (!cacheControl.equals(other.cacheControl)) } else if (!cacheControl.equals(other.cacheControl))
return false; return false;
if (contentDisposition == null) { if (contentMetadata == null) {
if (other.contentDisposition != null) if (other.contentMetadata != null)
return false; return false;
} else if (!contentDisposition.equals(other.contentDisposition)) } else if (!contentMetadata.equals(other.contentMetadata))
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))
return false; return false;
if (eTag == null) { if (eTag == null) {
if (other.eTag != null) if (other.eTag != null)
@ -312,11 +237,6 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
return false; return false;
} else if (!owner.equals(other.owner)) } else if (!owner.equals(other.owner))
return false; return false;
if (size == null) {
if (other.size != null)
return false;
} else if (!size.equals(other.size))
return false;
if (storageClass == null) { if (storageClass == null) {
if (other.storageClass != null) if (other.storageClass != null)
return false; return false;
@ -332,12 +252,9 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
@Override @Override
public String toString() { public String toString() {
return "MutableObjectMetadataImpl [key=" + key + ", cacheControl=" + cacheControl return "[key=" + key + ", cacheControl=" + cacheControl + ", contentMetadata=" + contentMetadata + ", eTag="
+ ", contentDisposition=" + contentDisposition + ", contentEncoding=" + eTag + ", lastModified=" + lastModified + ", owner=" + owner + ", storageClass=" + storageClass
+ contentEncoding + ", contentMD5=" + Arrays.toString(contentMD5) + ", contentType=" + ", userMetadata=" + userMetadata + "]";
+ contentType + ", eTag=" + eTag + ", lastModified=" + lastModified + ", owner="
+ owner + ", size=" + size + ", 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.aws.s3.domain.S3Object;
import org.jclouds.http.internal.PayloadEnclosingImpl; import org.jclouds.http.internal.PayloadEnclosingImpl;
import org.jclouds.io.Payload; 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.LinkedHashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
@ -59,15 +57,13 @@ public class S3ObjectImpl extends PayloadEnclosingImpl implements S3Object, Comp
return this.accessControlList; return this.accessControlList;
} }
private final MutableObjectMetadata _metadata; private final MutableObjectMetadata metadata;
private final SetPayloadPropertiesMutableObjectMetadata metadata;
private Multimap<String, String> allHeaders = LinkedHashMultimap.create(); private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
@Inject @Inject
public S3ObjectImpl(MutableObjectMetadata metadata) { public S3ObjectImpl(MutableObjectMetadata metadata) {
super(); super();
this.metadata = linkMetadataToThis(metadata); this.metadata = metadata;
this._metadata = this.metadata.getDelegate();
} }
/** /**
@ -108,7 +104,7 @@ public class S3ObjectImpl extends PayloadEnclosingImpl implements S3Object, Comp
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = super.hashCode(); int result = super.hashCode();
result = prime * result + ((_metadata == null) ? 0 : _metadata.hashCode()); result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
return result; return result;
} }
@ -121,85 +117,23 @@ public class S3ObjectImpl extends PayloadEnclosingImpl implements S3Object, Comp
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
S3ObjectImpl other = (S3ObjectImpl) obj; S3ObjectImpl other = (S3ObjectImpl) obj;
if (_metadata == null) { if (metadata == null) {
if (other._metadata != null) if (other.metadata != null)
return false; return false;
} else if (!_metadata.equals(other._metadata)) } else if (!metadata.equals(other.metadata))
return false; return false;
return true; return true;
} }
@Override @Override
public String toString() { public String toString() {
return "[metadata=" + _metadata + "]"; return "[metadata=" + metadata + "]";
} }
@Override @Override
public void setPayload(Payload data) { public void setPayload(Payload data) {
linkPayloadToMetadata(data); super.setPayload(data);
} metadata.setContentMetadata(data.getContentMetadata());
/**
* 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;
}
} }
} }

View File

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

View File

@ -74,6 +74,6 @@ public class BindRegionToXmlPayload extends BindToStringPayload {
"<CreateBucketConfiguration><LocationConstraint>%s</LocationConstraint></CreateBucketConfiguration>", "<CreateBucketConfiguration><LocationConstraint>%s</LocationConstraint></CreateBucketConfiguration>",
value); value);
super.bindToRequest(request, payload); 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) { public S3Object apply(HttpResponse from) {
MutableObjectMetadata metadata = metadataParser.apply(from); MutableObjectMetadata metadata = metadataParser.apply(from);
if (metadata.getContentMD5() != null)
from.getPayload().setContentMD5(metadata.getContentMD5());
S3Object object = objectProvider.create(metadata); S3Object object = objectProvider.create(metadata);
object.getAllHeaders().putAll(from.getHeaders()); object.getAllHeaders().putAll(from.getHeaders());
object.setPayload(from.getPayload()); object.setPayload(from.getPayload());

View File

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

View File

@ -67,8 +67,8 @@ public class AWSUtils {
if (response.getPayload() == null) if (response.getPayload() == null)
return null; return null;
// Eucalyptus and Walrus occasionally return text/plain // Eucalyptus and Walrus occasionally return text/plain
if (response.getPayload().getContentType() != null if (response.getPayload().getContentMetadata().getContentType() != null
&& response.getPayload().getContentType().indexOf("text/plain") != -1) && response.getPayload().getContentMetadata().getContentType().indexOf("text/plain") != -1)
return null; return null;
try { try {
AWSError error = (AWSError) factory.create(errorHandlerProvider.get()).setContext(request) 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) { protected void uploadBlob(String container, String name, String script) {
Blob blob = blobContext.getBlobStore().newBlob(name); Blob blob = blobContext.getBlobStore().newBlob(name);
blob.setPayload(script); blob.setPayload(script);
blob.getPayload().setContentType("text/plain"); blob.getPayload().getContentMetadata().setContentType("text/plain");
blobContext.getBlobStore().putBlob(container, blob); blobContext.getBlobStore().putBlob(container, blob);
} }

View File

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

View File

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

View File

@ -57,7 +57,7 @@ public class BindBucketLoggingToXmlPayloadTest extends BaseHandlerTest {
.getInstance(BindBucketLoggingToXmlPayload.class); .getInstance(BindBucketLoggingToXmlPayload.class);
binder.bindToRequest(request, bucketLogging); binder.bindToRequest(request, bucketLogging);
assertEquals(request.getPayload().getContentType(), "text/xml"); assertEquals(request.getPayload().getContentMetadata().getContentType(), "text/xml");
assertEquals(request.getPayload().getRawContent(), expected); 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.binders.BindUserMetadataToHeadersWithPrefix;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -52,17 +53,19 @@ public class BindS3ObjectToPayloadTest {
Payload payload = createMock(Payload.class); Payload payload = createMock(Payload.class);
Blob blob = createMock(Blob.class); Blob blob = createMock(Blob.class);
MutableObjectMetadata md = createMock(MutableObjectMetadata.class); MutableObjectMetadata md = createMock(MutableObjectMetadata.class);
MutableContentMetadata content = createMock(MutableContentMetadata.class);
expect(object.getPayload()).andReturn(payload).atLeastOnce(); 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); expect(object2Blob.apply(object)).andReturn(blob);
mdBinder.bindToRequest(request, blob); mdBinder.bindToRequest(request, blob);
expect(object.getMetadata()).andReturn(md).atLeastOnce(); expect(object.getMetadata()).andReturn(md).atLeastOnce();
expect(md.getCacheControl()).andReturn(null).atLeastOnce(); expect(md.getCacheControl()).andReturn(null).atLeastOnce();
expect(md.getContentDisposition()).andReturn(null).atLeastOnce();
expect(md.getContentEncoding()).andReturn(null).atLeastOnce();
replay(payload); replay(payload);
replay(content);
replay(mdBinder); replay(mdBinder);
replay(object2Blob); replay(object2Blob);
replay(request); replay(request);
@ -75,6 +78,7 @@ public class BindS3ObjectToPayloadTest {
binder.bindToRequest(request, object); binder.bindToRequest(request, object);
verify(payload); verify(payload);
verify(content);
verify(mdBinder); verify(mdBinder);
verify(object2Blob); verify(object2Blob);
verify(request); verify(request);
@ -96,9 +100,11 @@ public class BindS3ObjectToPayloadTest {
Blob blob = createMock(Blob.class); Blob blob = createMock(Blob.class);
MutableObjectMetadata md = createMock(MutableObjectMetadata.class); MutableObjectMetadata md = createMock(MutableObjectMetadata.class);
Multimap<String, String> headers = createMock(Multimap.class); Multimap<String, String> headers = createMock(Multimap.class);
MutableContentMetadata content = createMock(MutableContentMetadata.class);
expect(object.getPayload()).andReturn(payload).atLeastOnce(); 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); expect(object2Blob.apply(object)).andReturn(blob);
mdBinder.bindToRequest(request, blob); mdBinder.bindToRequest(request, blob);
expect(object.getMetadata()).andReturn(md).atLeastOnce(); expect(object.getMetadata()).andReturn(md).atLeastOnce();
@ -106,15 +112,9 @@ public class BindS3ObjectToPayloadTest {
expect(md.getCacheControl()).andReturn("no-cache").atLeastOnce(); expect(md.getCacheControl()).andReturn("no-cache").atLeastOnce();
expect(headers.put("Cache-Control", "no-cache")).andReturn(true); 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(headers);
replay(payload); replay(payload);
replay(content);
replay(mdBinder); replay(mdBinder);
replay(object2Blob); replay(object2Blob);
replay(request); replay(request);
@ -127,6 +127,7 @@ public class BindS3ObjectToPayloadTest {
binder.bindToRequest(request, object); binder.bindToRequest(request, object);
verify(headers); verify(headers);
verify(content);
verify(payload); verify(payload);
verify(mdBinder); verify(mdBinder);
verify(object2Blob); verify(object2Blob);
@ -147,17 +148,20 @@ public class BindS3ObjectToPayloadTest {
Payload payload = createMock(Payload.class); Payload payload = createMock(Payload.class);
Blob blob = createMock(Blob.class); Blob blob = createMock(Blob.class);
MutableObjectMetadata md = createMock(MutableObjectMetadata.class); MutableObjectMetadata md = createMock(MutableObjectMetadata.class);
MutableContentMetadata content = createMock(MutableContentMetadata.class);
expect(object.getPayload()).andReturn(payload).atLeastOnce(); 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); expect(object2Blob.apply(object)).andReturn(blob);
mdBinder.bindToRequest(request, blob); mdBinder.bindToRequest(request, blob);
expect(object.getMetadata()).andReturn(md).atLeastOnce(); expect(object.getMetadata()).andReturn(md).atLeastOnce();
expect(md.getCacheControl()).andReturn(null).atLeastOnce(); expect(md.getCacheControl()).andReturn(null).atLeastOnce();
expect(md.getContentDisposition()).andReturn(null).atLeastOnce(); expect(content.getContentDisposition()).andReturn(null).atLeastOnce();
expect(md.getContentEncoding()).andReturn(null).atLeastOnce(); expect(content.getContentEncoding()).andReturn(null).atLeastOnce();
replay(payload); replay(payload);
replay(content);
replay(mdBinder); replay(mdBinder);
replay(object2Blob); replay(object2Blob);
replay(request); replay(request);
@ -170,6 +174,7 @@ public class BindS3ObjectToPayloadTest {
bindS3ObjectToPayload.bindToRequest(request, object); bindS3ObjectToPayload.bindToRequest(request, object);
verify(payload); verify(payload);
verify(content);
verify(mdBinder); verify(mdBinder);
verify(object2Blob); verify(object2Blob);
verify(request); verify(request);

View File

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

View File

@ -53,11 +53,11 @@ public class ParseObjectMetadataFromHeadersTest {
@Test @Test
void testNormal() throws Exception { void testNormal() throws Exception {
HttpResponse http = new HttpResponse(400, "boa", Payloads.newStringPayload("")); 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(HttpHeaders.CACHE_CONTROL, "cacheControl");
http.getHeaders().put("Content-Disposition", "contentDisposition"); http.getPayload().getContentMetadata().setContentDisposition("contentDisposition");
http.getHeaders().put(HttpHeaders.CONTENT_ENCODING, "encoding"); http.getPayload().getContentMetadata().setContentEncoding("encoding");
ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders(blobParser(http, "\"abcd\""), ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders(blobParser(http, "\"abcd\""),
blobToObjectMetadata, "x-amz-meta-"); blobToObjectMetadata, "x-amz-meta-");
MutableObjectMetadata response = parser.apply(http); MutableObjectMetadata response = parser.apply(http);
@ -68,11 +68,10 @@ public class ParseObjectMetadataFromHeadersTest {
void testAmzEtag() throws Exception { void testAmzEtag() throws Exception {
HttpResponse http = new HttpResponse(400, "boa", Payloads.newStringPayload("")); 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(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\""); http.getHeaders().put("x-amz-meta-object-eTag", "\"abcd\"");
ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders(blobParser(http, null), ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders(blobParser(http, null),
blobToObjectMetadata, "x-amz-meta-"); blobToObjectMetadata, "x-amz-meta-");
@ -88,11 +87,14 @@ public class ParseObjectMetadataFromHeadersTest {
private ParseSystemAndUserMetadataFromHeaders blobParser(HttpResponse response, String etag) { private ParseSystemAndUserMetadataFromHeaders blobParser(HttpResponse response, String etag) {
ParseSystemAndUserMetadataFromHeaders parser = createMock(ParseSystemAndUserMetadataFromHeaders.class); ParseSystemAndUserMetadataFromHeaders parser = createMock(ParseSystemAndUserMetadataFromHeaders.class);
MutableBlobMetadata md = new MutableBlobMetadataImpl(); MutableBlobMetadata md = new MutableBlobMetadataImpl();
md.setContentType("type"); md.getContentMetadata().setContentType("type");
md.setETag(etag); md.setETag(etag);
md.setName("key"); md.setName("key");
md.setLastModified(now); 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); md.setUserMetadata(userMetadata);
expect(parser.apply(response)).andReturn(md); expect(parser.apply(response)).andReturn(md);
replay(parser); replay(parser);
@ -104,15 +106,15 @@ public class ParseObjectMetadataFromHeadersTest {
blobToObjectMetadata = new BlobToObjectMetadata(); blobToObjectMetadata = new BlobToObjectMetadata();
expects = new MutableObjectMetadataImpl(); expects = new MutableObjectMetadataImpl();
expects.setCacheControl("cacheControl"); expects.setCacheControl("cacheControl");
expects.setContentDisposition("contentDisposition"); expects.getContentMetadata().setContentDisposition("contentDisposition");
expects.setContentEncoding("encoding"); expects.getContentMetadata().setContentEncoding("encoding");
expects.setContentMD5(CryptoStreams.hex("abcd")); expects.getContentMetadata().setContentMD5(CryptoStreams.hex("abcd"));
expects.setContentType("type"); expects.getContentMetadata().setContentType("type");
expects.getContentMetadata().setContentLength(1025l);
expects.setETag("\"abcd\""); expects.setETag("\"abcd\"");
expects.setKey("key"); expects.setKey("key");
expects.setLastModified(now); expects.setLastModified(now);
expects.setOwner(null); expects.setOwner(null);
expects.setSize(1025l);
expects.setStorageClass(StorageClass.STANDARD); expects.setStorageClass(StorageClass.STANDARD);
expects.setUserMetadata(userMetadata); 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 assert object.getLastModified().equals(expected) : String.format("expected %1$s, but got %1$s", expected, object
.getLastModified()); .getLastModified());
assertEquals(object.getETag(), "\"9d7bb64e8e18ee34eec06dd2cf37b766\""); assertEquals(object.getETag(), "\"9d7bb64e8e18ee34eec06dd2cf37b766\"");
assert object.getSize() == 136; assert object.getContentMetadata().getContentLength() == 136;
CanonicalUser owner = new CanonicalUser("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0"); CanonicalUser owner = new CanonicalUser("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0");
owner.setDisplayName("ferncam"); owner.setDisplayName("ferncam");
assert object.getOwner().equals(owner); assert object.getOwner().equals(owner);

View File

@ -73,7 +73,7 @@ public class AWSUtilsTest {
HttpResponse response(InputStream content) { HttpResponse response(InputStream content) {
HttpResponse response = new HttpResponse(400, "boa", Payloads.newInputStreamPayload(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-request-id", "requestid");
response.getHeaders().put("x-amz-id-2", "requesttoken"); response.getHeaders().put("x-amz-id-2", "requesttoken");
return response; return response;

View File

@ -39,40 +39,27 @@ public class BindAzureBlobToPayload implements Binder {
private final BindUserMetadataToHeadersWithPrefix blobBinder; private final BindUserMetadataToHeadersWithPrefix blobBinder;
@Inject @Inject
public BindAzureBlobToPayload(AzureBlobToBlob azureBlob2Blob, public BindAzureBlobToPayload(AzureBlobToBlob azureBlob2Blob, BindUserMetadataToHeadersWithPrefix blobBinder) {
BindUserMetadataToHeadersWithPrefix blobBinder) {
this.azureBlob2Blob = azureBlob2Blob; this.azureBlob2Blob = azureBlob2Blob;
this.blobBinder = blobBinder; this.blobBinder = blobBinder;
} }
public void bindToRequest(HttpRequest request, Object payload) { public void bindToRequest(HttpRequest request, Object payload) {
AzureBlob blob = (AzureBlob) 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()); request.getHeaders().put("x-ms-blob-type", blob.getProperties().getType().toString());
switch (blob.getProperties().getType()) { switch (blob.getProperties().getType()) {
case PAGE_BLOB: case PAGE_BLOB:
request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, "0"); request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, "0");
request.getHeaders().put("x-ms-blob-content-length", request.getHeaders().put("x-ms-blob-content-length",
blob.getPayload().getContentLength().toString()); blob.getPayload().getContentMetadata().getContentLength().toString());
break; break;
case BLOCK_BLOB: case BLOCK_BLOB:
checkArgument(checkNotNull(blob.getPayload().getContentLength(), checkArgument(checkNotNull(blob.getPayload().getContentMetadata().getContentLength(),
"blob.getContentLength()") <= 64l * 1024 * 1024, "blob.getContentLength()") <= 64l * 1024 * 1024, "maximum size for put Blob is 64MB");
"maximum size for put Blob is 64MB");
break; break;
} }
blobBinder.bindToRequest(request, azureBlob2Blob.apply(blob)); 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.MutableBlobProperties;
import org.jclouds.azure.storage.blob.domain.internal.MutableBlobPropertiesImpl; import org.jclouds.azure.storage.blob.domain.internal.MutableBlobPropertiesImpl;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.http.HttpUtils;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -38,13 +39,10 @@ public class BlobMetadataToBlobProperties implements Function<BlobMetadata, Muta
if (from == null) if (from == null)
return null; return null;
MutableBlobProperties to = new MutableBlobPropertiesImpl(); MutableBlobProperties to = new MutableBlobPropertiesImpl();
to.setContentType(from.getContentType()); HttpUtils.copy(from.getContentMetadata(), to.getContentMetadata());
to.setETag(from.getETag()); to.setETag(from.getETag());
to.setContentMD5(from.getContentMD5());
to.setName(from.getName()); to.setName(from.getName());
to.setLastModified(from.getLastModified()); to.setLastModified(from.getLastModified());
if (from.getSize() != null)
to.setContentLength(from.getSize());
if (from.getUserMetadata() != null) { if (from.getUserMetadata() != null) {
for (Entry<String, String> entry : from.getUserMetadata().entrySet()) for (Entry<String, String> entry : from.getUserMetadata().entrySet())
to.getMetadata().put(entry.getKey().toLowerCase(), entry.getValue()); 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.StorageType;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl; import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy; import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy;
import org.jclouds.http.HttpUtils;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -46,15 +47,11 @@ public class BlobPropertiesToBlobMetadata implements Function<BlobProperties, Mu
if (from == null) if (from == null)
return null; return null;
MutableBlobMetadata to = new MutableBlobMetadataImpl(); MutableBlobMetadata to = new MutableBlobMetadataImpl();
if (from.getContentMD5() != null) HttpUtils.copy(from.getContentMetadata(), to.getContentMetadata());
to.setContentMD5(from.getContentMD5());
if (from.getContentType() != null)
to.setContentType(from.getContentType());
to.setUserMetadata(from.getMetadata()); to.setUserMetadata(from.getMetadata());
to.setETag(from.getETag()); to.setETag(from.getETag());
to.setLastModified(from.getLastModified()); to.setLastModified(from.getLastModified());
to.setName(from.getName()); to.setName(from.getName());
to.setSize(from.getContentLength());
String directoryName = ifDirectoryReturnName.execute(to); String directoryName = ifDirectoryReturnName.execute(to);
if (directoryName != null) { if (directoryName != null) {
to.setName(directoryName); to.setName(directoryName);

View File

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

View File

@ -23,6 +23,8 @@ import java.net.URI;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import org.jclouds.io.ContentMetadata;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
@ -47,31 +49,6 @@ public interface BlobProperties extends Comparable<BlobProperties> {
String getETag(); 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 java.util.Map;
import org.jclouds.azure.storage.blob.domain.internal.MutableBlobPropertiesImpl; import org.jclouds.azure.storage.blob.domain.internal.MutableBlobPropertiesImpl;
import org.jclouds.io.MutableContentMetadata;
import com.google.inject.ImplementedBy; import com.google.inject.ImplementedBy;
@ -54,30 +55,9 @@ public interface MutableBlobProperties extends BlobProperties {
*/ */
void setETag(String eTag); void setETag(String eTag);
/** MutableContentMetadata getContentMetadata();
* @see ListableContainerProperties#getContentLength
*/
void setContentLength(Long size);
/** void setContentMetadata(MutableContentMetadata md);
* @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);
/** /**
* @see ListableContainerProperties#getMetadata * @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.azure.storage.blob.domain.MutableBlobProperties;
import org.jclouds.http.internal.PayloadEnclosingImpl; import org.jclouds.http.internal.PayloadEnclosingImpl;
import org.jclouds.io.Payload; 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.LinkedHashMultimap;
import com.google.common.collect.Multimap; 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> { public class AzureBlobImpl extends PayloadEnclosingImpl implements AzureBlob, Comparable<AzureBlob> {
private final MutableBlobProperties _properties; private final MutableBlobProperties properties;
private final SetPayloadPropertiesMutableBlobProperties properties;
private Multimap<String, String> allHeaders = LinkedHashMultimap.create(); private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
@Inject @Inject
public AzureBlobImpl(MutableBlobProperties properties) { public AzureBlobImpl(MutableBlobProperties properties) {
super(); super();
this.properties = linkMetadataToThis(properties); this.properties = properties;
this._properties = this.properties.getDelegate();
} }
/** /**
@ -89,7 +85,7 @@ public class AzureBlobImpl extends PayloadEnclosingImpl implements AzureBlob, Co
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = super.hashCode(); int result = super.hashCode();
result = prime * result + ((_properties == null) ? 0 : _properties.hashCode()); result = prime * result + ((properties == null) ? 0 : properties.hashCode());
return result; return result;
} }
@ -102,83 +98,23 @@ public class AzureBlobImpl extends PayloadEnclosingImpl implements AzureBlob, Co
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
AzureBlobImpl other = (AzureBlobImpl) obj; AzureBlobImpl other = (AzureBlobImpl) obj;
if (_properties == null) { if (properties == null) {
if (other._properties != null) if (other.properties != null)
return false; return false;
} else if (!_properties.equals(other._properties)) } else if (!properties.equals(other.properties))
return false; return false;
return true; return true;
} }
@Override @Override
public String toString() { public String toString() {
return "[properties=" + _properties + "]"; return "[properties=" + properties + "]";
} }
@Override @Override
public void setPayload(Payload data) { 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.io.Serializable;
import java.net.URI; import java.net.URI;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import org.jclouds.azure.storage.blob.domain.BlobProperties; import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.BlobType; import org.jclouds.azure.storage.blob.domain.BlobType;
import org.jclouds.azure.storage.blob.domain.LeaseStatus; 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.common.collect.Maps;
import com.google.inject.internal.Nullable; import com.google.inject.internal.Nullable;
@ -48,40 +49,24 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
private final URI url; private final URI url;
private final Date lastModified; private final Date lastModified;
private final String eTag; 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 Map<String, String> metadata = Maps.newLinkedHashMap();
private final LeaseStatus leaseStatus; private final LeaseStatus leaseStatus;
private final BaseImmutableContentMetadata contentMetadata;
public BlobPropertiesImpl(BlobType type, String name, URI url, Date lastModified, String eTag, public BlobPropertiesImpl(BlobType type, String name, URI url, Date lastModified, String eTag, long size,
long size, String contentType, @Nullable byte[] contentMD5, String contentType, @Nullable byte[] contentMD5, @Nullable String contentMetadata,
@Nullable String contentEncoding, @Nullable String contentLanguage, @Nullable String contentLanguage, LeaseStatus leaseStatus, Map<String, String> metadata) {
LeaseStatus leaseStatus, Map<String, String> metadata) {
this.type = checkNotNull(type, "type"); this.type = checkNotNull(type, "type");
this.leaseStatus = checkNotNull(leaseStatus, "leaseStatus"); this.leaseStatus = checkNotNull(leaseStatus, "leaseStatus");
this.name = checkNotNull(name, "name"); this.name = checkNotNull(name, "name");
this.url = checkNotNull(url, "url"); this.url = checkNotNull(url, "url");
this.lastModified = checkNotNull(lastModified, "lastModified"); this.lastModified = checkNotNull(lastModified, "lastModified");
this.eTag = checkNotNull(eTag, "eTag"); this.eTag = checkNotNull(eTag, "eTag");
this.size = size; this.contentMetadata = new BaseImmutableContentMetadata(contentType, size, contentMD5, null, contentLanguage,
this.contentType = checkNotNull(contentType, "contentType"); contentMetadata);
this.contentMD5 = contentMD5;
this.contentEncoding = contentEncoding;
this.contentLanguage = contentLanguage;
this.metadata.putAll(checkNotNull(metadata, "metadata")); this.metadata.putAll(checkNotNull(metadata, "metadata"));
} }
/**
*{@inheritDoc}
*/
@Override
public byte[] getContentMD5() {
return contentMD5;
}
/** /**
*{@inheritDoc} *{@inheritDoc}
*/ */
@ -98,22 +83,6 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
return name; return name;
} }
/**
*{@inheritDoc}
*/
@Override
public String getContentEncoding() {
return contentEncoding;
}
/**
*{@inheritDoc}
*/
@Override
public String getContentType() {
return contentType;
}
/** /**
*{@inheritDoc} *{@inheritDoc}
*/ */
@ -130,14 +99,6 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
return eTag; return eTag;
} }
/**
*{@inheritDoc}
*/
@Override
public Long getContentLength() {
return size;
}
/** /**
*{@inheritDoc} *{@inheritDoc}
*/ */
@ -154,14 +115,6 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
return metadata; return metadata;
} }
/**
*{@inheritDoc}
*/
@Override
public String getContentLanguage() {
return contentLanguage;
}
/** /**
*{@inheritDoc} *{@inheritDoc}
*/ */
@ -178,20 +131,24 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
return leaseStatus; return leaseStatus;
} }
/**
*{@inheritDoc}
*/
@Override
public ContentMetadata getContentMetadata() {
return contentMetadata;
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + ((contentEncoding == null) ? 0 : contentEncoding.hashCode()); result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.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 + ((eTag == null) ? 0 : eTag.hashCode()); result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode()); result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
result = prime * result + ((leaseStatus == null) ? 0 : leaseStatus.hashCode()); result = prime * result + ((leaseStatus == null) ? 0 : leaseStatus.hashCode());
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode()); result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
result = prime * result + ((name == null) ? 0 : name.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 + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((url == null) ? 0 : url.hashCode()); result = prime * result + ((url == null) ? 0 : url.hashCode());
return result; return result;
@ -206,22 +163,10 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
BlobPropertiesImpl other = (BlobPropertiesImpl) obj; BlobPropertiesImpl other = (BlobPropertiesImpl) obj;
if (contentEncoding == null) { if (contentMetadata == null) {
if (other.contentEncoding != null) if (other.contentMetadata != null)
return false; return false;
} else if (!contentEncoding.equals(other.contentEncoding)) } else if (!contentMetadata.equals(other.contentMetadata))
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))
return false; return false;
if (eTag == null) { if (eTag == null) {
if (other.eTag != null) if (other.eTag != null)
@ -248,8 +193,6 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
return false; return false;
} else if (!name.equals(other.name)) } else if (!name.equals(other.name))
return false; return false;
if (size != other.size)
return false;
if (type == null) { if (type == null) {
if (other.type != null) if (other.type != null)
return false; return false;
@ -265,8 +208,8 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
@Override @Override
public String toString() { public String toString() {
return "[name=" + name + ", type=" + type + ", contentType=" + contentType return "[name=" + name + ", type=" + type + ", contentMetadata=" + contentMetadata + ", eTag=" + eTag
+ ", eTag=" + eTag + ", lastModified=" + lastModified + ", size=" + size + "]"; + ", 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.io.Serializable;
import java.net.URI; import java.net.URI;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.Map; 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.BlobType;
import org.jclouds.azure.storage.blob.domain.LeaseStatus; import org.jclouds.azure.storage.blob.domain.LeaseStatus;
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties; 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; import com.google.common.collect.Maps;
@ -49,14 +51,17 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
private URI url; private URI url;
private Date lastModified; private Date lastModified;
private String eTag; private String eTag;
private Long size; private MutableContentMetadata contentMetadata;
private String contentType;
private byte[] contentMD5;
private String contentEncoding;
private String contentLanguage;
private Map<String, String> metadata = Maps.newHashMap(); private Map<String, String> metadata = Maps.newHashMap();
public MutableBlobPropertiesImpl() { 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; return name;
} }
/**
*{@inheritDoc}
*/
public String getContentEncoding() {
return contentEncoding;
}
/**
*{@inheritDoc}
*/
public String getContentType() {
return contentType;
}
/** /**
*{@inheritDoc} *{@inheritDoc}
*/ */
@ -108,13 +99,6 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
return eTag; return eTag;
} }
/**
*{@inheritDoc}
*/
public Long getContentLength() {
return size;
}
/** /**
*{@inheritDoc} *{@inheritDoc}
*/ */
@ -129,37 +113,6 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
return metadata; 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} *{@inheritDoc}
*/ */
@ -168,13 +121,6 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
return leaseStatus; return leaseStatus;
} }
/**
*{@inheritDoc}
*/
public void setContentType(String contentType) {
this.contentType = contentType;
}
/** /**
*{@inheritDoc} *{@inheritDoc}
*/ */
@ -196,13 +142,6 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
this.lastModified = lastModified; this.lastModified = lastModified;
} }
/**
*{@inheritDoc}
*/
public void setContentLength(Long size) {
this.size = size;
}
/** /**
*{@inheritDoc} *{@inheritDoc}
*/ */
@ -210,18 +149,10 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
this.metadata = metadata; this.metadata = metadata;
} }
public void setContentLanguage(String contentLanguage) {
this.contentLanguage = contentLanguage;
}
public void setUrl(URI url) { public void setUrl(URI url) {
this.url = url; this.url = url;
} }
public String getContentLanguage() {
return contentLanguage;
}
public URI getUrl() { public URI getUrl() {
return url; return url;
} }
@ -230,15 +161,11 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + ((contentEncoding == null) ? 0 : contentEncoding.hashCode()); result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.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 + ((eTag == null) ? 0 : eTag.hashCode()); result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode()); result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode()); result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
result = prime * result + ((name == null) ? 0 : name.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 + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((url == null) ? 0 : url.hashCode()); result = prime * result + ((url == null) ? 0 : url.hashCode());
return result; return result;
@ -253,22 +180,10 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
MutableBlobPropertiesImpl other = (MutableBlobPropertiesImpl) obj; MutableBlobPropertiesImpl other = (MutableBlobPropertiesImpl) obj;
if (contentEncoding == null) { if (contentMetadata == null) {
if (other.contentEncoding != null) if (other.contentMetadata != null)
return false; return false;
} else if (!contentEncoding.equals(other.contentEncoding)) } else if (!contentMetadata.equals(other.contentMetadata))
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))
return false; return false;
if (eTag == null) { if (eTag == null) {
if (other.eTag != null) if (other.eTag != null)
@ -290,8 +205,6 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
return false; return false;
} else if (!name.equals(other.name)) } else if (!name.equals(other.name))
return false; return false;
if (size != other.size)
return false;
if (type == null) { if (type == null) {
if (other.type != null) if (other.type != null)
return false; return false;
@ -310,4 +223,21 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
return "[name=" + name + ", type=" + type + ", lastModified=" + lastModified + "]"; 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; package org.jclouds.azure.storage.blob.functions;
import static org.jclouds.http.HttpUtils.attemptToParseSizeAndRangeFromHeaders;
import javax.inject.Inject; 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.blobstore.functions.BlobMetadataToBlobProperties;
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties; import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
@ -41,8 +38,7 @@ import com.google.common.base.Function;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class ParseBlobPropertiesFromHeaders implements public class ParseBlobPropertiesFromHeaders implements Function<HttpResponse, MutableBlobProperties>, InvocationContext {
Function<HttpResponse, MutableBlobProperties>, InvocationContext {
private final ParseSystemAndUserMetadataFromHeaders blobMetadataParser; private final ParseSystemAndUserMetadataFromHeaders blobMetadataParser;
private final BlobMetadataToBlobProperties blobToBlobProperties; private final BlobMetadataToBlobProperties blobToBlobProperties;
@ -59,9 +55,6 @@ public class ParseBlobPropertiesFromHeaders implements
public MutableBlobProperties apply(HttpResponse from) { public MutableBlobProperties apply(HttpResponse from) {
BlobMetadata base = blobMetadataParser.apply(from); BlobMetadata base = blobMetadataParser.apply(from);
MutableBlobProperties to = blobToBlobProperties.apply(base); 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; return to;
} }

View File

@ -103,9 +103,9 @@ public class SharedKeyLiteAuthentication implements HttpRequestFilter {
} }
private void appendPayloadMetadata(HttpRequest request, StringBuilder buffer) { 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"); .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"); .append("\n");
} }

View File

@ -229,11 +229,12 @@ public class AzureBlobClientLiveTest {
object.getProperties().setName("object"); object.getProperties().setName("object");
object.setPayload(data); object.setPayload(data);
Payloads.calculateMD5(object); Payloads.calculateMD5(object);
object.getProperties().setContentType("text/plain"); object.getProperties().getContentMetadata().setContentType("text/plain");
object.getProperties().getMetadata().put("mykey", "metadata-value"); object.getProperties().getMetadata().put("mykey", "metadata-value");
byte[] md5 = object.getProperties().getContentMD5(); byte[] md5 = object.getProperties().getContentMetadata().getContentMD5();
String newEtag = client.putBlob(privateContainer, object); 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 // Test HEAD of missing object
assert client.getBlobProperties(privateContainer, "non-existent-object") == null; assert client.getBlobProperties(privateContainer, "non-existent-object") == null;
@ -247,9 +248,10 @@ public class AzureBlobClientLiveTest {
// inexpensive fashion // inexpensive fashion
// http://code.google.com/p/jclouds/issues/detail?id=92 // http://code.google.com/p/jclouds/issues/detail?id=92
// assertEquals(metadata.getSize(), data.length()); // 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.. // 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.getETag(), newEtag);
assertEquals(metadata.getMetadata().entrySet().size(), 1); assertEquals(metadata.getMetadata().entrySet().size(), 1);
assertEquals(metadata.getMetadata().get("mykey"), "metadata-value"); assertEquals(metadata.getMetadata().get("mykey"), "metadata-value");
@ -268,9 +270,10 @@ public class AzureBlobClientLiveTest {
AzureBlob getBlob = client.getBlob(privateContainer, object.getProperties().getName()); AzureBlob getBlob = client.getBlob(privateContainer, object.getProperties().getName());
assertEquals(Utils.toStringAndClose(getBlob.getPayload().getInput()), data); assertEquals(Utils.toStringAndClose(getBlob.getPayload().getInput()), data);
// TODO assertEquals(getBlob.getName(), object.getProperties().getName()); // TODO assertEquals(getBlob.getName(), object.getProperties().getName());
assertEquals(getBlob.getPayload().getContentLength(), new Long(data.length())); assertEquals(getBlob.getPayload().getContentMetadata().getContentLength(), new Long(data.length()));
assertEquals(getBlob.getProperties().getContentType(), "text/plain"); assertEquals(getBlob.getProperties().getContentMetadata().getContentType(), "text/plain");
assertEquals(CryptoStreams.hex(md5), CryptoStreams.hex(getBlob.getProperties().getContentMD5())); assertEquals(CryptoStreams.hex(md5), CryptoStreams.hex(getBlob.getProperties().getContentMetadata()
.getContentMD5()));
assertEquals(newEtag, getBlob.getProperties().getETag()); assertEquals(newEtag, getBlob.getProperties().getETag());
// wait until we can update metadata // wait until we can update metadata
// assertEquals(getBlob.getProperties().getMetadata().entries().size(), 2); // assertEquals(getBlob.getProperties().getMetadata().entries().size(), 2);
@ -306,9 +309,10 @@ public class AzureBlobClientLiveTest {
object = client.newBlob(); object = client.newBlob();
object.getProperties().setName("chunked-object"); object.getProperties().setName("chunked-object");
object.setPayload(bais); 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); 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 // Test GET with options
// Non-matching ETag // 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.binders.BindUserMetadataToHeadersWithPrefix;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -55,9 +56,11 @@ public class BindAzureBlobToPayloadTest {
Blob blob = createMock(Blob.class); Blob blob = createMock(Blob.class);
MutableBlobProperties md = createMock(MutableBlobProperties.class); MutableBlobProperties md = createMock(MutableBlobProperties.class);
Multimap<String, String> headers = createMock(Multimap.class); Multimap<String, String> headers = createMock(Multimap.class);
MutableContentMetadata content = createMock(MutableContentMetadata.class);
expect(object.getPayload()).andReturn(payload).atLeastOnce(); 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); expect(object2Blob.apply(object)).andReturn(blob);
mdBinder.bindToRequest(request, blob); mdBinder.bindToRequest(request, blob);
expect(object.getProperties()).andReturn(md).atLeastOnce(); expect(object.getProperties()).andReturn(md).atLeastOnce();
@ -65,10 +68,8 @@ public class BindAzureBlobToPayloadTest {
expect(request.getHeaders()).andReturn(headers).atLeastOnce(); expect(request.getHeaders()).andReturn(headers).atLeastOnce();
expect(headers.put("x-ms-blob-type", "BlockBlob")).andReturn(true); 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(headers);
replay(content);
replay(payload); replay(payload);
replay(mdBinder); replay(mdBinder);
replay(object2Blob); replay(object2Blob);
@ -82,6 +83,7 @@ public class BindAzureBlobToPayloadTest {
binder.bindToRequest(request, object); binder.bindToRequest(request, object);
verify(headers); verify(headers);
verify(content);
verify(payload); verify(payload);
verify(mdBinder); verify(mdBinder);
verify(object2Blob); verify(object2Blob);
@ -104,9 +106,11 @@ public class BindAzureBlobToPayloadTest {
Blob blob = createMock(Blob.class); Blob blob = createMock(Blob.class);
MutableBlobProperties md = createMock(MutableBlobProperties.class); MutableBlobProperties md = createMock(MutableBlobProperties.class);
Multimap<String, String> headers = createMock(Multimap.class); Multimap<String, String> headers = createMock(Multimap.class);
MutableContentMetadata content = createMock(MutableContentMetadata.class);
expect(object.getPayload()).andReturn(payload).atLeastOnce(); 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); expect(object2Blob.apply(object)).andReturn(blob);
mdBinder.bindToRequest(request, blob); mdBinder.bindToRequest(request, blob);
expect(object.getProperties()).andReturn(md).atLeastOnce(); expect(object.getProperties()).andReturn(md).atLeastOnce();
@ -114,14 +118,9 @@ public class BindAzureBlobToPayloadTest {
expect(request.getHeaders()).andReturn(headers).atLeastOnce(); expect(request.getHeaders()).andReturn(headers).atLeastOnce();
expect(headers.put("x-ms-blob-type", "BlockBlob")).andReturn(true); 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(headers);
replay(payload); replay(payload);
replay(content);
replay(mdBinder); replay(mdBinder);
replay(object2Blob); replay(object2Blob);
replay(request); replay(request);
@ -135,6 +134,7 @@ public class BindAzureBlobToPayloadTest {
verify(headers); verify(headers);
verify(payload); verify(payload);
verify(content);
verify(mdBinder); verify(mdBinder);
verify(object2Blob); verify(object2Blob);
verify(request); verify(request);
@ -156,9 +156,11 @@ public class BindAzureBlobToPayloadTest {
Blob blob = createMock(Blob.class); Blob blob = createMock(Blob.class);
MutableBlobProperties md = createMock(MutableBlobProperties.class); MutableBlobProperties md = createMock(MutableBlobProperties.class);
Multimap<String, String> headers = createMock(Multimap.class); Multimap<String, String> headers = createMock(Multimap.class);
MutableContentMetadata content = createMock(MutableContentMetadata.class);
expect(object.getPayload()).andReturn(payload).atLeastOnce(); 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); expect(object2Blob.apply(object)).andReturn(blob);
mdBinder.bindToRequest(request, blob); mdBinder.bindToRequest(request, blob);
expect(object.getProperties()).andReturn(md).atLeastOnce(); expect(object.getProperties()).andReturn(md).atLeastOnce();
@ -166,11 +168,13 @@ public class BindAzureBlobToPayloadTest {
expect(request.getHeaders()).andReturn(headers).atLeastOnce(); expect(request.getHeaders()).andReturn(headers).atLeastOnce();
expect(headers.put("x-ms-blob-type", "BlockBlob")).andReturn(true); expect(headers.put("x-ms-blob-type", "BlockBlob")).andReturn(true);
expect(md.getContentLanguage()).andReturn(null).atLeastOnce(); expect(content.getContentLanguage()).andReturn(null).atLeastOnce();
expect(md.getContentEncoding()).andReturn(null).atLeastOnce(); expect(content.getContentEncoding()).andReturn(null).atLeastOnce();
replay(headers); replay(headers);
replay(payload); replay(payload);
replay(content);
replay(mdBinder); replay(mdBinder);
replay(object2Blob); replay(object2Blob);
replay(request); replay(request);
@ -178,12 +182,12 @@ public class BindAzureBlobToPayloadTest {
replay(blob); replay(blob);
replay(md); replay(md);
BindAzureBlobToPayload bindAzureBlobToPayload = new BindAzureBlobToPayload(object2Blob, BindAzureBlobToPayload bindAzureBlobToPayload = new BindAzureBlobToPayload(object2Blob, mdBinder);
mdBinder);
bindAzureBlobToPayload.bindToRequest(request, object); bindAzureBlobToPayload.bindToRequest(request, object);
verify(headers); verify(headers);
verify(content);
verify(payload); verify(payload);
verify(mdBinder); verify(mdBinder);
verify(object2Blob); verify(object2Blob);

View File

@ -32,7 +32,6 @@ import org.jclouds.blobstore.domain.Blob.Factory;
import org.jclouds.date.TimeStamp; import org.jclouds.date.TimeStamp;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
import org.jclouds.io.payloads.PhantomPayload;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestClientTest; import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.RestContextFactory; import org.jclouds.rest.RestContextFactory;
@ -46,7 +45,7 @@ import com.google.inject.Module;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@Test(groups = "unit", testName = "s3.AzureBlobBlobRequestSignerTest") @Test(groups = "unit", testName = "s3.AzureBlobBlobRequestSignerTest")
public class AzureBlobBlobRequestSignerTest extends RestClientTest<AzureBlobAsyncClient> { public class AzureBlobRequestSignerTest extends RestClientTest<AzureBlobAsyncClient> {
private BlobRequestSigner signer; private BlobRequestSigner signer;
private Factory blobFactory; private Factory blobFactory;
@ -81,8 +80,10 @@ public class AzureBlobBlobRequestSignerTest extends RestClientTest<AzureBlobAsyn
NoSuchMethodException, IOException { NoSuchMethodException, IOException {
Blob blob = blobFactory.create(null); Blob blob = blobFactory.create(null);
blob.getMetadata().setName("name"); blob.getMetadata().setName("name");
blob.setPayload(new PhantomPayload(2l, new byte[] { 0, 2, 4, 8 })); blob.setPayload("");
blob.getPayload().setContentType("text/plain"); 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); 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] ([container-name path #^BlobStore blobstore]
(.getBlob blobstore container-name path))) (.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 (defn sign-blob-request
"Get a signed http request for manipulating a blob in another application. "Get a signed http request for manipulating a blob in another application.
ex. curl" ex. curl"
@ -278,14 +249,18 @@ in another application. ex. curl"
{:keys [method content-type content-length content-md5]} blobstore] {:keys [method content-type content-length content-md5]} blobstore]
{:pre [(or content-length (#{:delete :get} method))]} {:pre [(or content-length (#{:delete :get} method))]}
(case method (case method
:delete (sign-remove-blob-request container-name path blobstore) :delete (.signRemoveBlob (.. blobstore getContext getSigner) container-name path)
:get (sign-get-blob-request container-name path blobstore) :get (.signGetBlob (.. blobstore getContext getSigner) container-name path)
:put (.signPutBlob :put (.signPutBlob
(.. blobstore getContext getSigner) container-name (.. blobstore getContext getSigner) container-name
(doto (.newBlob blobstore path) (doto (.newBlob blobstore path)
(.setPayload (.setPayload
(doto (PhantomPayload. (long content-length) content-md5) (doto
(.setContentType content-type)))))))) (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 (defn get-blob-stream
"Get an inputstream from the blob at a given path" "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)))))] target (.md5(.crypto (.utils (blobstore-context blobstore)))))]
(.writeTo (.getPayload blob) digest-stream) (.writeTo (.getPayload blob) digest-stream)
(let [digest (.digest (.getMessageDigest 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) (when-not (Arrays/equals digest metadata-digest)
(if (<= (or retries 0) *max-retries*) (if (<= (or retries 0) *max-retries*)
(recur container-name name target blobstore [(inc (or retries 1))]) (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.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.options.HttpRequestOptions; import org.jclouds.http.options.HttpRequestOptions;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import org.jclouds.io.Payloads; import org.jclouds.io.Payloads;
import org.jclouds.io.payloads.ByteArrayPayload; import org.jclouds.io.payloads.ByteArrayPayload;
@ -103,8 +105,7 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.internal.Nullable; import com.google.inject.internal.Nullable;
/** /**
* Implementation of {@link BaseAsyncBlobStore} which keeps all data in a local * Implementation of {@link BaseAsyncBlobStore} which keeps all data in a local Map object.
* Map object.
* *
* @author Adrian Cole * @author Adrian Cole
* @author James Murty * @author James Murty
@ -121,11 +122,12 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
@Inject @Inject
protected TransientAsyncBlobStore(BlobStoreContext context, DateService dateService, Crypto crypto, protected TransientAsyncBlobStore(BlobStoreContext context, DateService dateService, Crypto crypto,
ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs, ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
ConcurrentMap<String, Location> containerToLocation, HttpGetOptionsListToGetOptions httpGetOptionsConverter, ConcurrentMap<String, Location> containerToLocation,
IfDirectoryReturnNameStrategy ifDirectoryReturnName, Blob.Factory blobFactory, BlobUtils blobUtils, HttpGetOptionsListToGetOptions httpGetOptionsConverter,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation, IfDirectoryReturnNameStrategy ifDirectoryReturnName, Blob.Factory blobFactory, BlobUtils blobUtils,
Supplier<Set<? extends Location>> locations) { @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
Supplier<Set<? extends Location>> locations) {
super(context, blobUtils, service, defaultLocation, locations); super(context, blobUtils, service, defaultLocation, locations);
this.blobFactory = blobFactory; this.blobFactory = blobFactory;
this.dateService = dateService; this.dateService = dateService;
@ -149,21 +151,21 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
return immediateFailedFuture(cnfe(container)); return immediateFailedFuture(cnfe(container));
SortedSet<StorageMetadata> contents = newTreeSet(transform(realContents.keySet(), SortedSet<StorageMetadata> contents = newTreeSet(transform(realContents.keySet(),
new Function<String, StorageMetadata>() { new Function<String, StorageMetadata>() {
public StorageMetadata apply(String key) { public StorageMetadata apply(String key) {
Blob oldBlob = realContents.get(key); Blob oldBlob = realContents.get(key);
checkState(oldBlob != null, "blob " + key + " is not present although it was in the list of " checkState(oldBlob != null, "blob " + key + " is not present although it was in the list of "
+ container); + container);
checkState(oldBlob.getMetadata() != null, "blob " + container + "/" + key + " has no metadata"); checkState(oldBlob.getMetadata() != null, "blob " + container + "/" + key + " has no metadata");
MutableBlobMetadata md = copy(oldBlob.getMetadata()); MutableBlobMetadata md = copy(oldBlob.getMetadata());
String directoryName = ifDirectoryReturnName.execute(md); String directoryName = ifDirectoryReturnName.execute(md);
if (directoryName != null) { if (directoryName != null) {
md.setName(directoryName); md.setName(directoryName);
md.setType(StorageType.RELATIVE_PATH); md.setType(StorageType.RELATIVE_PATH);
}
return md;
} }
return md; }));
}
}));
if (options.getMarker() != null) { if (options.getMarker() != null) {
final String finalMarker = options.getMarker(); 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))); contents = newTreeSet(filter(contents, new DelimiterFilter(prefix != null ? prefix : null, delimiter)));
Iterables.<StorageMetadata> addAll(contents, transform(commonPrefixes, Iterables.<StorageMetadata> addAll(contents, transform(commonPrefixes,
new Function<String, StorageMetadata>() { new Function<String, StorageMetadata>() {
public StorageMetadata apply(String o) { public StorageMetadata apply(String o) {
MutableStorageMetadata md = new MutableStorageMetadataImpl(); MutableStorageMetadata md = new MutableStorageMetadataImpl();
md.setType(StorageType.RELATIVE_PATH); md.setType(StorageType.RELATIVE_PATH);
md.setName(o); md.setName(o);
return md; return md;
} }
})); }));
} }
// trim metadata, if the response isn't supposed to be detailed. // trim metadata, if the response isn't supposed to be detailed.
@ -226,13 +228,13 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
} }
return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(contents, return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(contents,
marker)); marker));
} }
private ContainerNotFoundException cnfe(final String name) { private ContainerNotFoundException cnfe(final String name) {
return new ContainerNotFoundException(name, String.format("container %s not in %s", name, getContainerToBlobs() return new ContainerNotFoundException(name, String.format("container %s not in %s", name, getContainerToBlobs()
.keySet())); .keySet()));
} }
public static MutableBlobMetadata copy(MutableBlobMetadata in) { public static MutableBlobMetadata copy(MutableBlobMetadata in) {
@ -242,9 +244,10 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
os = new ObjectOutputStream(bout); os = new ObjectOutputStream(bout);
os.writeObject(in); os.writeObject(in);
ObjectInput is = new ObjectInputStream(new ByteArrayInputStream(bout.toByteArray())); ObjectInput is = new ObjectInputStream(new ByteArrayInputStream(bout.toByteArray()));
MutableBlobMetadata metadata = (MutableBlobMetadata) is.readObject(); MutableBlobMetadata out = (MutableBlobMetadata) is.readObject();
convertUserMetadataKeysToLowercase(metadata); convertUserMetadataKeysToLowercase(out);
return metadata; HttpUtils.copy(in.getContentMetadata(), out.getContentMetadata());
return out;
} catch (Exception e) { } catch (Exception e) {
propagate(e); propagate(e);
assert false : "exception should have propagated: " + e; assert false : "exception should have propagated: " + e;
@ -329,15 +332,15 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
@Override @Override
public ListenableFuture<PageSet<? extends StorageMetadata>> list() { public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(transform( return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(transform(
getContainerToBlobs().keySet(), new Function<String, StorageMetadata>() { getContainerToBlobs().keySet(), new Function<String, StorageMetadata>() {
public StorageMetadata apply(String name) { public StorageMetadata apply(String name) {
MutableStorageMetadata cmd = create(); MutableStorageMetadata cmd = create();
cmd.setName(name); cmd.setName(name);
cmd.setType(StorageType.CONTAINER); cmd.setType(StorageType.CONTAINER);
cmd.setLocation(getContainerToLocation().get(name)); cmd.setLocation(getContainerToLocation().get(name));
return cmd; return cmd;
} }
}), null)); }), null));
} }
protected MutableStorageMetadata create() { protected MutableStorageMetadata create() {
@ -361,7 +364,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
*/ */
public ListenableFuture<Void> createContainerInLocationIfAbsent(final Location location, final String name) { public ListenableFuture<Void> createContainerInLocationIfAbsent(final Location location, final String name) {
ConcurrentMap<String, Blob> container = getContainerToBlobs().putIfAbsent(name, ConcurrentMap<String, Blob> container = getContainerToBlobs().putIfAbsent(name,
new ConcurrentHashMap<String, Blob>()); new ConcurrentHashMap<String, Blob>());
if (container == null) { if (container == null) {
getContainerToLocation().put(name, location != null ? location : defaultLocation.get()); getContainerToLocation().put(name, location != null ? location : defaultLocation.get());
return immediateFuture((Void) null); return immediateFuture((Void) null);
@ -506,20 +509,20 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
protected Blob createUpdatedCopyOfBlob(Blob in) { protected Blob createUpdatedCopyOfBlob(Blob in) {
ByteArrayPayload payload = (in.getPayload() instanceof ByteArrayPayload) ? ByteArrayPayload.class.cast(in ByteArrayPayload payload = (in.getPayload() instanceof ByteArrayPayload) ? ByteArrayPayload.class.cast(in
.getPayload()) : null; .getPayload()) : null;
if (payload == null) if (payload == null)
payload = (in.getPayload() instanceof DelegatingPayload) ? (DelegatingPayload.class.cast(in.getPayload()) payload = (in.getPayload() instanceof DelegatingPayload) ? (DelegatingPayload.class.cast(in.getPayload())
.getDelegate() instanceof ByteArrayPayload) ? ByteArrayPayload.class.cast(DelegatingPayload.class.cast( .getDelegate() instanceof ByteArrayPayload) ? ByteArrayPayload.class.cast(DelegatingPayload.class
in.getPayload()).getDelegate()) : null : null; .cast(in.getPayload()).getDelegate()) : null : null;
try { try {
if (payload == null || !(payload instanceof ByteArrayPayload)) { if (payload == null || !(payload instanceof ByteArrayPayload)) {
String oldContentType = in.getPayload().getContentType(); MutableContentMetadata oldMd = in.getPayload().getContentMetadata();
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
in.getPayload().writeTo(out); in.getPayload().writeTo(out);
payload = (ByteArrayPayload) Payloads.calculateMD5(Payloads.newPayload(out.toByteArray())); payload = (ByteArrayPayload) Payloads.calculateMD5(Payloads.newPayload(out.toByteArray()));
payload.setContentType(oldContentType); HttpUtils.copy(oldMd, payload.getContentMetadata());
} else { } else {
if (payload.getContentMD5() == null) if (payload.getContentMetadata().getContentMD5() == null)
Payloads.calculateMD5(in, crypto.md5()); Payloads.calculateMD5(in, crypto.md5());
} }
} catch (IOException e) { } catch (IOException e) {
@ -528,18 +531,11 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
Blob blob = blobFactory.create(copy(in.getMetadata())); Blob blob = blobFactory.create(copy(in.getMetadata()));
blob.setPayload(payload); blob.setPayload(payload);
blob.getMetadata().setLastModified(new Date()); blob.getMetadata().setLastModified(new Date());
blob.getMetadata().setSize(payload.getContentLength()); String eTag = CryptoStreams.hex(payload.getContentMetadata().getContentMD5());
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());
blob.getMetadata().setETag(eTag); blob.getMetadata().setETag(eTag);
// Set HTTP headers to match metadata // Set HTTP headers to match metadata
blob.getAllHeaders().replaceValues(HttpHeaders.LAST_MODIFIED, 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)); blob.getAllHeaders().replaceValues(HttpHeaders.ETAG, Collections.singleton(eTag));
copyPayloadHeadersToBlob(payload, blob); copyPayloadHeadersToBlob(payload, blob);
blob.getAllHeaders().putAll(Multimaps.forMap(blob.getMetadata().getUserMetadata())); blob.getAllHeaders().putAll(Multimaps.forMap(blob.getMetadata().getUserMetadata()));
@ -547,23 +543,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
} }
private void copyPayloadHeadersToBlob(Payload payload, Blob blob) { private void copyPayloadHeadersToBlob(Payload payload, Blob blob) {
if (payload.getContentType() != null) HttpUtils.addContentHeadersFromMetadata(payload.getContentMetadata(), blob.getAllHeaders());
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())));
} }
/** /**
@ -603,7 +583,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
if (object.getMetadata().getLastModified().before(modifiedSince)) { if (object.getMetadata().getLastModified().before(modifiedSince)) {
HttpResponse response = new HttpResponse(304, null, null); HttpResponse response = new HttpResponse(304, null, null);
return immediateFailedFuture(new HttpResponseException(String.format("%1$s is before %2$s", object 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)) { if (object.getMetadata().getLastModified().after(unmodifiedSince)) {
HttpResponse response = new HttpResponse(412, null, null); HttpResponse response = new HttpResponse(412, null, null);
return immediateFailedFuture(new HttpResponseException(String.format("%1$s is after %2$s", object 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); Blob returnVal = copyBlob(object);
@ -644,7 +624,6 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
} }
returnVal.setPayload(out.toByteArray()); returnVal.setPayload(out.toByteArray());
returnVal.getMetadata().setSize(new Long(data.length));
} }
checkNotNull(returnVal.getPayload(), "payload " + returnVal); checkNotNull(returnVal.getPayload(), "payload " + returnVal);
return immediateFuture(returnVal); return immediateFuture(returnVal);

View File

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

View File

@ -39,7 +39,7 @@ public class BindBlobToMultipartForm implements Binder {
Blob blob = (Blob) payload; Blob blob = (Blob) payload;
Part part = Part.create(blob.getMetadata().getName(), blob.getPayload(), 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)); request.setPayload(new MultipartForm(part));
} }

View File

@ -19,9 +19,8 @@
package org.jclouds.blobstore.domain; package org.jclouds.blobstore.domain;
import javax.annotation.Nullable;
import org.jclouds.blobstore.domain.internal.BlobMetadataImpl; import org.jclouds.blobstore.domain.internal.BlobMetadataImpl;
import org.jclouds.io.ContentMetadata;
import com.google.inject.ImplementedBy; import com.google.inject.ImplementedBy;
@ -32,40 +31,5 @@ import com.google.inject.ImplementedBy;
*/ */
@ImplementedBy(BlobMetadataImpl.class) @ImplementedBy(BlobMetadataImpl.class)
public interface BlobMetadata extends StorageMetadata { public interface BlobMetadata extends StorageMetadata {
ContentMetadata 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." />
*/
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();
} }

View File

@ -19,9 +19,8 @@
package org.jclouds.blobstore.domain; package org.jclouds.blobstore.domain;
import javax.annotation.Nullable;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl; import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.io.MutableContentMetadata;
import com.google.inject.ImplementedBy; import com.google.inject.ImplementedBy;
@ -32,22 +31,8 @@ import com.google.inject.ImplementedBy;
*/ */
@ImplementedBy(MutableBlobMetadataImpl.class) @ImplementedBy(MutableBlobMetadataImpl.class)
public interface MutableBlobMetadata extends BlobMetadata, MutableStorageMetadata { public interface MutableBlobMetadata extends BlobMetadata, MutableStorageMetadata {
MutableContentMetadata getContentMetadata();
/** void setContentMetadata(MutableContentMetadata md);
* 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);
} }

View File

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

View File

@ -83,14 +83,6 @@ public interface StorageMetadata extends ResourceMetadata<StorageType> {
*/ */
String getETag(); 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 * 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.blobstore.domain.StorageMetadata;
import org.jclouds.http.internal.PayloadEnclosingImpl; import org.jclouds.http.internal.PayloadEnclosingImpl;
import org.jclouds.io.Payload; 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.LinkedHashMultimap;
import com.google.common.collect.Multimap; 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> { public class BlobImpl extends PayloadEnclosingImpl implements Blob, Comparable<Blob> {
private final MutableBlobMetadata _metadata; private final MutableBlobMetadata metadata;
private final SetPayloadPropertiesMutableBlobMetadata metadata;
private Multimap<String, String> allHeaders = LinkedHashMultimap.create(); private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
@Inject @Inject
public BlobImpl(MutableBlobMetadata metadata) { public BlobImpl(MutableBlobMetadata metadata) {
super(); super();
this.metadata = linkMetadataToThis(metadata); this.metadata = metadata;
this._metadata = this.metadata.getDelegate();
} }
/** /**
@ -93,7 +89,7 @@ public class BlobImpl extends PayloadEnclosingImpl implements Blob, Comparable<B
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = super.hashCode(); int result = super.hashCode();
result = prime * result + ((_metadata == null) ? 0 : _metadata.hashCode()); result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
return result; return result;
} }
@ -106,124 +102,23 @@ public class BlobImpl extends PayloadEnclosingImpl implements Blob, Comparable<B
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
BlobImpl other = (BlobImpl) obj; BlobImpl other = (BlobImpl) obj;
if (_metadata == null) { if (metadata == null) {
if (other._metadata != null) if (other.metadata != null)
return false; return false;
} else if (!_metadata.equals(other._metadata)) } else if (!metadata.equals(other.metadata))
return false; return false;
return true; return true;
} }
@Override @Override
public String toString() { public String toString() {
return "[metadata=" + _metadata + "]"; return "[metadata=" + metadata + "]";
} }
@Override @Override
public void setPayload(Payload data) { 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; package org.jclouds.blobstore.domain.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable; import java.io.Serializable;
import java.net.URI; import java.net.URI;
import java.util.Date; 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.BlobMetadata;
import org.jclouds.blobstore.domain.StorageType; import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.io.ContentMetadata;
import com.google.inject.internal.Nullable; import com.google.inject.internal.Nullable;
@ -39,68 +42,20 @@ import com.google.inject.internal.Nullable;
public class BlobMetadataImpl extends StorageMetadataImpl implements Serializable, BlobMetadata { public class BlobMetadataImpl extends StorageMetadataImpl implements Serializable, BlobMetadata {
/** The serialVersionUID */ /** The serialVersionUID */
private static final long serialVersionUID = -5932618957134612231L; private static final long serialVersionUID = -5932618957134612231L;
private final ContentMetadata contentMetadata;
private final String contentType; public BlobMetadataImpl(String id, String name, @Nullable Location location, URI uri, String eTag,
private final String contentDisposition; Date lastModified, Map<String, String> userMetadata, ContentMetadata contentMetadata) {
private final String contentEncoding; super(StorageType.BLOB, id, name, location, uri, eTag, lastModified, userMetadata);
private final String contentLanguage; this.contentMetadata = checkNotNull(contentMetadata, "contentMetadata");
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;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public String getContentType() { public ContentMetadata getContentMetadata() {
return contentType; return contentMetadata;
}
/**
* {@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;
}
} }
} }

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.BlobMetadata;
import org.jclouds.blobstore.domain.MutableBlobMetadata; import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.StorageType; 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}. * 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 { public class MutableBlobMetadataImpl extends MutableStorageMetadataImpl implements MutableBlobMetadata {
/** The serialVersionUID */ /** The serialVersionUID */
private static final long serialVersionUID = -5932618957134612231L; private static final long serialVersionUID = -5932618957134612231L;
private MutableContentMetadata contentMetadata;
private String contentType;
private String contentDisposition;
private String contentEncoding;
private String contentLanguage;
private byte[] contentMD5;
public MutableBlobMetadataImpl() { public MutableBlobMetadataImpl() {
super(); super();
this.setType(StorageType.BLOB); this.setType(StorageType.BLOB);
this.contentMetadata = new BaseMutableContentMetadata();
} }
public MutableBlobMetadataImpl(BlobMetadata from) { public MutableBlobMetadataImpl(BlobMetadata from) {
super(from); super(from);
this.contentType = from.getContentType(); this.contentMetadata = new BaseMutableContentMetadata();
this.contentDisposition = from.getContentDisposition(); HttpUtils.copy(from.getContentMetadata(), this.contentMetadata);
this.contentEncoding = from.getContentEncoding();
this.contentLanguage = from.getContentLanguage();
this.contentMD5 = from.getContentMD5();
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public String getContentType() { public MutableContentMetadata getContentMetadata() {
return contentType; return contentMetadata;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public void setContentType(String contentType) { public void setContentMetadata(MutableContentMetadata contentMetadata) {
this.contentType = contentType; this.contentMetadata = contentMetadata;
}
/**
* {@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;
}
} }
} }

View File

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

View File

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

View File

@ -49,13 +49,13 @@ public class ObjectMD5 implements Function<Object, byte[]> {
object = blobFactory.create(null); object = blobFactory.create(null);
object.setPayload(Payloads.newPayload(from)); object.setPayload(Payloads.newPayload(from));
} }
if (object.getMetadata().getContentMD5() == null) if (object.getMetadata().getContentMetadata().getContentMD5() == null)
try { try {
Payloads.calculateMD5(object, crypto.md5()); Payloads.calculateMD5(object, crypto.md5());
} catch (IOException e) { } catch (IOException e) {
Throwables.propagate(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.Constants.PROPERTY_API_VERSION;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX; import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.jclouds.blobstore.util.BlobStoreUtils.getKeyFor; import static org.jclouds.blobstore.util.BlobStoreUtils.getKeyFor;
import static org.jclouds.http.HttpUtils.attemptToParseSizeAndRangeFromHeaders;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -37,6 +36,7 @@ import org.jclouds.date.DateService;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.rest.InvocationContext; import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.GeneratedHttpRequest;
@ -47,7 +47,7 @@ import com.google.common.base.Function;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class ParseSystemAndUserMetadataFromHeaders implements Function<HttpResponse, MutableBlobMetadata>, public class ParseSystemAndUserMetadataFromHeaders implements Function<HttpResponse, MutableBlobMetadata>,
InvocationContext { InvocationContext {
private final String metadataPrefix; private final String metadataPrefix;
private final DateService dateParser; private final DateService dateParser;
private final Provider<MutableBlobMetadata> metadataFactory; private final Provider<MutableBlobMetadata> metadataFactory;
@ -57,7 +57,7 @@ public class ParseSystemAndUserMetadataFromHeaders implements Function<HttpRespo
@Inject @Inject
public ParseSystemAndUserMetadataFromHeaders(Provider<MutableBlobMetadata> metadataFactory, DateService dateParser, 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.metadataFactory = metadataFactory;
this.dateParser = dateParser; this.dateParser = dateParser;
this.metadataPrefix = metadataPrefix; this.metadataPrefix = metadataPrefix;
@ -68,11 +68,9 @@ public class ParseSystemAndUserMetadataFromHeaders implements Function<HttpRespo
String objectKey = getKeyFor(request, from); String objectKey = getKeyFor(request, from);
MutableBlobMetadata to = metadataFactory.get(); MutableBlobMetadata to = metadataFactory.get();
to.setName(objectKey); to.setName(objectKey);
setContentTypeOrThrowException(from, to); HttpUtils.copy(from.getPayload().getContentMetadata(), to.getContentMetadata());
addETagTo(from, to); addETagTo(from, to);
addContentMD5To(from, to);
parseLastModifiedOrThrowException(from, to); parseLastModifiedOrThrowException(from, to);
setContentLength(from, to);
addUserMetadataTo(from, to); addUserMetadataTo(from, to);
return to; return to;
} }
@ -82,15 +80,10 @@ public class ParseSystemAndUserMetadataFromHeaders implements Function<HttpRespo
for (Entry<String, String> header : from.getHeaders().entries()) { for (Entry<String, String> header : from.getHeaders().entries()) {
if (header.getKey() != null && header.getKey().startsWith(metadataPrefix)) if (header.getKey() != null && header.getKey().startsWith(metadataPrefix))
metadata.getUserMetadata().put((header.getKey().substring(metadataPrefix.length())).toLowerCase(), 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 @VisibleForTesting
void parseLastModifiedOrThrowException(HttpResponse from, MutableBlobMetadata metadata) throws HttpException { void parseLastModifiedOrThrowException(HttpResponse from, MutableBlobMetadata metadata) throws HttpException {
String lastModified = from.getFirstHeaderOrNull(HttpHeaders.LAST_MODIFIED); 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) { public ParseSystemAndUserMetadataFromHeaders setContext(HttpRequest request) {
checkArgument(request instanceof GeneratedHttpRequest<?>, "note this handler requires a GeneratedHttpRequest"); checkArgument(request instanceof GeneratedHttpRequest<?>, "note this handler requires a GeneratedHttpRequest");
this.request = (GeneratedHttpRequest<?>) request; this.request = (GeneratedHttpRequest<?>) request;

View File

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

View File

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

View File

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

View File

@ -65,7 +65,7 @@ public class MarkersGetDirectoryStrategy implements GetDirectoryStrategy {
public StorageMetadata execute(String containerName, String directory) { public StorageMetadata execute(String containerName, String directory) {
BlobMetadata md = connection.blobMetadata(containerName, 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); return resource2Directory.apply(md);
for (String suffix : BlobStoreConstants.DIRECTORY_SUFFIXES) { for (String suffix : BlobStoreConstants.DIRECTORY_SUFFIXES) {
md = connection.blobMetadata(containerName, directory + suffix); 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 // 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 // suffix who also has content type set to application/directory
if (blobMd.getContentType() != null if (blobMd.getContentMetadata().getContentType() != null
&& blobMd.getContentType().equals("application/directory")) && blobMd.getContentMetadata().getContentType().equals("application/directory"))
return metadata.getName(); return metadata.getName();
} }
return null; return null;

View File

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

View File

@ -109,14 +109,6 @@
(download-blob container-name name data-file))) (download-blob container-name name data-file)))
(finally (.delete 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! ;; this will fail until somebody fixes it!
#_ #_
(deftest sing-blob-request-test (deftest sing-blob-request-test

View File

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

View File

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

View File

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

View File

@ -63,7 +63,7 @@ public class ParseSystemAndUserMetadataFromHeadersTest {
void setUp() { void setUp() {
parser = new ParseSystemAndUserMetadataFromHeaders(blobMetadataProvider, new SimpleDateFormatDateService(), parser = new ParseSystemAndUserMetadataFromHeaders(blobMetadataProvider, new SimpleDateFormatDateService(),
"prefix", "default"); "prefix", "default");
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class); GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes(); expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
@ -75,9 +75,9 @@ public class ParseSystemAndUserMetadataFromHeadersTest {
@Test @Test
public void testApplySetsKey() { public void testApplySetsKey() {
HttpResponse from = new HttpResponse(200, "ok", Payloads.newStringPayload("")); 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.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); BlobMetadata metadata = parser.apply(from);
assertEquals(metadata.getName(), "key"); assertEquals(metadata.getName(), "key");
} }
@ -89,38 +89,6 @@ public class ParseSystemAndUserMetadataFromHeadersTest {
parser.apply(from); 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 @Test
public void testSetLastModified() { public void testSetLastModified() {
HttpResponse from = new HttpResponse(200, "ok", Payloads.newStringPayload("")); HttpResponse from = new HttpResponse(200, "ok", Payloads.newStringPayload(""));
@ -128,7 +96,7 @@ public class ParseSystemAndUserMetadataFromHeadersTest {
MutableBlobMetadata metadata = blobMetadataProvider.get(); MutableBlobMetadata metadata = blobMetadataProvider.get();
parser.parseLastModifiedOrThrowException(from, metadata); parser.parseLastModifiedOrThrowException(from, metadata);
assertEquals(metadata.getLastModified(), new SimpleDateFormatDateService() 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) @Test(expectedExceptions = HttpException.class)

View File

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

View File

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

View File

@ -197,7 +197,7 @@ public abstract class BaseBlobMapIntegrationTest extends BaseMapIntegrationTest<
for (String key : fiveInputs.keySet()) { for (String key : fiveInputs.keySet()) {
Blob blob = context.getBlobStore().newBlob(key); Blob blob = context.getBlobStore().newBlob(key);
blob.setPayload(fiveInputs.get(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); newMap.put(key, blob);
} }
map.putAll(newMap); map.putAll(newMap);

View File

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

View File

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

View File

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

View File

@ -257,7 +257,7 @@ public class TemplateOptions {
checkArgument(checkNotNull(privateKey, "privateKey").startsWith("-----BEGIN RSA PRIVATE KEY-----"), checkArgument(checkNotNull(privateKey, "privateKey").startsWith("-----BEGIN RSA PRIVATE KEY-----"),
"key should start with -----BEGIN RSA PRIVATE KEY-----"); "key should start with -----BEGIN RSA PRIVATE KEY-----");
Payload payload = newStringPayload(privateKey); Payload payload = newStringPayload(privateKey);
payload.setContentType("text/plain"); payload.getContentMetadata().setContentType("text/plain");
return installPrivateKey(payload); return installPrivateKey(payload);
} }
@ -300,7 +300,7 @@ public class TemplateOptions {
public TemplateOptions authorizePublicKey(String publicKey) { public TemplateOptions authorizePublicKey(String publicKey) {
checkArgument(checkNotNull(publicKey, "publicKey").startsWith("ssh-rsa"), "key should start with ssh-rsa"); checkArgument(checkNotNull(publicKey, "publicKey").startsWith("ssh-rsa"), "key should start with ssh-rsa");
Payload payload = newStringPayload(publicKey); Payload payload = newStringPayload(publicKey);
payload.setContentType("text/plain"); payload.getContentMetadata().setContentType("text/plain");
return authorizePublicKey(payload); 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.ByteStreams.toByteArray;
import static com.google.common.io.Closeables.closeQuietly; import static com.google.common.io.Closeables.closeQuietly;
import static java.util.Collections.singletonList; 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_LENGTH;
import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE; import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE;
import static javax.ws.rs.core.HttpHeaders.HOST; import static javax.ws.rs.core.HttpHeaders.HOST;
@ -52,6 +54,7 @@ import java.net.URI;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -69,7 +72,9 @@ import javax.ws.rs.core.UriBuilder;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.crypto.CryptoStreams; import org.jclouds.crypto.CryptoStreams;
import org.jclouds.io.ContentMetadata;
import org.jclouds.io.InputSuppliers; import org.jclouds.io.InputSuppliers;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import org.jclouds.io.PayloadEnclosing; import org.jclouds.io.PayloadEnclosing;
import org.jclouds.io.Payloads; 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. * 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); byte[] returnVal = toByteArrayOrNull(response);
if (returnVal != null && !response.getPayload().isRepeatable()) { if (returnVal != null && !response.getPayload().isRepeatable()) {
Payload newPayload = Payloads.newByteArrayPayload(returnVal); Payload newPayload = Payloads.newByteArrayPayload(returnVal);
newPayload.setContentMD5(response.getPayload().getContentMD5()); MutableContentMetadata fromMd = response.getPayload().getContentMetadata();
newPayload.setContentType(response.getPayload().getContentType()); MutableContentMetadata toMd = newPayload.getContentMetadata();
copy(fromMd, toMd);
response.setPayload(newPayload); response.setPayload(newPayload);
} }
return returnVal; 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) { public static URI parseEndPoint(String hostHeader) {
URI redirectURI = URI.create(hostHeader); URI redirectURI = URI.create(hostHeader);
String scheme = redirectURI.getScheme(); String scheme = redirectURI.getScheme();
@ -338,17 +368,27 @@ public class HttpUtils {
logger.debug("%s %s: %s", prefix, header.getKey(), header.getValue()); logger.debug("%s %s: %s", prefix, header.getKey(), header.getValue());
} }
if (message.getPayload() != null) { if (message.getPayload() != null) {
if (message.getPayload().getContentType() != null) if (message.getPayload().getContentMetadata().getContentType() != null)
logger.debug("%s %s: %s", prefix, HttpHeaders.CONTENT_TYPE, message.getPayload().getContentType()); logger.debug("%s %s: %s", prefix, CONTENT_TYPE, message.getPayload().getContentMetadata().getContentType());
if (message.getPayload().getContentLength() != null) if (message.getPayload().getContentMetadata().getContentLength() != null)
logger.debug("%s %s: %s", prefix, HttpHeaders.CONTENT_LENGTH, message.getPayload().getContentLength()); logger.debug("%s %s: %s", prefix, CONTENT_LENGTH, message.getPayload().getContentMetadata()
if (message.getPayload().getContentMD5() != null) .getContentLength());
if (message.getPayload().getContentMetadata().getContentMD5() != null)
try { try {
logger.debug("%s %s: %s", prefix, "Content-MD5", CryptoStreams.base64Encode(InputSuppliers.of(message logger.debug("%s %s: %s", prefix, "Content-MD5", CryptoStreams.base64Encode(InputSuppliers.of(message
.getPayload().getContentMD5()))); .getPayload().getContentMetadata().getContentMD5())));
} catch (IOException e) { } catch (IOException e) {
logger.warn(e, " error getting md5 for %s", message); 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()) { for (Entry<String, String> header : headers.entries()) {
if (!chunked && CONTENT_LENGTH.equalsIgnoreCase(header.getKey())) { if (!chunked && CONTENT_LENGTH.equalsIgnoreCase(header.getKey())) {
if (payload != null) if (payload != null)
payload.setContentLength(new Long(header.getValue())); payload.getContentMetadata().setContentLength(new Long(header.getValue()));
} else if ("Content-MD5".equalsIgnoreCase(header.getKey())) { } else if ("Content-MD5".equalsIgnoreCase(header.getKey())) {
if (payload != null) if (payload != null)
payload.setContentMD5(CryptoStreams.base64(header.getValue())); payload.getContentMetadata().setContentMD5(CryptoStreams.base64(header.getValue()));
} else if (CONTENT_TYPE.equalsIgnoreCase(header.getKey())) { } else if (CONTENT_TYPE.equalsIgnoreCase(header.getKey())) {
if (payload != null) if (payload != null)
payload.setContentType(header.getValue()); payload.getContentMetadata().setContentType(header.getValue());
} else if ("Content-Disposition".equalsIgnoreCase(header.getKey())) { } else if ("Content-Disposition".equalsIgnoreCase(header.getKey())) {
if (payload != null) 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 { } else {
message.getHeaders().put(header.getKey(), header.getValue()); message.getHeaders().put(header.getKey(), header.getValue());
} }
@ -521,19 +567,34 @@ public class HttpUtils {
if (message instanceof HttpRequest) { if (message instanceof HttpRequest) {
checkArgument( checkArgument(
message.getPayload() == null || message.getFirstHeaderOrNull(CONTENT_TYPE) == null, 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); + message);
checkArgument( checkArgument(
message.getPayload() == null || message.getFirstHeaderOrNull(CONTENT_LENGTH) == null, 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); + message);
checkArgument(message.getPayload() == null || message.getPayload().getContentLength() != null checkArgument(message.getPayload() == null
|| message.getPayload().getContentMetadata().getContentLength() != null
|| "chunked".equalsIgnoreCase(message.getFirstHeaderOrNull("Transfer-Encoding")), || "chunked".equalsIgnoreCase(message.getFirstHeaderOrNull("Transfer-Encoding")),
"either chunked encoding must be set on the http request or contentlength set on the payload: " "either chunked encoding must be set on the http request or contentlength set on the payload: "
+ message); + message);
checkArgument(message.getPayload() == null || message.getFirstHeaderOrNull("Content-MD5") == null, checkArgument(
"configuration error please use request.getPayload().setContentMD5(value) as opposed to adding a content md5 header: " 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); + 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 { public static Long attemptToParseSizeAndRangeFromHeaders(HttpResponse from) throws HttpException {
String contentRange = from.getFirstHeaderOrNull("Content-Range"); String contentRange = from.getFirstHeaderOrNull("Content-Range");
if (contentRange == null && from.getPayload() != null) { if (contentRange == null && from.getPayload() != null) {
return from.getPayload().getContentLength(); return from.getPayload().getContentMetadata().getContentLength();
} else if (contentRange != null) { } else if (contentRange != null) {
return Long.parseLong(contentRange.substring(contentRange.lastIndexOf('/') + 1)); return Long.parseLong(contentRange.substring(contentRange.lastIndexOf('/') + 1));
} }
@ -566,7 +627,8 @@ public class HttpUtils {
public static void checkRequestHasContentLengthOrChunkedEncoding(HttpRequest request, String message) { public static void checkRequestHasContentLengthOrChunkedEncoding(HttpRequest request, String message) {
boolean chunked = "chunked".equals(request.getFirstHeaderOrNull("Transfer-Encoding")); 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) { public static void wirePayloadIfEnabled(Wire wire, HttpRequest request) {

View File

@ -33,8 +33,7 @@ import com.google.common.base.Function;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
public class ParseContentMD5FromHeaders implements Function<HttpResponse, byte[]>, public class ParseContentMD5FromHeaders implements Function<HttpResponse, byte[]>, InvocationContext {
InvocationContext {
public static class NoContentMD5Exception extends RuntimeException { public static class NoContentMD5Exception extends RuntimeException {
@ -65,7 +64,7 @@ public class ParseContentMD5FromHeaders implements Function<HttpResponse, byte[]
public byte[] apply(HttpResponse from) { public byte[] apply(HttpResponse from) {
releasePayload(from); releasePayload(from);
if (from.getPayload() != null) { if (from.getPayload() != null) {
return from.getPayload().getContentMD5(); return from.getPayload().getContentMetadata().getContentMD5();
} }
throw new NoContentMD5Exception(request, from); 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.IOExceptionRetryHandler;
import org.jclouds.http.handlers.DelegatingErrorHandler; import org.jclouds.http.handlers.DelegatingErrorHandler;
import org.jclouds.http.handlers.DelegatingRetryHandler; import org.jclouds.http.handlers.DelegatingRetryHandler;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import org.jclouds.io.Payloads; import org.jclouds.io.Payloads;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
@ -197,20 +198,21 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
connection.setRequestProperty(HttpHeaders.USER_AGENT, USER_AGENT); connection.setRequestProperty(HttpHeaders.USER_AGENT, USER_AGENT);
if (request.getPayload() != null) { if (request.getPayload() != null) {
if (request.getPayload().getContentMD5() != null) MutableContentMetadata md = request.getPayload().getContentMetadata();
connection.setRequestProperty("Content-MD5", CryptoStreams.base64(request.getPayload().getContentMD5())); if (md.getContentMD5() != null)
if (request.getPayload().getContentType() != null) connection.setRequestProperty("Content-MD5", CryptoStreams.base64(md.getContentMD5()));
connection.setRequestProperty(HttpHeaders.CONTENT_TYPE, request.getPayload().getContentType()); if (md.getContentType() != null)
if (request.getPayload().getContentDisposition() != null) connection.setRequestProperty(HttpHeaders.CONTENT_TYPE, md.getContentType());
connection.setRequestProperty("Content-Disposition", request.getPayload().getContentDisposition()); if (md.getContentDisposition() != null)
if (request.getPayload().getContentEncoding() != null) connection.setRequestProperty("Content-Disposition", md.getContentDisposition());
connection.setRequestProperty("Content-Encoding", request.getPayload().getContentEncoding()); if (md.getContentEncoding() != null)
if (request.getPayload().getContentLanguage() != null) connection.setRequestProperty("Content-Encoding", md.getContentEncoding());
connection.setRequestProperty("Content-Language", request.getPayload().getContentLanguage()); if (md.getContentLanguage() != null)
connection.setRequestProperty("Content-Language", md.getContentLanguage());
if (chunked) { if (chunked) {
connection.setChunkedStreamingMode(8196); connection.setChunkedStreamingMode(8196);
} else { } else {
Long length = checkNotNull(request.getPayload().getContentLength(), "payload.getContentLength"); Long length = checkNotNull(md.getContentLength(), "payload.getContentLength");
connection.setRequestProperty(HttpHeaders.CONTENT_LENGTH, length.toString()); connection.setRequestProperty(HttpHeaders.CONTENT_LENGTH, length.toString());
connection.setFixedLengthStreamingMode(length.intValue()); 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.Closeable;
import java.io.InputStream; import java.io.InputStream;
import javax.annotation.Nullable;
import com.google.common.io.InputSupplier; import com.google.common.io.InputSupplier;
/** /**
@ -46,86 +44,13 @@ public interface Payload extends InputSupplier<InputStream>, WriteTo, Closeable
*/ */
boolean isRepeatable(); boolean isRepeatable();
void setContentLength(@Nullable Long contentLength);
/** /**
* Returns the total size of the payload, or the chunk that's available. * release resources used by this entity. This should be called when data is discarded.
* <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.
*/ */
void release(); 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 { public static Payload calculateMD5(Payload payload, MessageDigest md5) throws IOException {
checkNotNull(payload, "payload"); checkNotNull(payload, "payload");
if (!payload.isRepeatable()) { if (!payload.isRepeatable()) {
String oldContentType = payload.getContentType(); String oldContentType = payload.getContentMetadata().getContentType();
Payload oldPayload = payload; Payload oldPayload = payload;
try { try {
payload = newByteArrayPayload(toByteArray(payload)); payload = newByteArrayPayload(toByteArray(payload));
} finally { } finally {
oldPayload.release(); oldPayload.release();
} }
payload.setContentType(oldContentType); payload.getContentMetadata().setContentType(oldContentType);
} }
payload.setContentMD5(CryptoStreams.digest(payload, md5)); payload.getContentMetadata().setContentMD5(CryptoStreams.digest(payload, md5));
return payload; 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