mirror of https://github.com/apache/jclouds.git
Issue 353: refactored payload/blob so that contentMetadata is a type.
This commit is contained in:
parent
546630ba52
commit
3639af0f12
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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());
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,9 +82,11 @@ 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);
|
||||||
|
|
||||||
assertRequestLineEquals(request,
|
assertRequestLineEquals(request,
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
|
@ -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();
|
||||||
|
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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 + "]";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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))])
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
}
|
|
@ -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);
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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"));
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
|
@ -109,19 +109,19 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses default md5 generator.
|
* Uses default md5 generator.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue