mirror of https://github.com/apache/jclouds.git
Issue 134: switch to typed payloads for http requests and blob types
git-svn-id: http://jclouds.googlecode.com/svn/trunk@2410 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
74be2180d3
commit
4a22f808d1
|
@ -64,7 +64,7 @@ public class ${clientName}AsyncClientTest extends RestClientTest<${clientName}As
|
|||
|
||||
assertRequestLineEquals(httpMethod, "TODO: insert expected request");
|
||||
assertHeadersEqual(httpMethod, "");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseStatusesFromJsonResponse.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
|
|
|
@ -36,7 +36,7 @@ import javax.ws.rs.Path;
|
|||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.atmosonline.saas.binders.BindAtmosObjectToEntityAndMetadataToHeaders;
|
||||
import org.jclouds.atmosonline.saas.binders.BindAtmosObjectToPayloadAndMetadataToHeaders;
|
||||
import org.jclouds.atmosonline.saas.domain.AtmosObject;
|
||||
import org.jclouds.atmosonline.saas.domain.BoundedSortedSet;
|
||||
import org.jclouds.atmosonline.saas.domain.DirectoryEntry;
|
||||
|
@ -117,7 +117,7 @@ public interface AtmosStorageAsyncClient {
|
|||
@Consumes(MediaType.WILDCARD)
|
||||
Future<URI> createFile(
|
||||
@PathParam("parent") String parent,
|
||||
@PathParam("name") @ParamParser(AtmosObjectName.class) @BinderParam(BindAtmosObjectToEntityAndMetadataToHeaders.class) AtmosObject object);
|
||||
@PathParam("name") @ParamParser(AtmosObjectName.class) @BinderParam(BindAtmosObjectToPayloadAndMetadataToHeaders.class) AtmosObject object);
|
||||
|
||||
/**
|
||||
* @see AtmosStorageClient#updateFile
|
||||
|
@ -128,7 +128,7 @@ public interface AtmosStorageAsyncClient {
|
|||
@Consumes(MediaType.WILDCARD)
|
||||
Future<Void> updateFile(
|
||||
@PathParam("parent") String parent,
|
||||
@PathParam("name") @ParamParser(AtmosObjectName.class) @BinderParam(BindAtmosObjectToEntityAndMetadataToHeaders.class) AtmosObject object);
|
||||
@PathParam("name") @ParamParser(AtmosObjectName.class) @BinderParam(BindAtmosObjectToPayloadAndMetadataToHeaders.class) AtmosObject object);
|
||||
|
||||
/**
|
||||
* @see AtmosStorageClient#readFile
|
||||
|
|
|
@ -33,21 +33,21 @@ import org.jclouds.encryption.EncryptionService;
|
|||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.Binder;
|
||||
|
||||
public class BindAtmosObjectToEntityAndMetadataToHeaders implements Binder {
|
||||
public class BindAtmosObjectToPayloadAndMetadataToHeaders implements Binder {
|
||||
private final BindUserMetadataToHeaders metaBinder;
|
||||
private final EncryptionService encryptionService;
|
||||
|
||||
@Inject
|
||||
protected BindAtmosObjectToEntityAndMetadataToHeaders(BindUserMetadataToHeaders metaBinder,
|
||||
protected BindAtmosObjectToPayloadAndMetadataToHeaders(BindUserMetadataToHeaders metaBinder,
|
||||
EncryptionService encryptionService) {
|
||||
this.metaBinder = metaBinder;
|
||||
this.encryptionService = encryptionService;
|
||||
}
|
||||
|
||||
public void bindToRequest(HttpRequest request, Object entity) {
|
||||
AtmosObject object = (AtmosObject) entity;
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
AtmosObject object = (AtmosObject) payload;
|
||||
|
||||
request.setEntity(checkNotNull(object.getData(), "object.getContent()"));
|
||||
request.setPayload(checkNotNull(object.getPayload(), "object.getPayload()"));
|
||||
request.getHeaders().put(
|
||||
HttpHeaders.CONTENT_TYPE,
|
||||
checkNotNull(object.getContentMetadata().getContentType(),
|
|
@ -35,8 +35,8 @@ import org.jclouds.rest.Binder;
|
|||
|
||||
public class BindUserMetadataToHeaders implements Binder {
|
||||
|
||||
public void bindToRequest(HttpRequest request, Object entity) {
|
||||
UserMetadata md = (UserMetadata) checkNotNull(entity, "entity");
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
UserMetadata md = (UserMetadata) checkNotNull(payload, "payload");
|
||||
if (md.getMetadata().size() > 0) {
|
||||
String header = join(md.getMetadata());
|
||||
request.getHeaders().put("x-emc-meta", header);
|
||||
|
|
|
@ -45,7 +45,7 @@ public class BlobToObject implements Function<Blob, AtmosObject> {
|
|||
|
||||
public AtmosObject apply(Blob from) {
|
||||
AtmosObject object = blobMd2Object.apply(from.getMetadata());
|
||||
object.setData(from.getData());
|
||||
object.setPayload(from.getPayload());
|
||||
object.setAllHeaders(from.getAllHeaders());
|
||||
return object;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public class ObjectToBlob implements Function<AtmosObject, Blob> {
|
|||
Blob blob = blobFactory.create(object2BlobMd.apply(from));
|
||||
if (from.getContentMetadata().getContentLength() != null)
|
||||
blob.setContentLength(from.getContentMetadata().getContentLength());
|
||||
blob.setData(from.getData());
|
||||
blob.setPayload(from.getPayload());
|
||||
blob.setAllHeaders(from.getAllHeaders());
|
||||
return blob;
|
||||
}
|
||||
|
|
|
@ -31,9 +31,7 @@ import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
|
|||
import org.jclouds.atmosonline.saas.domain.SystemMetadata;
|
||||
import org.jclouds.atmosonline.saas.domain.UserMetadata;
|
||||
import org.jclouds.atmosonline.saas.domain.internal.AtmosObjectImpl;
|
||||
import org.jclouds.blobstore.functions.CalculateSize;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5Result;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
@ -57,28 +55,24 @@ public class AtmosObjectModule extends AbstractModule {
|
|||
|
||||
private static class AtmosObjectFactory implements AtmosObject.Factory {
|
||||
@Inject
|
||||
GenerateMD5Result generateMD5Result;
|
||||
@Inject
|
||||
GenerateMD5 generateMD5;
|
||||
@Inject
|
||||
CalculateSize calculateSize;
|
||||
EncryptionService encryptionService;
|
||||
@Inject
|
||||
Provider<MutableContentMetadata> metadataProvider;
|
||||
|
||||
public AtmosObject create(MutableContentMetadata contentMetadata) {
|
||||
return new AtmosObjectImpl(generateMD5Result, generateMD5, calculateSize,
|
||||
contentMetadata != null ? contentMetadata : metadataProvider.get());
|
||||
return new AtmosObjectImpl(encryptionService, contentMetadata != null ? contentMetadata
|
||||
: metadataProvider.get());
|
||||
}
|
||||
|
||||
public AtmosObject create(SystemMetadata systemMetadata, UserMetadata userMetadata) {
|
||||
return new AtmosObjectImpl(generateMD5Result, generateMD5, calculateSize, metadataProvider
|
||||
.get(), systemMetadata, userMetadata);
|
||||
return new AtmosObjectImpl(encryptionService, metadataProvider.get(), systemMetadata,
|
||||
userMetadata);
|
||||
}
|
||||
|
||||
public AtmosObject create(MutableContentMetadata contentMetadata,
|
||||
SystemMetadata systemMetadata, UserMetadata userMetadata) {
|
||||
return new AtmosObjectImpl(generateMD5Result, generateMD5, calculateSize, contentMetadata,
|
||||
systemMetadata, userMetadata);
|
||||
return new AtmosObjectImpl(encryptionService, contentMetadata, systemMetadata,
|
||||
userMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,14 +23,14 @@
|
|||
*/
|
||||
package org.jclouds.atmosonline.saas.domain;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.jclouds.http.PayloadEnclosing;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.inject.internal.Nullable;
|
||||
|
||||
/**
|
||||
* Amazon Atmos is designed to store objects. Objects are stored in buckets and consist of a
|
||||
* {@link ObjectMetadataAtmosObject#getData() value}, a {@link ObjectMetadata#getKey key},
|
||||
* {@link ObjectMetadataAtmosObject#getContent() value}, a {@link ObjectMetadata#getKey key},
|
||||
* {@link ObjectMetadata#getUserMetadata() metadata}, and an access control policy.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
|
@ -38,7 +38,7 @@ import com.google.inject.internal.Nullable;
|
|||
* href="http://docs.amazonwebservices.com/AmazonAtmos/2006-03-01/index.html?UsingObjects.html"
|
||||
* />
|
||||
*/
|
||||
public interface AtmosObject extends Comparable<AtmosObject> {
|
||||
public interface AtmosObject extends PayloadEnclosing, Comparable<AtmosObject> {
|
||||
public interface Factory {
|
||||
AtmosObject create(@Nullable MutableContentMetadata contentMetadata);
|
||||
|
||||
|
@ -49,33 +49,6 @@ public interface AtmosObject extends Comparable<AtmosObject> {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* generate an MD5 Hash for the current data.
|
||||
* <p/>
|
||||
* <h2>Note</h2>
|
||||
* <p/>
|
||||
* If this is an InputStream, it will be converted to a byte array first.
|
||||
*
|
||||
* @throws IOException
|
||||
* if there is a problem generating the hash.
|
||||
*/
|
||||
void generateMD5() throws IOException;
|
||||
|
||||
/**
|
||||
* Sets entity for the request or the content from the response. If size isn't set, this will
|
||||
* attempt to discover it.
|
||||
*
|
||||
* @param data
|
||||
* typically InputStream for downloads, or File, byte [], String, or InputStream for
|
||||
* uploads.
|
||||
*/
|
||||
void setData(Object data);
|
||||
|
||||
/**
|
||||
* @return InputStream, if downloading, or whatever was set during {@link #setData(Object)}
|
||||
*/
|
||||
Object getData();
|
||||
|
||||
MutableContentMetadata getContentMetadata();
|
||||
|
||||
/**
|
||||
|
|
|
@ -51,7 +51,7 @@ public class MutableContentMetadata {
|
|||
* 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 #getData()}
|
||||
* @return the length in bytes that can be be obtained from {@link #getContent()}
|
||||
* @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
|
||||
* @see GetObjectOptions
|
||||
*/
|
||||
|
|
|
@ -24,18 +24,13 @@
|
|||
package org.jclouds.atmosonline.saas.domain.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.jclouds.atmosonline.saas.domain.AtmosObject;
|
||||
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
|
||||
import org.jclouds.atmosonline.saas.domain.SystemMetadata;
|
||||
import org.jclouds.atmosonline.saas.domain.UserMetadata;
|
||||
import org.jclouds.blobstore.domain.MD5InputStreamResult;
|
||||
import org.jclouds.blobstore.functions.CalculateSize;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5Result;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
import org.jclouds.http.internal.BasePayloadEnclosingImpl;
|
||||
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
@ -45,67 +40,28 @@ import com.google.common.collect.Multimap;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class AtmosObjectImpl implements AtmosObject, Comparable<AtmosObject> {
|
||||
public class AtmosObjectImpl extends BasePayloadEnclosingImpl implements AtmosObject,
|
||||
Comparable<AtmosObject> {
|
||||
private final UserMetadata userMetadata;
|
||||
private final GenerateMD5Result generateMD5Result;
|
||||
private final GenerateMD5 generateMD5;
|
||||
private final CalculateSize calculateSize;
|
||||
private final MutableContentMetadata contentMetadata;
|
||||
private final SystemMetadata systemMetadata;
|
||||
private Object data;
|
||||
|
||||
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
||||
|
||||
public AtmosObjectImpl(GenerateMD5Result generateMD5Result, GenerateMD5 generateMD5,
|
||||
CalculateSize calculateSize, MutableContentMetadata contentMetadata) {
|
||||
this(generateMD5Result, generateMD5, calculateSize, contentMetadata, null, new UserMetadata());
|
||||
public AtmosObjectImpl(EncryptionService encryptionService,
|
||||
MutableContentMetadata contentMetadata) {
|
||||
this(encryptionService, contentMetadata, null, new UserMetadata());
|
||||
}
|
||||
|
||||
public AtmosObjectImpl(GenerateMD5Result generateMD5Result, GenerateMD5 generateMD5,
|
||||
CalculateSize calculateSize, MutableContentMetadata contentMetadata,
|
||||
SystemMetadata systemMetadata, UserMetadata userMetadata) {
|
||||
this.generateMD5Result = generateMD5Result;
|
||||
this.generateMD5 = generateMD5;
|
||||
this.calculateSize = calculateSize;
|
||||
public AtmosObjectImpl(EncryptionService encryptionService,
|
||||
MutableContentMetadata contentMetadata, SystemMetadata systemMetadata,
|
||||
UserMetadata userMetadata) {
|
||||
super(encryptionService);
|
||||
this.contentMetadata = contentMetadata;
|
||||
this.systemMetadata = systemMetadata;
|
||||
this.userMetadata = userMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void generateMD5() {
|
||||
checkState(data != null, "data");
|
||||
if (data instanceof InputStream) {
|
||||
MD5InputStreamResult result = generateMD5Result.apply((InputStream) data);
|
||||
getContentMetadata().setContentMD5(result.md5);
|
||||
getContentMetadata().setContentLength(result.length);
|
||||
setData(result.data);
|
||||
} else {
|
||||
getContentMetadata().setContentMD5(generateMD5.apply(data));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setData(Object data) {
|
||||
this.data = checkNotNull(data, "data");
|
||||
if (getContentMetadata().getContentLength() == null) {
|
||||
Long size = calculateSize.apply(data);
|
||||
if (size != null)
|
||||
getContentMetadata().setContentLength(size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -148,4 +104,19 @@ public class AtmosObjectImpl implements AtmosObject, Comparable<AtmosObject> {
|
|||
return userMetadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getContentLength() {
|
||||
return getContentMetadata().getContentLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentLength(long contentLength) {
|
||||
getContentMetadata().setContentLength(contentLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setContentMD5(byte[] md5) {
|
||||
getContentMetadata().setContentMD5(md5);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ public class ParseObjectFromHeadersAndHttpContent implements Function<HttpRespon
|
|||
AtmosObject object = objectProvider.create(systemMetadataParser.apply(from),
|
||||
userMetadataParser.apply(from));
|
||||
addAllHeadersTo(from, object);
|
||||
object.setData(from.getContent());
|
||||
object.setPayload(from.getContent());
|
||||
String contentLength = from.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH);
|
||||
if (contentLength != null) {
|
||||
object.getContentMetadata().setContentLength(Long.parseLong(contentLength));
|
||||
|
|
|
@ -27,7 +27,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.net.URI;
|
||||
import java.security.SecureRandom;
|
||||
|
@ -47,6 +46,8 @@ import org.jclouds.blobstore.KeyNotFoundException;
|
|||
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
|
||||
import org.jclouds.blobstore.strategy.ClearContainerStrategy;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.http.Payloads;
|
||||
import org.jclouds.http.payloads.InputStreamPayload;
|
||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||
import org.jclouds.rest.RestContext;
|
||||
import org.jclouds.util.Utils;
|
||||
|
@ -225,7 +226,7 @@ public class AtmosStorageClientLiveTest {
|
|||
// Test PUT with string data, ETag hash, and a piece of metadata
|
||||
AtmosObject object = connection.newObject();
|
||||
object.getContentMetadata().setName(name);
|
||||
object.setData(data);
|
||||
object.setPayload(Payloads.newPayload(data));
|
||||
object.getContentMetadata().setContentLength(16);
|
||||
object.generateMD5();
|
||||
object.getContentMetadata().setContentType("text/plain");
|
||||
|
@ -273,7 +274,7 @@ public class AtmosStorageClientLiveTest {
|
|||
String metadataValue) throws InterruptedException, ExecutionException,
|
||||
TimeoutException, IOException {
|
||||
AtmosObject getBlob = connection.headFile(path);
|
||||
assertEquals(IOUtils.toString((InputStream) getBlob.getData()), "");
|
||||
assertEquals(IOUtils.toString(getBlob.getContent()), "");
|
||||
verifyMetadata(metadataValue, getBlob);
|
||||
}
|
||||
|
||||
|
@ -281,8 +282,7 @@ public class AtmosStorageClientLiveTest {
|
|||
String metadataValue) throws InterruptedException, ExecutionException,
|
||||
TimeoutException, IOException {
|
||||
AtmosObject getBlob = connection.readFile(path);
|
||||
assertEquals(getBlob.getData() instanceof String ? getBlob.getData() : IOUtils
|
||||
.toString((InputStream) getBlob.getData()), compare);
|
||||
assertEquals(IOUtils.toString(getBlob.getContent()), compare);
|
||||
verifyMetadata(metadataValue, getBlob);
|
||||
}
|
||||
|
||||
|
@ -326,14 +326,14 @@ public class AtmosStorageClientLiveTest {
|
|||
try {
|
||||
connection.createFile(privateDirectory, object);
|
||||
System.err.printf("%s %s; %dms%n", "created",
|
||||
object.getData() instanceof InputStream ? "stream" : "string", System
|
||||
object.getPayload() instanceof InputStreamPayload ? "stream" : "string", System
|
||||
.currentTimeMillis()
|
||||
- time);
|
||||
} catch (Exception e) {
|
||||
String message = (e.getCause().getCause() != null) ? e.getCause().getCause().getMessage()
|
||||
: e.getCause().getMessage();
|
||||
System.err.printf("failure %s %s; %dms: [%s]%n", "creating",
|
||||
object.getData() instanceof InputStream ? "stream" : "string", System
|
||||
object.getPayload() instanceof InputStreamPayload ? "stream" : "string", System
|
||||
.currentTimeMillis()
|
||||
- time, message);
|
||||
throw e;
|
||||
|
@ -386,7 +386,7 @@ public class AtmosStorageClientLiveTest {
|
|||
}
|
||||
if (failures > 0)
|
||||
System.err.printf("%d failures create/replacing %s%n", failures,
|
||||
object.getData() instanceof InputStream ? "stream" : "string");
|
||||
object.getPayload() instanceof InputStreamPayload ? "stream" : "string");
|
||||
}
|
||||
|
||||
private void checkSystemMetadataAndPutIfPresentReplaceStrategy(AtmosObject object)
|
||||
|
@ -404,14 +404,14 @@ public class AtmosStorageClientLiveTest {
|
|||
else
|
||||
connection.createFile(privateDirectory, object);
|
||||
System.err.printf("%s %s; %dms%n", update ? "updated" : "created",
|
||||
object.getData() instanceof InputStream ? "stream" : "string", System
|
||||
object.getPayload() instanceof InputStreamPayload ? "stream" : "string", System
|
||||
.currentTimeMillis()
|
||||
- time);
|
||||
} catch (Exception e) {
|
||||
String message = (e.getCause().getCause() != null) ? e.getCause().getCause().getMessage()
|
||||
: e.getCause().getMessage();
|
||||
System.err.printf("failure %s %s; %dms: [%s]%n", update ? "updating" : "creating", object
|
||||
.getData() instanceof InputStream ? "stream" : "string", System
|
||||
.getPayload() instanceof InputStreamPayload ? "stream" : "string", System
|
||||
.currentTimeMillis()
|
||||
- time, message);
|
||||
throw e;
|
||||
|
|
|
@ -82,7 +82,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
|
|||
assertRequestLineEquals(httpMethod,
|
||||
"GET http://accesspoint.emccis.com/rest/namespace HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": text/xml\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod,
|
||||
ParseDirectoryListFromContentAndHeaders.class);
|
||||
|
@ -101,7 +101,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
|
|||
assertRequestLineEquals(httpMethod,
|
||||
"GET http://accesspoint.emccis.com/rest/namespace/directory/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": text/xml\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod,
|
||||
ParseDirectoryListFromContentAndHeaders.class);
|
||||
|
@ -122,7 +122,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
|
|||
"GET http://accesspoint.emccis.com/rest/namespace HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT
|
||||
+ ": text/xml\nx-emc-limit: 1\nx-emc-token: asda\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod,
|
||||
ParseDirectoryListFromContentAndHeaders.class);
|
||||
|
@ -143,7 +143,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
|
|||
"GET http://accesspoint.emccis.com/rest/namespace/directory/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT
|
||||
+ ": text/xml\nx-emc-limit: 1\nx-emc-token: asda\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod,
|
||||
ParseDirectoryListFromContentAndHeaders.class);
|
||||
|
@ -161,7 +161,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
|
|||
assertRequestLineEquals(httpMethod,
|
||||
"POST http://accesspoint.emccis.com/rest/namespace/dir/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": */*\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod,
|
||||
ParseURIFromListOrLocationHeaderIf20x.class);
|
||||
|
@ -181,7 +181,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
|
|||
"POST http://accesspoint.emccis.com/rest/namespace/dir/hello HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT
|
||||
+ ": */*\nContent-Length: 5\nContent-Type: text/plain\n");
|
||||
assertEntityEquals(httpMethod, "hello");
|
||||
assertPayloadEquals(httpMethod, "hello");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod,
|
||||
ParseURIFromListOrLocationHeaderIf20x.class);
|
||||
|
@ -201,7 +201,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
|
|||
"PUT http://accesspoint.emccis.com/rest/namespace/dir/hello HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT
|
||||
+ ": */*\nContent-Length: 5\nContent-Type: text/plain\n");
|
||||
assertEntityEquals(httpMethod, "hello");
|
||||
assertPayloadEquals(httpMethod, "hello");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
|
@ -219,7 +219,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
|
|||
assertRequestLineEquals(httpMethod,
|
||||
"GET http://accesspoint.emccis.com/rest/namespace/dir/file HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": */*\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod,
|
||||
ParseObjectFromHeadersAndHttpContent.class);
|
||||
|
@ -237,7 +237,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
|
|||
assertRequestLineEquals(httpMethod,
|
||||
"HEAD http://accesspoint.emccis.com/rest/namespace/dir/file HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": */*\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSystemMetadataFromHeaders.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
|
@ -254,7 +254,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
|
|||
assertRequestLineEquals(httpMethod,
|
||||
"DELETE http://accesspoint.emccis.com/rest/namespace/dir/file HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": */*\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
|
|
|
@ -103,13 +103,13 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
|
|||
checkNotNull(request.getFirstHeaderOrNull(HttpHeaders.HOST),
|
||||
"request is not ready to sign; host not present");
|
||||
Multimap<String, String> decodedParams = RestAnnotationProcessor.parseQueryToMap(request
|
||||
.getEntity().toString());
|
||||
.getPayload().getRawContent().toString());
|
||||
addSigningParams(decodedParams);
|
||||
validateParams(decodedParams);
|
||||
String stringToSign = createStringToSign(request, decodedParams);
|
||||
String signature = signString(stringToSign);
|
||||
addSignature(decodedParams, signature);
|
||||
setEntity(request, decodedParams);
|
||||
setPayload(request, decodedParams);
|
||||
HttpUtils.logRequest(signatureLog, request, "<<");
|
||||
}
|
||||
|
||||
|
@ -128,8 +128,8 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
|
|||
return parts;
|
||||
}
|
||||
|
||||
void setEntity(GeneratedHttpRequest<?> request, Multimap<String, String> decodedParams) {
|
||||
request.setEntity(RestAnnotationProcessor.makeQueryLine(decodedParams,
|
||||
void setPayload(GeneratedHttpRequest<?> request, Multimap<String, String> decodedParams) {
|
||||
request.setPayload(RestAnnotationProcessor.makeQueryLine(decodedParams,
|
||||
new Comparator<Map.Entry<String, String>>() {
|
||||
public int compare(Entry<String, String> o1, Entry<String, String> o2) {
|
||||
if (o1.getKey().startsWith("Action")
|
||||
|
@ -209,8 +209,8 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
|
|||
}
|
||||
|
||||
public String createStringToSign(HttpRequest input) {
|
||||
return createStringToSign(input, RestAnnotationProcessor.parseQueryToMap(input.getEntity()
|
||||
.toString()));
|
||||
return createStringToSign(input, RestAnnotationProcessor.parseQueryToMap(input.getPayload()
|
||||
.getRawContent().toString()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,8 +36,8 @@ import javax.ws.rs.PUT;
|
|||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
|
||||
import org.jclouds.aws.s3.binders.BindACLToXMLEntity;
|
||||
import org.jclouds.aws.s3.binders.BindS3ObjectToEntity;
|
||||
import org.jclouds.aws.s3.binders.BindACLToXMLPayload;
|
||||
import org.jclouds.aws.s3.binders.BindS3ObjectToPayload;
|
||||
import org.jclouds.aws.s3.domain.AccessControlList;
|
||||
import org.jclouds.aws.s3.domain.BucketMetadata;
|
||||
import org.jclouds.aws.s3.domain.ListBucketResponse;
|
||||
|
@ -139,7 +139,7 @@ public interface S3AsyncClient {
|
|||
@ResponseParser(ParseETagHeader.class)
|
||||
Future<String> putObject(
|
||||
@HostPrefixParam String bucketName,
|
||||
@PathParam("key") @ParamParser(ObjectKey.class) @BinderParam(BindS3ObjectToEntity.class) S3Object object,
|
||||
@PathParam("key") @ParamParser(ObjectKey.class) @BinderParam(BindS3ObjectToPayload.class) S3Object object,
|
||||
PutObjectOptions... options);
|
||||
|
||||
/**
|
||||
|
@ -214,7 +214,7 @@ public interface S3AsyncClient {
|
|||
@Path("/")
|
||||
@QueryParams(keys = "acl")
|
||||
Future<Boolean> putBucketACL(@HostPrefixParam String bucketName,
|
||||
@BinderParam(BindACLToXMLEntity.class) AccessControlList acl);
|
||||
@BinderParam(BindACLToXMLPayload.class) AccessControlList acl);
|
||||
|
||||
/**
|
||||
* @see S3Client#getObjectACL
|
||||
|
@ -234,6 +234,6 @@ public interface S3AsyncClient {
|
|||
@QueryParams(keys = "acl")
|
||||
@Path("{key}")
|
||||
Future<Boolean> putObjectACL(@HostPrefixParam String bucketName, @PathParam("key") String key,
|
||||
@BinderParam(BindACLToXMLEntity.class) AccessControlList acl);
|
||||
@BinderParam(BindACLToXMLPayload.class) AccessControlList acl);
|
||||
|
||||
}
|
||||
|
|
|
@ -42,17 +42,17 @@ import org.jclouds.util.Utils;
|
|||
|
||||
import com.jamesmurty.utils.XMLBuilder;
|
||||
|
||||
public class BindACLToXMLEntity implements Binder {
|
||||
public class BindACLToXMLPayload implements Binder {
|
||||
|
||||
public void bindToRequest(HttpRequest request, Object entity) {
|
||||
AccessControlList from = (AccessControlList) entity;
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
AccessControlList from = (AccessControlList) payload;
|
||||
Properties outputProperties = new Properties();
|
||||
outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||
try {
|
||||
String stringEntity = generateBuilder(from).asString(outputProperties);
|
||||
String stringPayload = generateBuilder(from).asString(outputProperties);
|
||||
request.getHeaders().put(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_XML);
|
||||
request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, stringEntity.getBytes().length + "");
|
||||
request.setEntity(stringEntity);
|
||||
request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, stringPayload.getBytes().length + "");
|
||||
request.setPayload(stringPayload);
|
||||
} catch (Exception e) {
|
||||
Utils.rethrowIfRuntime(e);
|
||||
throw new RuntimeException("error transforming acl: " + from, e);
|
|
@ -31,23 +31,23 @@ import javax.ws.rs.core.HttpHeaders;
|
|||
|
||||
import org.jclouds.aws.s3.blobstore.functions.ObjectToBlob;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix;
|
||||
import org.jclouds.blobstore.binders.BindBlobToPayloadAndUserMetadataToHeadersWithPrefix;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.Binder;
|
||||
|
||||
public class BindS3ObjectToEntity implements Binder {
|
||||
private final BindBlobToEntityAndUserMetadataToHeadersWithPrefix blobBinder;
|
||||
public class BindS3ObjectToPayload implements Binder {
|
||||
private final BindBlobToPayloadAndUserMetadataToHeadersWithPrefix blobBinder;
|
||||
private final ObjectToBlob object2Blob;
|
||||
|
||||
@Inject
|
||||
public BindS3ObjectToEntity(ObjectToBlob object2Blob,
|
||||
BindBlobToEntityAndUserMetadataToHeadersWithPrefix blobBinder) {
|
||||
public BindS3ObjectToPayload(ObjectToBlob object2Blob,
|
||||
BindBlobToPayloadAndUserMetadataToHeadersWithPrefix blobBinder) {
|
||||
this.blobBinder = blobBinder;
|
||||
this.object2Blob = object2Blob;
|
||||
}
|
||||
|
||||
public void bindToRequest(HttpRequest request, Object entity) {
|
||||
S3Object s3Object = (S3Object) entity;
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
S3Object s3Object = (S3Object) payload;
|
||||
checkNotNull(s3Object.getContentLength(), "contentLength");
|
||||
checkArgument(s3Object.getContentLength() <= 5 * 1024 * 1024 * 1024,
|
||||
"maximum size for put object is 5GB");
|
|
@ -49,7 +49,7 @@ public class BlobToObject implements Function<Blob, S3Object> {
|
|||
S3Object object = objectProvider.create(blob2ObjectMd.apply(from.getMetadata()));
|
||||
if (from.getContentLength() != null)
|
||||
object.setContentLength(from.getContentLength());
|
||||
object.setData(from.getData());
|
||||
object.setPayload(from.getPayload());
|
||||
object.setAllHeaders(from.getAllHeaders());
|
||||
return object;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public class ObjectToBlob implements Function<S3Object, Blob> {
|
|||
Blob blob = blobFactory.create(object2BlobMd.apply(from.getMetadata()));
|
||||
if (from.getContentLength() != null)
|
||||
blob.setContentLength(from.getContentLength());
|
||||
blob.setData(from.getData());
|
||||
blob.setPayload(from.getPayload());
|
||||
blob.setAllHeaders(from.getAllHeaders());
|
||||
return blob;
|
||||
}
|
||||
|
|
|
@ -29,9 +29,7 @@ import javax.inject.Provider;
|
|||
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.aws.s3.domain.internal.S3ObjectImpl;
|
||||
import org.jclouds.blobstore.functions.CalculateSize;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5Result;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
@ -44,7 +42,6 @@ import com.google.inject.Scopes;
|
|||
*/
|
||||
public class S3ObjectModule extends AbstractModule {
|
||||
|
||||
|
||||
/**
|
||||
* explicit factories are created here as it has been shown that Assisted Inject is extremely
|
||||
* inefficient. http://code.google.com/p/google-guice/issues/detail?id=435
|
||||
|
@ -56,17 +53,13 @@ public class S3ObjectModule extends AbstractModule {
|
|||
|
||||
private static class S3ObjectFactory implements S3Object.Factory {
|
||||
@Inject
|
||||
GenerateMD5Result generateMD5Result;
|
||||
@Inject
|
||||
GenerateMD5 generateMD5;
|
||||
@Inject
|
||||
CalculateSize calculateSize;
|
||||
EncryptionService encryptionService;
|
||||
@Inject
|
||||
Provider<MutableObjectMetadata> metadataProvider;
|
||||
|
||||
public S3Object create(MutableObjectMetadata metadata) {
|
||||
return new S3ObjectImpl(generateMD5Result, generateMD5, calculateSize,
|
||||
metadata != null ? metadata : metadataProvider.get());
|
||||
return new S3ObjectImpl(encryptionService, metadata != null ? metadata : metadataProvider
|
||||
.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,9 +40,9 @@ import com.google.common.collect.Collections2;
|
|||
* An Access Control List (ACL) describes the access control settings for a bucket or object in S3.
|
||||
*
|
||||
* ACL settings comprise a set of {@link Grant}s, each of which specifies a {@link Permission} that
|
||||
* has been granted to a specific {@link Grantee}. If an entity tries to access or modify an item in
|
||||
* has been granted to a specific {@link Grantee}. If an payload tries to access or modify an item in
|
||||
* S3, the operation will be denied unless the item has ACL settings that explicitly permit that
|
||||
* entity to perform that action.
|
||||
* payload to perform that action.
|
||||
*
|
||||
*
|
||||
* @author James Murty
|
||||
|
|
|
@ -23,66 +23,25 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.domain;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.jclouds.http.PayloadEnclosing;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.inject.internal.Nullable;
|
||||
|
||||
/**
|
||||
* Amazon S3 is designed to store objects. Objects are stored in buckets and consist of a
|
||||
* {@link ObjectMetadataS3Object#getData() value}, a {@link ObjectMetadata#getKey key},
|
||||
* {@link ObjectMetadataS3Object#getContent() value}, a {@link ObjectMetadata#getKey key},
|
||||
* {@link ObjectMetadata#getUserMetadata() metadata}, and an access control policy.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html"
|
||||
* />
|
||||
*/
|
||||
public interface S3Object extends Comparable<S3Object> {
|
||||
public interface S3Object extends PayloadEnclosing, Comparable<S3Object> {
|
||||
public interface Factory {
|
||||
S3Object create(@Nullable MutableObjectMetadata metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets entity for the request or the content from the response. If size isn't set, this will
|
||||
* attempt to discover it.
|
||||
*
|
||||
* @param data
|
||||
* typically InputStream for downloads, or File, byte [], String, or InputStream for
|
||||
* uploads.
|
||||
*/
|
||||
void setData(Object data);
|
||||
|
||||
/**
|
||||
* @return InputStream, if downloading, or whatever was set during {@link #setData(Object)}
|
||||
*/
|
||||
Object getData();
|
||||
|
||||
/**
|
||||
* generate an MD5 Hash for the current data.
|
||||
* <p/>
|
||||
* <h2>Note</h2>
|
||||
* <p/>
|
||||
* If this is an InputStream, it will be converted to a byte array first.
|
||||
*
|
||||
* @throws IOException
|
||||
* if there is a problem generating the hash.
|
||||
*/
|
||||
void generateMD5() throws IOException;
|
||||
|
||||
void setContentLength(long contentLength);
|
||||
|
||||
/**
|
||||
* 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 #getData()}
|
||||
* @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
|
||||
* @see GetObjectOptions
|
||||
*/
|
||||
Long getContentLength();
|
||||
|
||||
/**
|
||||
* @return System and User metadata relevant to this object.
|
||||
*/
|
||||
|
|
|
@ -24,19 +24,14 @@
|
|||
package org.jclouds.aws.s3.domain.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.aws.s3.domain.AccessControlList;
|
||||
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.blobstore.domain.MD5InputStreamResult;
|
||||
import org.jclouds.blobstore.functions.CalculateSize;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5Result;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
import org.jclouds.http.internal.BasePayloadEnclosingImpl;
|
||||
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
@ -46,25 +41,22 @@ import com.google.common.collect.Multimap;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class S3ObjectImpl implements S3Object, Comparable<S3Object> {
|
||||
private final GenerateMD5Result generateMD5Result;
|
||||
private final GenerateMD5 generateMD5;
|
||||
private final CalculateSize calculateSize;
|
||||
public class S3ObjectImpl extends BasePayloadEnclosingImpl implements S3Object,
|
||||
Comparable<S3Object> {
|
||||
private final MutableObjectMetadata metadata;
|
||||
private Object data;
|
||||
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
||||
private Long contentLength;
|
||||
private AccessControlList accessControlList;
|
||||
|
||||
@Inject
|
||||
public S3ObjectImpl(GenerateMD5Result generateMD5Result, GenerateMD5 generateMD5,
|
||||
CalculateSize calculateSize, MutableObjectMetadata metadata) {
|
||||
this.generateMD5Result = generateMD5Result;
|
||||
this.generateMD5 = generateMD5;
|
||||
this.calculateSize = calculateSize;
|
||||
public S3ObjectImpl(EncryptionService encryptionService, MutableObjectMetadata metadata) {
|
||||
super(encryptionService);
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
private AccessControlList accessControlList;
|
||||
@Override
|
||||
protected void setContentMD5(byte[] md5) {
|
||||
getMetadata().setContentMD5(md5);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
@ -80,54 +72,6 @@ public class S3ObjectImpl implements S3Object, Comparable<S3Object> {
|
|||
return this.accessControlList;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void generateMD5() {
|
||||
checkState(data != null, "data");
|
||||
if (data instanceof InputStream) {
|
||||
MD5InputStreamResult result = generateMD5Result.apply((InputStream) data);
|
||||
getMetadata().setContentMD5(result.md5);
|
||||
setContentLength(result.length);
|
||||
setData(result.data);
|
||||
} else {
|
||||
getMetadata().setContentMD5(generateMD5.apply(data));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setData(Object data) {
|
||||
this.data = checkNotNull(data, "data");
|
||||
if (getContentLength() == null) {
|
||||
Long size = calculateSize.apply(data);
|
||||
if (size != null)
|
||||
this.setContentLength(size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Long getContentLength() {
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setContentLength(long contentLength) {
|
||||
this.contentLength = contentLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -165,7 +109,7 @@ public class S3ObjectImpl implements S3Object, Comparable<S3Object> {
|
|||
result = prime * result + ((accessControlList == null) ? 0 : accessControlList.hashCode());
|
||||
result = prime * result + ((allHeaders == null) ? 0 : allHeaders.hashCode());
|
||||
result = prime * result + ((contentLength == null) ? 0 : contentLength.hashCode());
|
||||
result = prime * result + ((data == null) ? 0 : data.hashCode());
|
||||
result = prime * result + ((payload == null) ? 0 : payload.hashCode());
|
||||
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
@ -194,10 +138,10 @@ public class S3ObjectImpl implements S3Object, Comparable<S3Object> {
|
|||
return false;
|
||||
} else if (!contentLength.equals(other.contentLength))
|
||||
return false;
|
||||
if (data == null) {
|
||||
if (other.data != null)
|
||||
if (payload == null) {
|
||||
if (other.payload != null)
|
||||
return false;
|
||||
} else if (!data.equals(other.data))
|
||||
} else if (!payload.equals(other.payload))
|
||||
return false;
|
||||
if (metadata == null) {
|
||||
if (other.metadata != null)
|
||||
|
|
|
@ -66,7 +66,7 @@ public class ParseObjectFromHeadersAndHttpContent implements Function<HttpRespon
|
|||
public S3Object apply(HttpResponse from) {
|
||||
S3Object object = objectProvider.create(metadataParser.apply(from));
|
||||
addAllHeadersTo(from, object);
|
||||
object.setData(from.getContent());
|
||||
object.setPayload(from.getContent());
|
||||
attemptToParseSizeAndRangeFromHeaders(from, object);
|
||||
return object;
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
|
|||
/**
|
||||
* For use in the request header: x-amz-copy-source-if-match
|
||||
* <p/>
|
||||
* Copies the object if its entity tag (ETag) matches the specified tag; otherwise return a 412
|
||||
* Copies the object if its payload tag (ETag) matches the specified tag; otherwise return a 412
|
||||
* (precondition failed).
|
||||
* <p/>
|
||||
* This header can be used with x-amz-copy-source-if-unmodified-since, but cannot be used with
|
||||
|
@ -160,7 +160,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
|
|||
/**
|
||||
* For use in the request header: x-amz-copy-source-if-none-match
|
||||
* <p/>
|
||||
* Copies the object if its entity tag (ETag) is different than the specified Etag; otherwise
|
||||
* Copies the object if its payload tag (ETag) is different than the specified Etag; otherwise
|
||||
* returns a 412 (failed condition).
|
||||
* <p/>
|
||||
* This header can be used with x-amz-copy-source-if-modified-since, but cannot be used with
|
||||
|
@ -221,7 +221,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
|
|||
* {@link #ifSourceModifiedSince(Date)}
|
||||
*
|
||||
* @param eTag
|
||||
* hash representing the entity
|
||||
* hash representing the payload
|
||||
*/
|
||||
public CopyObjectOptions ifSourceETagMatches(String eTag) throws UnsupportedEncodingException {
|
||||
checkState(getIfNoneMatch() == null,
|
||||
|
@ -240,7 +240,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
|
|||
* {@link #ifSourceUnmodifiedSince(Date)}
|
||||
*
|
||||
* @param eTag
|
||||
* hash representing the entity
|
||||
* hash representing the payload
|
||||
* @throws UnsupportedEncodingException
|
||||
* if there was a problem converting this into an S3 eTag string
|
||||
*/
|
||||
|
|
|
@ -61,7 +61,7 @@ public class PutBucketOptions extends BaseHttpRequestOptions {
|
|||
*/
|
||||
public PutBucketOptions createIn(LocationConstraint constraint) {
|
||||
this.constraint = checkNotNull(constraint, "constraint");
|
||||
this.entity = String
|
||||
this.payload = String
|
||||
.format(
|
||||
"<CreateBucketConfiguration><LocationConstraint>%1$s</LocationConstraint></CreateBucketConfiguration>",
|
||||
constraint.toString());
|
||||
|
|
|
@ -83,9 +83,9 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 40\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod, "Version=2009-08-15&Action=DescribeImages");
|
||||
assertPayloadEquals(httpMethod, "Version=2009-08-15&Action=DescribeImages");
|
||||
filter.filter(httpMethod);
|
||||
assertEntityEquals(
|
||||
assertPayloadEquals(
|
||||
httpMethod,
|
||||
"Action=DescribeImages&Signature=wJmKTnrx5v3PSECZJjm%2BE1s8I%2FqHkVs2K1hJ6yxbpC0%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2009-11-08T15%3A54%3A08.897Z&Version=2009-08-15&AWSAccessKeyId=user");
|
||||
|
||||
|
@ -106,7 +106,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 107\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(
|
||||
assertPayloadEquals(
|
||||
httpMethod,
|
||||
"Version=2009-08-15&Action=DescribeImages&ExecutableBy=me&Owner.1=fred&Owner.2=nancy&ImageId.1=1&ImageId.2=2");
|
||||
|
||||
|
@ -127,10 +127,10 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 93\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod,
|
||||
assertPayloadEquals(httpMethod,
|
||||
"Version=2009-08-15&Action=DescribeImageAttribute&ImageId=imageId&Attribute=blockDeviceMapping");
|
||||
filter.filter(httpMethod);
|
||||
assertEntityEquals(
|
||||
assertPayloadEquals(
|
||||
httpMethod,
|
||||
"Action=DescribeImageAttribute&Attribute=blockDeviceMapping&ImageId=imageId&Signature=IiyxXwoOmpLiPC%2BbfBdqJwE758bvbs8kXCL71FefStY%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2009-11-08T15%3A54%3A08.897Z&Version=2009-08-15&AWSAccessKeyId=user");
|
||||
|
||||
|
@ -149,7 +149,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 43\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod, "Version=2009-08-15&Action=DescribeInstances");
|
||||
assertPayloadEquals(httpMethod, "Version=2009-08-15&Action=DescribeInstances");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, DescribeInstancesResponseHandler.class);
|
||||
|
@ -167,7 +167,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 43\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod,
|
||||
assertPayloadEquals(httpMethod,
|
||||
"Version=2009-08-15&Action=DescribeInstances&InstanceId.1=1&InstanceId.2=2");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
|
@ -186,7 +186,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 59\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod,
|
||||
assertPayloadEquals(httpMethod,
|
||||
"Version=2009-08-15&Action=TerminateInstances&InstanceId.0=1&InstanceId.1=2");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
|
@ -204,7 +204,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 76\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod,
|
||||
assertPayloadEquals(httpMethod,
|
||||
"Version=2009-08-15&Action=RunInstances&ImageId=ami-voo&MaxCount=1&MinCount=1");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
|
@ -224,7 +224,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 118\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(
|
||||
assertPayloadEquals(
|
||||
httpMethod,
|
||||
"Version=2009-08-15&Action=RunInstances&ImageId=ami-voo&MaxCount=5&MinCount=1&KernelId=kernelId&Monitoring.Enabled=true");
|
||||
|
||||
|
@ -242,7 +242,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 53\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod, "Version=2009-08-15&Action=CreateKeyPair&KeyName=mykey");
|
||||
assertPayloadEquals(httpMethod, "Version=2009-08-15&Action=CreateKeyPair&KeyName=mykey");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, KeyPairResponseHandler.class);
|
||||
|
@ -260,7 +260,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 64\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod,
|
||||
assertPayloadEquals(httpMethod,
|
||||
"Version=2009-08-15&Action=DisassociateAddress&PublicIp=127.0.0.1");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
|
||||
|
@ -279,7 +279,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 75\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod,
|
||||
assertPayloadEquals(httpMethod,
|
||||
"Version=2009-08-15&Action=AssociateAddress&PublicIp=127.0.0.1&InstanceId=me");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
|
||||
|
@ -297,7 +297,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 59\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod, "Version=2009-08-15&Action=ReleaseAddress&PublicIp=127.0.0.1");
|
||||
assertPayloadEquals(httpMethod, "Version=2009-08-15&Action=ReleaseAddress&PublicIp=127.0.0.1");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
|
@ -315,7 +315,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 43\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod,
|
||||
assertPayloadEquals(httpMethod,
|
||||
"Version=2009-08-15&Action=DescribeAddresses&PublicIp.1=127.0.0.1");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
|
@ -332,7 +332,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 41\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod, "Version=2009-08-15&Action=AllocateAddress");
|
||||
assertPayloadEquals(httpMethod, "Version=2009-08-15&Action=AllocateAddress");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, AllocateAddressResponseHandler.class);
|
||||
|
@ -348,7 +348,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 53\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod, "Version=2009-08-15&Action=DeleteKeyPair&KeyName=mykey");
|
||||
assertPayloadEquals(httpMethod, "Version=2009-08-15&Action=DeleteKeyPair&KeyName=mykey");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
|
@ -365,7 +365,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 42\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod, "Version=2009-08-15&Action=DescribeKeyPairs");
|
||||
assertPayloadEquals(httpMethod, "Version=2009-08-15&Action=DescribeKeyPairs");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, DescribeKeyPairsResponseHandler.class);
|
||||
|
@ -383,7 +383,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 42\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod,
|
||||
assertPayloadEquals(httpMethod,
|
||||
"Version=2009-08-15&Action=DescribeKeyPairs&KeyName.1=1&KeyName.2=2");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
|
@ -401,7 +401,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 60\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod, "Version=2009-08-15&Action=DeleteSecurityGroup&GroupName=name");
|
||||
assertPayloadEquals(httpMethod, "Version=2009-08-15&Action=DeleteSecurityGroup&GroupName=name");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
|
@ -419,7 +419,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 89\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod,
|
||||
assertPayloadEquals(httpMethod,
|
||||
"Version=2009-08-15&Action=CreateSecurityGroup&GroupName=name&GroupDescription=description");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
|
||||
|
@ -438,7 +438,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 48\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod, "Version=2009-08-15&Action=DescribeSecurityGroups");
|
||||
assertPayloadEquals(httpMethod, "Version=2009-08-15&Action=DescribeSecurityGroups");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, DescribeSecurityGroupsResponseHandler.class);
|
||||
|
@ -456,7 +456,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 48\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(httpMethod,
|
||||
assertPayloadEquals(httpMethod,
|
||||
"Version=2009-08-15&Action=DescribeSecurityGroups&GroupName.1=1&GroupName.2=2");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
|
@ -476,7 +476,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 71\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(
|
||||
assertPayloadEquals(
|
||||
httpMethod,
|
||||
"Version=2009-08-15&Action=AuthorizeSecurityGroupIngress&GroupName=group&SourceSecurityGroupOwnerId=sourceUser&SourceSecurityGroupName=sourceGroup");
|
||||
|
||||
|
@ -497,7 +497,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 131\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(
|
||||
assertPayloadEquals(
|
||||
httpMethod,
|
||||
"Version=2009-08-15&Action=AuthorizeSecurityGroupIngress&GroupName=group&FromPort=6000&IpProtocol=tcp&ToPort=7000&CidrIp=0.0.0.0%2F0");
|
||||
|
||||
|
@ -518,7 +518,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 68\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(
|
||||
assertPayloadEquals(
|
||||
httpMethod,
|
||||
"Version=2009-08-15&Action=RevokeSecurityGroupIngress&GroupName=group&SourceSecurityGroupOwnerId=sourceUser&SourceSecurityGroupName=sourceGroup");
|
||||
|
||||
|
@ -539,7 +539,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 128\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
|
||||
assertEntityEquals(
|
||||
assertPayloadEquals(
|
||||
httpMethod,
|
||||
"Version=2009-08-15&Action=RevokeSecurityGroupIngress&GroupName=group&FromPort=6000&IpProtocol=tcp&ToPort=7000&CidrIp=0.0.0.0%2F0");
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ import static org.testng.Assert.assertFalse;
|
|||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
|
@ -104,7 +103,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
|
|||
String key = "hello";
|
||||
S3Object object = context.getApi().newS3Object();
|
||||
object.getMetadata().setKey(key);
|
||||
object.setData(TEST_STRING);
|
||||
object.setPayload(TEST_STRING);
|
||||
context.getApi().putObject(containerName, object,
|
||||
|
||||
withAcl(CannedAccessPolicy.PUBLIC_READ));
|
||||
|
@ -149,7 +148,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
|
|||
try {
|
||||
S3Object object = context.getApi().newS3Object();
|
||||
object.getMetadata().setKey(publicReadWriteObjectKey);
|
||||
object.setData("");
|
||||
object.setPayload("");
|
||||
// Public Read-Write object
|
||||
context.getApi().putObject(containerName, object,
|
||||
new PutObjectOptions().withAcl(CannedAccessPolicy.PUBLIC_READ_WRITE));
|
||||
|
@ -252,7 +251,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
|
|||
try {
|
||||
S3Object object = context.getApi().newS3Object();
|
||||
object.getMetadata().setKey(publicReadObjectKey);
|
||||
object.setData("");
|
||||
object.setPayload("");
|
||||
context.getApi().putObject(containerName, object,
|
||||
new PutObjectOptions().withAcl(CannedAccessPolicy.PUBLIC_READ));
|
||||
|
||||
|
@ -284,7 +283,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
|
|||
S3Object sourceObject = context.getApi().newS3Object();
|
||||
sourceObject.getMetadata().setKey(key);
|
||||
sourceObject.getMetadata().setContentType("text/xml");
|
||||
sourceObject.setData(TEST_STRING);
|
||||
sourceObject.setPayload(TEST_STRING);
|
||||
return context.getApi().putObject(sourceContainer, sourceObject);
|
||||
}
|
||||
|
||||
|
@ -293,7 +292,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
|
|||
assertConsistencyAwareContainerSize(sourceContainer, 1);
|
||||
S3Object newObject = context.getApi().getObject(sourceContainer, key);
|
||||
assert newObject != null;
|
||||
assertEquals(Utils.toStringAndClose((InputStream) newObject.getData()), TEST_STRING);
|
||||
assertEquals(Utils.toStringAndClose(newObject.getContent()), TEST_STRING);
|
||||
return newObject;
|
||||
}
|
||||
|
||||
|
@ -302,7 +301,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
|
|||
|
||||
S3Object object = context.getApi().newS3Object();
|
||||
object.getMetadata().setKey(key);
|
||||
object.setData(TEST_STRING);
|
||||
object.setPayload(TEST_STRING);
|
||||
object.getMetadata().setCacheControl("no-cache");
|
||||
object.getMetadata().setContentDisposition("attachment; filename=hello.txt");
|
||||
String containerName = getContainerName();
|
||||
|
@ -325,7 +324,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
|
|||
|
||||
S3Object object = context.getApi().newS3Object();
|
||||
object.getMetadata().setKey(key);
|
||||
object.setData(TEST_STRING);
|
||||
object.setPayload(TEST_STRING);
|
||||
object.getMetadata().setContentEncoding("x-compress");
|
||||
String containerName = getContainerName();
|
||||
try {
|
||||
|
@ -619,7 +618,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
|
|||
for (char letter = 'a'; letter <= 'z'; letter++) {
|
||||
S3Object blob = context.getApi().newS3Object();
|
||||
blob.getMetadata().setKey(letter + "");
|
||||
blob.setData(letter + "content");
|
||||
blob.setPayload(letter + "content");
|
||||
context.getApi().putObject(containerName, blob);
|
||||
}
|
||||
}
|
||||
|
@ -694,7 +693,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
|
|||
for (int i = 0; i < 15; i++) {
|
||||
S3Object blob = context.getApi().newS3Object();
|
||||
blob.getMetadata().setKey(i + "");
|
||||
blob.setData(i + "content");
|
||||
blob.setPayload(i + "content");
|
||||
context.getApi().putObject(containerName, blob);
|
||||
}
|
||||
}
|
||||
|
@ -703,7 +702,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
|
|||
for (int i = 0; i < 10; i++) {
|
||||
S3Object blob = context.getApi().newS3Object();
|
||||
blob.getMetadata().setKey(prefix + "/" + i);
|
||||
blob.setData(i + "content");
|
||||
blob.setPayload(i + "content");
|
||||
context.getApi().putObject(containerName, blob);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
|
|||
|
||||
assertRequestLineEquals(httpMethod, "GET http://bucket.stub:8080/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, ListBucketHandler.class);
|
||||
|
@ -106,7 +106,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
|
|||
|
||||
assertRequestLineEquals(httpMethod, "HEAD http://bucket.stub:8080/?max-keys=0 HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
|
@ -127,7 +127,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
|
|||
"PUT http://destinationBucket.stub:8080/destinationObject HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 0\nHost: destinationBucket.stub\nx-amz-copy-source: /sourceBucket/sourceObject\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, CopyObjectHandler.class);
|
||||
|
@ -143,7 +143,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
|
|||
|
||||
assertRequestLineEquals(httpMethod, "DELETE http://bucket.stub:8080/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
|
@ -159,7 +159,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
|
|||
|
||||
assertRequestLineEquals(httpMethod, "DELETE http://bucket.stub:8080/object HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
|
@ -175,7 +175,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
|
|||
|
||||
assertRequestLineEquals(httpMethod, "GET http://bucket.stub:8080/?acl HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, AccessControlListHandler.class);
|
||||
|
@ -193,7 +193,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
|
|||
|
||||
assertRequestLineEquals(httpMethod, "GET http://bucket.stub:8080/object HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod,
|
||||
ParseObjectFromHeadersAndHttpContent.class);
|
||||
|
@ -211,7 +211,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
|
|||
|
||||
assertRequestLineEquals(httpMethod, "GET http://bucket.stub:8080/object?acl HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, AccessControlListHandler.class);
|
||||
|
@ -228,7 +228,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
|
|||
|
||||
assertRequestLineEquals(httpMethod, "HEAD http://bucket.stub:8080/object HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseObjectMetadataFromHeaders.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
|
@ -243,7 +243,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
|
|||
|
||||
assertRequestLineEquals(httpMethod, "GET http://stub:8080/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, "Host: stub\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, ListAllMyBucketsHandler.class);
|
||||
|
@ -266,7 +266,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "PUT http://bucket.stub:8080/?acl HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 321\nContent-Type: text/xml\nHost: bucket.stub\n");
|
||||
assertEntityEquals(
|
||||
assertPayloadEquals(
|
||||
httpMethod,
|
||||
"<AccessControlPolicy xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Owner><ID>1234</ID></Owner><AccessControlList><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CanonicalUser\"><ID>1234</ID></Grantee><Permission>FULL_CONTROL</Permission></Grant></AccessControlList></AccessControlPolicy>");
|
||||
|
||||
|
@ -285,7 +285,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
|
|||
|
||||
assertRequestLineEquals(httpMethod, "PUT http://bucket.stub:8080/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, "Content-Length: 0\nHost: bucket.stub\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
|
@ -305,7 +305,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "PUT http://bucket.stub:8080/hello HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 5\nContent-Type: text/plain\nHost: bucket.stub\n");
|
||||
assertEntityEquals(httpMethod, "hello");
|
||||
assertPayloadEquals(httpMethod, "hello");
|
||||
|
||||
assertResponseParserClassEquals(method, httpMethod, ParseETagHeader.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
|
@ -323,7 +323,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
|
|||
assertRequestLineEquals(httpMethod, "PUT http://bucket.stub:8080/key?acl HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 321\nContent-Type: text/xml\nHost: bucket.stub\n");
|
||||
assertEntityEquals(
|
||||
assertPayloadEquals(
|
||||
httpMethod,
|
||||
"<AccessControlPolicy xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Owner><ID>1234</ID></Owner><AccessControlList><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CanonicalUser\"><ID>1234</ID></Grantee><Permission>FULL_CONTROL</Permission></Grant></AccessControlList></AccessControlPolicy>");
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ public class StubS3AsyncClient implements S3AsyncClient {
|
|||
|
||||
newMd.setLastModified(new Date());
|
||||
Blob newBlob = blobProvider.create(newMd);
|
||||
newBlob.setData(sourceS3.getData());
|
||||
newBlob.setPayload(sourceS3.getContent());
|
||||
dest.put(destinationObject, newBlob);
|
||||
return blob2ObjectMetadata.apply(blobStore.copy(newMd));
|
||||
}
|
||||
|
|
|
@ -54,11 +54,11 @@ public class PutBucketOptionsTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testEntity() {
|
||||
public void testPayload() {
|
||||
PutBucketOptions options = new PutBucketOptions();
|
||||
options.createIn(LocationConstraint.EU);
|
||||
assertEquals(
|
||||
options.buildStringEntity(),
|
||||
options.buildStringPayload(),
|
||||
"<CreateBucketConfiguration><LocationConstraint>EU</LocationConstraint></CreateBucketConfiguration>");
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ public class MainApp {
|
|||
|
||||
Blob blob = blobStore.newBlob();
|
||||
blob.getMetadata().setName("test");
|
||||
blob.setData("testdata");
|
||||
blob.setPayload("testdata");
|
||||
blobStore.putBlob(containerName, blob);
|
||||
|
||||
// List Container
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.jets3t;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
|
@ -114,8 +113,8 @@ public class Util {
|
|||
|
||||
public static S3Object convertObject(org.jclouds.aws.s3.domain.S3Object jcObject) {
|
||||
S3Object jsObject = convertObjectHead(jcObject.getMetadata());
|
||||
if (jcObject.getData() != null) {
|
||||
jsObject.setDataInputStream((InputStream) jcObject.getData());
|
||||
if (jcObject.getContent() != null) {
|
||||
jsObject.setDataInputStream(jcObject.getContent());
|
||||
}
|
||||
return jsObject;
|
||||
}
|
||||
|
@ -149,9 +148,9 @@ public class Util {
|
|||
}
|
||||
|
||||
if (jsObject.getDataInputStream() != null) {
|
||||
jcObject.setData(jsObject.getDataInputStream());
|
||||
jcObject.setPayload(jsObject.getDataInputStream());
|
||||
} else {
|
||||
jcObject.setData(""); // Must explicitly set data for empty jClouds objects.
|
||||
jcObject.setPayload(""); // Must explicitly set data for empty jClouds objects.
|
||||
}
|
||||
|
||||
if (jsObject.getContentType() != null) {
|
||||
|
|
|
@ -134,7 +134,7 @@ public class JCloudsS3ServiceLiveTest extends BaseBlobStoreIntegrationTest<S3Asy
|
|||
String objectValue = "test";
|
||||
Blob blob = context.getAsyncBlobStore().newBlob();
|
||||
blob.getMetadata().setName(objectKey);
|
||||
blob.setData(objectValue);
|
||||
blob.setPayload(objectValue);
|
||||
addBlobToContainer(bucketName, blob);
|
||||
|
||||
service.deleteObject(bucketName, objectKey);
|
||||
|
@ -155,7 +155,7 @@ public class JCloudsS3ServiceLiveTest extends BaseBlobStoreIntegrationTest<S3Asy
|
|||
|
||||
Blob blob = context.getAsyncBlobStore().newBlob();
|
||||
blob.getMetadata().setName(objectKey);
|
||||
blob.setData(objectValue);
|
||||
blob.setPayload(objectValue);
|
||||
blob.getMetadata().getUserMetadata().put(metadataName, metadataValue);
|
||||
addBlobToContainer(bucketName, blob);
|
||||
|
||||
|
@ -182,7 +182,7 @@ public class JCloudsS3ServiceLiveTest extends BaseBlobStoreIntegrationTest<S3Asy
|
|||
|
||||
Blob blob = context.getAsyncBlobStore().newBlob();
|
||||
blob.getMetadata().setName(objectKey);
|
||||
blob.setData(objectValue);
|
||||
blob.setPayload(objectValue);
|
||||
blob.getMetadata().getUserMetadata().put(metadataName, metadataValue);
|
||||
addBlobToContainer(bucketName, blob);
|
||||
|
||||
|
@ -441,7 +441,7 @@ public class JCloudsS3ServiceLiveTest extends BaseBlobStoreIntegrationTest<S3Asy
|
|||
|
||||
Blob blob = context.getAsyncBlobStore().newBlob();
|
||||
blob.getMetadata().setName(sourceObjectKey);
|
||||
blob.setData(data);
|
||||
blob.setPayload(data);
|
||||
blob.getMetadata().getUserMetadata().put(metadataName, sourceMetadataValue);
|
||||
addBlobToContainer(bucketName, blob);
|
||||
|
||||
|
|
|
@ -44,8 +44,8 @@ public abstract class BaseJCloudsPerformanceLiveTest extends BasePerformanceLive
|
|||
// object.setKey(id + "");
|
||||
// //object.setContentType("text/plain");
|
||||
// object.setContentType("application/octetstream");
|
||||
// //object.setData("this is a test");
|
||||
// object.setData(test);
|
||||
// //object.setPayload("this is a test");
|
||||
// object.setPayload(test);
|
||||
// return context.getApi()Provider.getObject(s3Bucket,
|
||||
// object.getKey()).get(120,TimeUnit.SECONDS) !=
|
||||
// S3Object.NOT_FOUND;
|
||||
|
@ -57,7 +57,7 @@ public abstract class BaseJCloudsPerformanceLiveTest extends BasePerformanceLive
|
|||
throws Exception {
|
||||
S3Object object = newObject(key);
|
||||
object.getMetadata().setContentType(contentType);
|
||||
object.setData(data);
|
||||
object.setPayload(data);
|
||||
return context.getApi().putObject(bucket, object) != null;
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ public abstract class BaseJCloudsPerformanceLiveTest extends BasePerformanceLive
|
|||
throws Exception {
|
||||
S3Object object = newObject(key);
|
||||
object.getMetadata().setContentType(contentType);
|
||||
object.setData(data);
|
||||
object.setPayload(data);
|
||||
return context.getApi().putObject(bucket, object) != null;
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ public abstract class BaseJCloudsPerformanceLiveTest extends BasePerformanceLive
|
|||
throws Exception {
|
||||
S3Object object = newObject(key);
|
||||
object.getMetadata().setContentType(contentType);
|
||||
object.setData(data);
|
||||
object.setPayload(data);
|
||||
object.setContentLength(new Long(data.available()));
|
||||
return context.getApi().putObject(bucket, object) != null;
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ public abstract class BaseJCloudsPerformanceLiveTest extends BasePerformanceLive
|
|||
throws Exception {
|
||||
S3Object object = newObject(key);
|
||||
object.getMetadata().setContentType(contentType);
|
||||
object.setData(data);
|
||||
object.setPayload(data);
|
||||
return context.getApi().putObject(bucket, object) != null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ import javax.ws.rs.Path;
|
|||
import javax.ws.rs.PathParam;
|
||||
|
||||
import org.jclouds.azure.storage.AzureBlob;
|
||||
import org.jclouds.azure.storage.blob.binders.BindAzureBlobToEntity;
|
||||
import org.jclouds.azure.storage.blob.binders.BindAzureBlobToPayload;
|
||||
import org.jclouds.azure.storage.blob.domain.BlobProperties;
|
||||
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
|
||||
import org.jclouds.azure.storage.blob.domain.ListableContainerProperties;
|
||||
|
@ -193,7 +193,7 @@ public interface AzureBlobAsyncClient {
|
|||
@ResponseParser(ParseETagHeader.class)
|
||||
Future<String> putBlob(
|
||||
@PathParam("container") String container,
|
||||
@PathParam("name") @ParamParser(BlobName.class) @BinderParam(BindAzureBlobToEntity.class) org.jclouds.azure.storage.blob.domain.AzureBlob object);
|
||||
@PathParam("name") @ParamParser(BlobName.class) @BinderParam(BindAzureBlobToPayload.class) org.jclouds.azure.storage.blob.domain.AzureBlob object);
|
||||
|
||||
/**
|
||||
* @see AzureBlobClient#getBlob
|
||||
|
|
|
@ -194,7 +194,7 @@ public interface AzureBlobClient {
|
|||
* it as a set of blocks. For more information, see the Put Block and Put Block List operations.
|
||||
* <p/>
|
||||
* If you attempt to upload a blob that is larger than 64 MB, the service returns status code 413
|
||||
* (Request Entity Too Large). The Blob service also returns additional information about the
|
||||
* (Request Payload Too Large). The Blob service also returns additional information about the
|
||||
* error in the response, including the maximum blob size permitted in bytes.
|
||||
* <p/>
|
||||
* A Put Blob operation is permitted 10 minutes per MB to complete. If the operation is taking
|
||||
|
|
|
@ -33,24 +33,24 @@ import javax.ws.rs.core.HttpHeaders;
|
|||
import org.jclouds.azure.storage.blob.blobstore.functions.AzureBlobToBlob;
|
||||
import org.jclouds.azure.storage.blob.domain.AzureBlob;
|
||||
import org.jclouds.azure.storage.blob.reference.AzureBlobConstants;
|
||||
import org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix;
|
||||
import org.jclouds.blobstore.binders.BindBlobToPayloadAndUserMetadataToHeadersWithPrefix;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
|
||||
public class BindAzureBlobToEntity extends BindBlobToEntityAndUserMetadataToHeadersWithPrefix {
|
||||
public class BindAzureBlobToPayload extends BindBlobToPayloadAndUserMetadataToHeadersWithPrefix {
|
||||
|
||||
private final AzureBlobToBlob azureBlob2Blob;
|
||||
|
||||
@Inject
|
||||
public BindAzureBlobToEntity(AzureBlobToBlob azureBlob2Blob,
|
||||
public BindAzureBlobToPayload(AzureBlobToBlob azureBlob2Blob,
|
||||
@Named(AzureBlobConstants.PROPERTY_AZUREBLOB_METADATA_PREFIX) String prefix,
|
||||
EncryptionService encryptionService) {
|
||||
super(prefix, encryptionService);
|
||||
this.azureBlob2Blob = azureBlob2Blob;
|
||||
}
|
||||
|
||||
public void bindToRequest(HttpRequest request, Object entity) {
|
||||
AzureBlob object = (AzureBlob) entity;
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
AzureBlob object = (AzureBlob) payload;
|
||||
checkArgument(object.getProperties().getSize() >= 0, "size must be set");
|
||||
checkArgument(
|
||||
checkNotNull(object.getContentLength(), "object.getContentLength()") <= 64 * 1024 * 1024,
|
|
@ -50,7 +50,7 @@ public class AzureBlobToBlob implements Function<AzureBlob, Blob> {
|
|||
Blob blob = blobFactory.create(blobPr2BlobMd.apply(from.getProperties()));
|
||||
if (from.getContentLength() != null)
|
||||
blob.setContentLength(from.getContentLength());
|
||||
blob.setData(from.getData());
|
||||
blob.setPayload(from.getPayload());
|
||||
blob.setAllHeaders(from.getAllHeaders());
|
||||
return blob;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public class BlobToAzureBlob implements Function<Blob, AzureBlob> {
|
|||
AzureBlob object = objectProvider.create(blob2ObjectMd.apply(from.getMetadata()));
|
||||
if (from.getContentLength() != null)
|
||||
object.setContentLength(from.getContentLength());
|
||||
object.setData(from.getData());
|
||||
object.setPayload(from.getPayload());
|
||||
object.setAllHeaders(from.getAllHeaders());
|
||||
return object;
|
||||
}
|
||||
|
|
|
@ -29,9 +29,7 @@ import javax.inject.Provider;
|
|||
import org.jclouds.azure.storage.blob.domain.AzureBlob;
|
||||
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
|
||||
import org.jclouds.azure.storage.blob.domain.internal.AzureBlobImpl;
|
||||
import org.jclouds.blobstore.functions.CalculateSize;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5Result;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
@ -44,7 +42,6 @@ import com.google.inject.Scopes;
|
|||
*/
|
||||
public class AzureBlobModule extends AbstractModule {
|
||||
|
||||
|
||||
/**
|
||||
* explicit factories are created here as it has been shown that Assisted Inject is extremely
|
||||
* inefficient. http://code.google.com/p/google-guice/issues/detail?id=435
|
||||
|
@ -56,17 +53,13 @@ public class AzureBlobModule extends AbstractModule {
|
|||
|
||||
private static class AzureBlobFactory implements AzureBlob.Factory {
|
||||
@Inject
|
||||
GenerateMD5Result generateMD5Result;
|
||||
@Inject
|
||||
GenerateMD5 generateMD5;
|
||||
@Inject
|
||||
CalculateSize calculateSize;
|
||||
EncryptionService encryptionService;
|
||||
@Inject
|
||||
Provider<MutableBlobProperties> metadataProvider;
|
||||
|
||||
public AzureBlob create(MutableBlobProperties metadata) {
|
||||
return new AzureBlobImpl(generateMD5Result, generateMD5, calculateSize,
|
||||
metadata != null ? metadata : metadataProvider.get());
|
||||
return new AzureBlobImpl(encryptionService, metadata != null ? metadata : metadataProvider
|
||||
.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,66 +23,25 @@
|
|||
*/
|
||||
package org.jclouds.azure.storage.blob.domain;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.jclouds.http.PayloadEnclosing;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.inject.internal.Nullable;
|
||||
|
||||
/**
|
||||
* Amazon S3 is designed to store objects. Objects are stored in buckets and consist of a
|
||||
* {@link ObjectPropertiesBlob#getData() value}, a {@link ObjectProperties#getKey key},
|
||||
* {@link ObjectPropertiesBlob#getContent() value}, a {@link ObjectProperties#getKey key},
|
||||
* {@link ObjectProperties#getUserProperties() metadata}, and an access control policy.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html"
|
||||
* />
|
||||
*/
|
||||
public interface AzureBlob extends Comparable<AzureBlob> {
|
||||
public interface AzureBlob extends PayloadEnclosing, Comparable<AzureBlob> {
|
||||
public interface Factory {
|
||||
AzureBlob create(@Nullable MutableBlobProperties properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets entity for the request or the content from the response. If size isn't set, this will
|
||||
* attempt to discover it.
|
||||
*
|
||||
* @param data
|
||||
* typically InputStream for downloads, or File, byte [], String, or InputStream for
|
||||
* uploads.
|
||||
*/
|
||||
void setData(Object data);
|
||||
|
||||
/**
|
||||
* @return InputStream, if downloading, or whatever was set during {@link #setData(Object)}
|
||||
*/
|
||||
Object getData();
|
||||
|
||||
/**
|
||||
* generate an MD5 Hash for the current data.
|
||||
* <p/>
|
||||
* <h2>Note</h2>
|
||||
* <p/>
|
||||
* If this is an InputStream, it will be converted to a byte array first.
|
||||
*
|
||||
* @throws IOException
|
||||
* if there is a problem generating the hash.
|
||||
*/
|
||||
void generateMD5() throws IOException;
|
||||
|
||||
void setContentLength(long contentLength);
|
||||
|
||||
/**
|
||||
* 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 #getData()}
|
||||
* @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
|
||||
* @see GetObjectOptions
|
||||
*/
|
||||
Long getContentLength();
|
||||
|
||||
/**
|
||||
* @return System and User metadata relevant to this object.
|
||||
*/
|
||||
|
|
|
@ -24,18 +24,13 @@
|
|||
package org.jclouds.azure.storage.blob.domain.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.azure.storage.blob.domain.AzureBlob;
|
||||
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
|
||||
import org.jclouds.blobstore.domain.MD5InputStreamResult;
|
||||
import org.jclouds.blobstore.functions.CalculateSize;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5Result;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
import org.jclouds.http.internal.BasePayloadEnclosingImpl;
|
||||
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
@ -45,70 +40,20 @@ import com.google.common.collect.Multimap;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class AzureBlobImpl implements AzureBlob, Comparable<AzureBlob> {
|
||||
private final GenerateMD5Result generateMD5Result;
|
||||
private final GenerateMD5 generateMD5;
|
||||
private final CalculateSize calculateSize;
|
||||
public class AzureBlobImpl extends BasePayloadEnclosingImpl implements AzureBlob,
|
||||
Comparable<AzureBlob> {
|
||||
private final MutableBlobProperties properties;
|
||||
private Object data;
|
||||
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
||||
private Long contentLength;
|
||||
|
||||
@Inject
|
||||
public AzureBlobImpl(GenerateMD5Result generateMD5Result, GenerateMD5 generateMD5,
|
||||
CalculateSize calculateSize, MutableBlobProperties properties) {
|
||||
this.generateMD5Result = generateMD5Result;
|
||||
this.generateMD5 = generateMD5;
|
||||
this.calculateSize = calculateSize;
|
||||
public AzureBlobImpl(EncryptionService encryptionService, MutableBlobProperties properties) {
|
||||
super(encryptionService);
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void generateMD5() {
|
||||
checkState(data != null, "data");
|
||||
if (data instanceof InputStream) {
|
||||
MD5InputStreamResult result = generateMD5Result.apply((InputStream) data);
|
||||
getProperties().setContentMD5(result.md5);
|
||||
setContentLength(result.length);
|
||||
setData(result.data);
|
||||
} else {
|
||||
getProperties().setContentMD5(generateMD5.apply(data));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setData(Object data) {
|
||||
this.data = checkNotNull(data, "data");
|
||||
if (getContentLength() == null) {
|
||||
Long size = calculateSize.apply(data);
|
||||
if (size != null)
|
||||
this.setContentLength(size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Long getContentLength() {
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setContentLength(long contentLength) {
|
||||
this.contentLength = contentLength;
|
||||
@Override
|
||||
protected void setContentMD5(byte[] md5) {
|
||||
getProperties().setContentMD5(md5);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,7 +92,7 @@ public class AzureBlobImpl implements AzureBlob, Comparable<AzureBlob> {
|
|||
int result = 1;
|
||||
result = prime * result + ((allHeaders == null) ? 0 : allHeaders.hashCode());
|
||||
result = prime * result + ((contentLength == null) ? 0 : contentLength.hashCode());
|
||||
result = prime * result + ((data == null) ? 0 : data.hashCode());
|
||||
result = prime * result + ((payload == null) ? 0 : payload.hashCode());
|
||||
result = prime * result + ((properties == null) ? 0 : properties.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
@ -171,10 +116,10 @@ public class AzureBlobImpl implements AzureBlob, Comparable<AzureBlob> {
|
|||
return false;
|
||||
} else if (!contentLength.equals(other.contentLength))
|
||||
return false;
|
||||
if (data == null) {
|
||||
if (other.data != null)
|
||||
if (payload == null) {
|
||||
if (other.payload != null)
|
||||
return false;
|
||||
} else if (!data.equals(other.data))
|
||||
} else if (!payload.equals(other.payload))
|
||||
return false;
|
||||
if (properties == null) {
|
||||
if (other.properties != null)
|
||||
|
|
|
@ -66,7 +66,7 @@ public class ParseBlobFromHeadersAndHttpContent implements Function<HttpResponse
|
|||
public AzureBlob apply(HttpResponse from) {
|
||||
AzureBlob object = objectProvider.create(metadataParser.apply(from));
|
||||
addAllHeadersTo(from, object);
|
||||
object.setData(from.getContent());
|
||||
object.setPayload(from.getContent());
|
||||
attemptToParseSizeAndRangeFromHeaders(from, object);
|
||||
return object;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import static org.testng.Assert.assertEquals;
|
|||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
|
@ -229,7 +228,7 @@ public class AzureBlobClientLiveTest {
|
|||
// Test PUT with string data, ETag hash, and a piece of metadata
|
||||
AzureBlob object = connection.newBlob();
|
||||
object.getProperties().setName("object");
|
||||
object.setData(data);
|
||||
object.setPayload(data);
|
||||
object.setContentLength(data.length());
|
||||
object.generateMD5();
|
||||
object.getProperties().setContentType("text/plain");
|
||||
|
@ -281,7 +280,7 @@ public class AzureBlobClientLiveTest {
|
|||
}
|
||||
// Test GET of object (including updated metadata)
|
||||
AzureBlob getBlob = connection.getBlob(privateContainer, object.getProperties().getName());
|
||||
assertEquals(IOUtils.toString((InputStream) getBlob.getData()), data);
|
||||
assertEquals(IOUtils.toString(getBlob.getContent()), data);
|
||||
// TODO assertEquals(getBlob.getName(), object.getProperties().getName());
|
||||
assertEquals(getBlob.getContentLength(), new Long(data.length()));
|
||||
assertEquals(getBlob.getProperties().getContentType(), "text/plain");
|
||||
|
@ -313,7 +312,7 @@ public class AzureBlobClientLiveTest {
|
|||
ByteArrayInputStream bais = new ByteArrayInputStream(data.getBytes("UTF-8"));
|
||||
object = connection.newBlob();
|
||||
object.getProperties().setName("chunked-object");
|
||||
object.setData(bais);
|
||||
object.setPayload(bais);
|
||||
object.setContentLength(new Long(data.getBytes().length));
|
||||
newEtag = connection.putBlob(privateContainer, object);
|
||||
assertEquals(encryptionService.toHexString(md5), encryptionService.toHexString(getBlob
|
||||
|
|
|
@ -48,18 +48,17 @@ public class BindBlobToMultipartForm implements Binder {
|
|||
|
||||
public static final String BOUNDARY = "--JCLOUDS--";
|
||||
|
||||
public void bindToRequest(HttpRequest request, Object entity) {
|
||||
Blob object = (Blob) entity;
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
Blob object = (Blob) payload;
|
||||
File file = new File(object.getMetadata().getName());
|
||||
Multimap<String, String> partHeaders = ImmutableMultimap.of("Content-Disposition", String
|
||||
.format("form-data; name=\"%s\"; filename=\"%s\"", file.getName(), file.getName()),
|
||||
HttpHeaders.CONTENT_TYPE, checkNotNull(object.getMetadata().getContentType(),
|
||||
"object.metadata.contentType()"));
|
||||
Object data = checkNotNull(object.getData(), "object.getData()");
|
||||
Object data = checkNotNull(object.getPayload(), "object.getPayload()").getRawContent();
|
||||
|
||||
Part part;
|
||||
try {
|
||||
|
||||
if (data instanceof byte[]) {
|
||||
part = new Part(partHeaders, (byte[]) data);
|
||||
} else if (data instanceof String) {
|
||||
|
@ -77,7 +76,7 @@ public class BindBlobToMultipartForm implements Binder {
|
|||
}
|
||||
MultipartForm form = new MultipartForm(BOUNDARY, part);
|
||||
|
||||
request.setEntity(form.getData());
|
||||
request.setPayload(form.getData());
|
||||
request.getHeaders().put(HttpHeaders.CONTENT_TYPE,
|
||||
"multipart/form-data; boundary=" + BOUNDARY);
|
||||
|
||||
|
|
|
@ -37,18 +37,18 @@ import org.jclouds.rest.Binder;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class BindBlobToEntity implements Binder {
|
||||
public class BindBlobToPayload implements Binder {
|
||||
private final EncryptionService encryptionService;
|
||||
|
||||
@Inject
|
||||
public BindBlobToEntity(EncryptionService encryptionService) {
|
||||
public BindBlobToPayload(EncryptionService encryptionService) {
|
||||
this.encryptionService = encryptionService;
|
||||
}
|
||||
|
||||
public void bindToRequest(HttpRequest request, Object entity) {
|
||||
Blob object = (Blob) entity;
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
Blob object = (Blob) payload;
|
||||
|
||||
request.setEntity(checkNotNull(object.getData(), "object.getContent()"));
|
||||
request.setPayload(checkNotNull(object.getContent(), "object.getContent()"));
|
||||
request.getHeaders()
|
||||
.put(
|
||||
HttpHeaders.CONTENT_TYPE,
|
|
@ -36,24 +36,24 @@ import org.jclouds.http.HttpRequest;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class BindBlobToEntityAndUserMetadataToHeadersWithPrefix extends BindBlobToEntity {
|
||||
public class BindBlobToPayloadAndUserMetadataToHeadersWithPrefix extends BindBlobToPayload {
|
||||
private final String metadataPrefix;
|
||||
|
||||
@Inject
|
||||
public BindBlobToEntityAndUserMetadataToHeadersWithPrefix(
|
||||
public BindBlobToPayloadAndUserMetadataToHeadersWithPrefix(
|
||||
@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix,
|
||||
EncryptionService encryptionService) {
|
||||
super(encryptionService);
|
||||
this.metadataPrefix = metadataPrefix;
|
||||
}
|
||||
|
||||
public void bindToRequest(HttpRequest request, Object entity) {
|
||||
Blob object = (Blob) entity;
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
Blob object = (Blob) payload;
|
||||
|
||||
for (String key : object.getMetadata().getUserMetadata().keySet()) {
|
||||
request.getHeaders().put(key.startsWith(metadataPrefix) ? key : metadataPrefix + key,
|
||||
object.getMetadata().getUserMetadata().get(key));
|
||||
}
|
||||
super.bindToRequest(request, entity);
|
||||
super.bindToRequest(request, payload);
|
||||
}
|
||||
}
|
|
@ -43,8 +43,8 @@ public class BindMapToHeadersWithPrefix implements Binder {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void bindToRequest(HttpRequest request, Object entity) {
|
||||
Map<String, String> userMetadata = (Map<String, String>) entity;
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
Map<String, String> userMetadata = (Map<String, String>) payload;
|
||||
for (Entry<String, String> entry : userMetadata.entrySet()) {
|
||||
if (entry.getKey().startsWith(metadataPrefix)) {
|
||||
request.getHeaders().put(entry.getKey().toLowerCase(), entry.getValue());
|
||||
|
|
|
@ -29,9 +29,7 @@ import javax.inject.Provider;
|
|||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
||||
import org.jclouds.blobstore.domain.internal.BlobImpl;
|
||||
import org.jclouds.blobstore.functions.CalculateSize;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5Result;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
@ -55,17 +53,13 @@ public class BlobStoreObjectModule extends AbstractModule {
|
|||
|
||||
private static class BlobFactory implements Blob.Factory {
|
||||
@Inject
|
||||
GenerateMD5Result generateMD5Result;
|
||||
@Inject
|
||||
GenerateMD5 generateMD5;
|
||||
@Inject
|
||||
CalculateSize calculateSize;
|
||||
EncryptionService encryptionService;
|
||||
@Inject
|
||||
Provider<MutableBlobMetadata> metadataProvider;
|
||||
|
||||
public Blob create(MutableBlobMetadata metadata) {
|
||||
return new BlobImpl(generateMD5Result, generateMD5, calculateSize,
|
||||
metadata != null ? metadata : metadataProvider.get());
|
||||
return new BlobImpl(encryptionService, metadata != null ? metadata : metadataProvider
|
||||
.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,60 +23,24 @@
|
|||
*/
|
||||
package org.jclouds.blobstore.domain;
|
||||
|
||||
import org.jclouds.http.PayloadEnclosing;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.inject.internal.Nullable;
|
||||
|
||||
/**
|
||||
* Value type for an HTTP Blob service. Blobs are stored in containers and consist
|
||||
* of a {@link org.jclouds.blobstore.domain.Value#getData() value}, a {@link Blob#getKey key and
|
||||
* of a {@link org.jclouds.blobstore.domain.Value#getContent() value}, a {@link Blob#getKey key and
|
||||
*
|
||||
* @link Blob.Metadata#getUserMetadata() metadata}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public interface Blob extends Comparable<Blob> {
|
||||
public interface Blob extends PayloadEnclosing, Comparable<Blob> {
|
||||
public interface Factory {
|
||||
Blob create(@Nullable MutableBlobMetadata metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets entity for the request or the content from the response. If size isn't set, this will
|
||||
* attempt to discover it.
|
||||
*
|
||||
* @param data
|
||||
* typically InputStream for downloads, or File, byte [], String, or InputStream for
|
||||
* uploads.
|
||||
*/
|
||||
void setData(Object data);
|
||||
|
||||
/**
|
||||
* @return InputStream, if downloading, or whatever was set during {@link #setData(Object)}
|
||||
*/
|
||||
Object getData();
|
||||
|
||||
/**
|
||||
* generate an MD5 Hash for the current data.
|
||||
* <p/>
|
||||
* <h2>Note</h2>
|
||||
* <p/>
|
||||
* If this is an InputStream, it will be converted to a byte array first.
|
||||
*/
|
||||
void generateMD5();
|
||||
|
||||
void setContentLength(long contentLength);
|
||||
|
||||
/**
|
||||
* 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 #getData()}
|
||||
* @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
|
||||
* @see GetObjectOptions
|
||||
*/
|
||||
Long getContentLength();
|
||||
|
||||
/**
|
||||
* @return System and User metadata relevant to this object.
|
||||
*/
|
||||
|
|
|
@ -24,109 +24,39 @@
|
|||
package org.jclouds.blobstore.domain.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.MD5InputStreamResult;
|
||||
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
||||
import org.jclouds.blobstore.domain.ResourceMetadata;
|
||||
import org.jclouds.blobstore.functions.CalculateSize;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5;
|
||||
import org.jclouds.blobstore.functions.GenerateMD5Result;
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
import org.jclouds.http.internal.BasePayloadEnclosingImpl;
|
||||
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* Value type for an HTTP Blob service. Blobs are stored in {@link ResourceMetadata containers} and consist
|
||||
* of a {@link org.jclouds.blobstore.domain.Value#getData() value}, a {@link Blob#getKey key and
|
||||
* of a {@link org.jclouds.blobstore.domain.Value#getContent() value}, a {@link Blob#getKey key and
|
||||
*
|
||||
* @link Blob.Metadata#getUserMetadata() metadata}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class BlobImpl implements Blob, Comparable<Blob> {
|
||||
private final GenerateMD5Result generateMD5Result;
|
||||
private final GenerateMD5 generateMD5;
|
||||
private final CalculateSize calculateSize;
|
||||
public class BlobImpl extends BasePayloadEnclosingImpl implements Blob, Comparable<Blob> {
|
||||
private final MutableBlobMetadata metadata;
|
||||
private Object data;
|
||||
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
||||
private Long contentLength;
|
||||
|
||||
@Inject
|
||||
public BlobImpl(GenerateMD5Result generateMD5Result, GenerateMD5 generateMD5,
|
||||
CalculateSize calculateSize, MutableBlobMetadata metadata) {
|
||||
this.generateMD5Result = generateMD5Result;
|
||||
this.generateMD5 = generateMD5;
|
||||
this.calculateSize = calculateSize;
|
||||
public BlobImpl(EncryptionService encryptionService, MutableBlobMetadata metadata) {
|
||||
super(encryptionService);
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate an MD5 Hash for the current data.
|
||||
* <p/>
|
||||
* <h2>Note</h2>
|
||||
* <p/>
|
||||
* If this is an InputStream, it will be converted to a byte array first.
|
||||
*
|
||||
*/
|
||||
public void generateMD5() {
|
||||
checkState(data != null, "data");
|
||||
if (data instanceof InputStream) {
|
||||
MD5InputStreamResult result = generateMD5Result.apply((InputStream) data);
|
||||
getMetadata().setContentMD5(result.md5);
|
||||
setContentLength(result.length);
|
||||
setData(result.data);
|
||||
} else {
|
||||
getMetadata().setContentMD5(generateMD5.apply(data));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InputStream, if downloading, or whatever was set during {@link #setData(Object)}
|
||||
*/
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets entity for the request or the content from the response. If size isn't set, this will
|
||||
* attempt to discover it.
|
||||
*
|
||||
* @param data
|
||||
* typically InputStream for downloads, or File, byte [], String, or InputStream for
|
||||
* uploads.
|
||||
*/
|
||||
public void setData(Object data) {
|
||||
this.data = checkNotNull(data, "data");
|
||||
if (getContentLength() == null) {
|
||||
Long size = calculateSize.apply(data);
|
||||
if (size != null)
|
||||
this.setContentLength(size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 #getData()}
|
||||
* @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
|
||||
* @see GetObjectOptions
|
||||
*/
|
||||
public Long getContentLength() {
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
public void setContentLength(long contentLength) {
|
||||
this.contentLength = contentLength;
|
||||
@Override
|
||||
protected void setContentMD5(byte[] md5) {
|
||||
getMetadata().setContentMD5(checkNotNull(md5, "md5"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,7 +89,7 @@ public class BlobImpl implements Blob, Comparable<Blob> {
|
|||
int result = 1;
|
||||
result = prime * result + ((allHeaders == null) ? 0 : allHeaders.hashCode());
|
||||
result = prime * result + ((contentLength == null) ? 0 : contentLength.hashCode());
|
||||
result = prime * result + ((data == null) ? 0 : data.hashCode());
|
||||
result = prime * result + ((payload == null) ? 0 : payload.hashCode());
|
||||
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
@ -183,10 +113,10 @@ public class BlobImpl implements Blob, Comparable<Blob> {
|
|||
return false;
|
||||
} else if (!contentLength.equals(other.contentLength))
|
||||
return false;
|
||||
if (data == null) {
|
||||
if (other.data != null)
|
||||
if (payload == null) {
|
||||
if (other.payload != null)
|
||||
return false;
|
||||
} else if (!data.equals(other.data))
|
||||
} else if (!payload.equals(other.payload))
|
||||
return false;
|
||||
if (metadata == null) {
|
||||
if (other.metadata != null)
|
||||
|
|
|
@ -35,7 +35,7 @@ import org.jclouds.blobstore.domain.ResourceType;
|
|||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
* Identity of the object
|
||||
* Idpayload of the object
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
|
|
|
@ -36,7 +36,7 @@ import org.jclouds.blobstore.domain.ResourceType;
|
|||
import com.google.inject.internal.Nullable;
|
||||
|
||||
/**
|
||||
* Identity of the object
|
||||
* Idpayload of the object
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.functions;
|
||||
|
||||
import org.jclouds.blobstore.functions.impl.CalculateSizeByLength;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@ImplementedBy(CalculateSizeByLength.class)
|
||||
public interface CalculateSize extends Function<Object, Long> {
|
||||
|
||||
}
|
|
@ -26,6 +26,7 @@ package org.jclouds.blobstore.functions;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.http.Payloads;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
|
@ -44,7 +45,7 @@ public class ObjectMD5 implements Function<Object, byte[]> {
|
|||
object = (Blob) from;
|
||||
} else {
|
||||
object = blobFactory.create(null);
|
||||
object.setData(from);
|
||||
object.setPayload(Payloads.newPayload(from));
|
||||
}
|
||||
if (object.getMetadata().getContentMD5() == null)
|
||||
object.generateMD5();
|
||||
|
|
|
@ -66,7 +66,7 @@ public class ParseBlobFromHeadersAndHttpContent implements Function<HttpResponse
|
|||
MutableBlobMetadata metadata = metadataParser.apply(from);
|
||||
Blob object = blobFactory.create(metadata);
|
||||
addAllHeadersTo(from, object);
|
||||
object.setData(from.getContent());
|
||||
object.setPayload(from.getContent());
|
||||
assert object.getMetadata() == metadata;
|
||||
attemptToParseSizeAndRangeFromHeaders(from, object);
|
||||
return object;
|
||||
|
|
|
@ -44,6 +44,12 @@ import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
|
|||
import org.jclouds.blobstore.strategy.CountListStrategy;
|
||||
import org.jclouds.blobstore.strategy.GetBlobsInListStrategy;
|
||||
import org.jclouds.blobstore.strategy.ListBlobMetadataStrategy;
|
||||
import org.jclouds.http.Payload;
|
||||
import org.jclouds.http.Payloads;
|
||||
import org.jclouds.http.payloads.ByteArrayPayload;
|
||||
import org.jclouds.http.payloads.FilePayload;
|
||||
import org.jclouds.http.payloads.InputStreamPayload;
|
||||
import org.jclouds.http.payloads.StringPayload;
|
||||
import org.jclouds.util.Utils;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
@ -81,7 +87,7 @@ public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements Inpu
|
|||
String realKey = prefixer.apply(o.toString());
|
||||
try {
|
||||
return (InputStream) (connection.getBlob(containerName, realKey).get(
|
||||
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).getData();
|
||||
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).getContent();
|
||||
} catch (KeyNotFoundException e) {
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
|
@ -129,7 +135,7 @@ public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements Inpu
|
|||
return Collections2.transform(getAllBlobs.execute(containerName, options),
|
||||
new Function<Blob, InputStream>() {
|
||||
public InputStream apply(Blob from) {
|
||||
return (InputStream) from.getData();
|
||||
return (InputStream) from.getContent();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -143,7 +149,7 @@ public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements Inpu
|
|||
Set<Map.Entry<String, InputStream>> entrySet = new HashSet<Map.Entry<String, InputStream>>();
|
||||
for (Blob object : this.getAllBlobs.execute(containerName, options)) {
|
||||
entrySet.add(new Entry(pathStripper.apply(object.getMetadata().getName()),
|
||||
(InputStream) object.getData()));
|
||||
(InputStream) object.getContent()));
|
||||
}
|
||||
return entrySet;
|
||||
}
|
||||
|
@ -226,7 +232,7 @@ public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements Inpu
|
|||
for (Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
|
||||
Blob object = connection.newBlob();
|
||||
object.getMetadata().setName(prefixer.apply(entry.getKey()));
|
||||
object.setData(entry.getValue());
|
||||
object.setPayload(Payloads.newPayload(entry.getValue()));
|
||||
object.generateMD5();
|
||||
puts.add(connection.putBlob(containerName, object));
|
||||
// / ParamExtractor Funcion<?,String>
|
||||
|
@ -248,7 +254,7 @@ public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements Inpu
|
|||
* @see #putInternal(String, Object)
|
||||
*/
|
||||
public InputStream putString(String key, String value) {
|
||||
return putInternal(key, value);
|
||||
return putInternal(key, new StringPayload(value));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -257,7 +263,7 @@ public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements Inpu
|
|||
* @see #putInternal(String, Object)
|
||||
*/
|
||||
public InputStream putFile(String key, File value) {
|
||||
return putInternal(key, value);
|
||||
return putInternal(key, new FilePayload(value));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -266,7 +272,7 @@ public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements Inpu
|
|||
* @see #putInternal(String, Object)
|
||||
*/
|
||||
public InputStream putBytes(String key, byte[] value) {
|
||||
return putInternal(key, value);
|
||||
return putInternal(key, new ByteArrayPayload(value));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -275,7 +281,7 @@ public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements Inpu
|
|||
* @see #putInternal(String, Object)
|
||||
*/
|
||||
public InputStream put(String key, InputStream value) {
|
||||
return putInternal(key, value);
|
||||
return putInternal(key, new InputStreamPayload(value));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -285,12 +291,12 @@ public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements Inpu
|
|||
* @see S3Client#put(String, Blob)
|
||||
*/
|
||||
@VisibleForTesting
|
||||
InputStream putInternal(String s, Object o) {
|
||||
InputStream putInternal(String s, Payload payload) {
|
||||
Blob object = connection.newBlob();
|
||||
object.getMetadata().setName(prefixer.apply(s));
|
||||
try {
|
||||
InputStream returnVal = containsKey(s) ? get(s) : null;
|
||||
object.setData(o);
|
||||
object.setPayload(payload);
|
||||
object.generateMD5();
|
||||
connection.putBlob(containerName, object).get(requestTimeoutMilliseconds,
|
||||
TimeUnit.MILLISECONDS);
|
||||
|
|
|
@ -133,7 +133,7 @@ public class GetOptions {
|
|||
* Not compatible with {@link #ifETagDoesntMatch(String)} or {@link #ifModifiedSince(Date)}
|
||||
*
|
||||
* @param eTag
|
||||
* hash representing the entity
|
||||
* hash representing the payload
|
||||
*/
|
||||
public GetOptions ifETagMatches(String eTag) {
|
||||
checkArgument(getIfNoneMatch() == null,
|
||||
|
@ -147,7 +147,7 @@ public class GetOptions {
|
|||
/**
|
||||
* For use in the request header: If-Match
|
||||
* <p />
|
||||
* Return the object only if its entity tag (ETag) is the same as the eTag specified, otherwise
|
||||
* Return the object only if its payload tag (ETag) is the same as the eTag specified, otherwise
|
||||
* return a 412 (precondition failed).
|
||||
*
|
||||
* @see GetOptions#ifETagMatches(String)
|
||||
|
@ -162,7 +162,7 @@ public class GetOptions {
|
|||
* Not compatible with {@link #ifETagMatches(String)} or {@link #ifUnmodifiedSince(Date)}
|
||||
*
|
||||
* @param eTag
|
||||
* hash representing the entity
|
||||
* hash representing the payload
|
||||
*/
|
||||
public GetOptions ifETagDoesntMatch(String eTag) {
|
||||
checkArgument(getIfMatch() == null,
|
||||
|
@ -176,7 +176,7 @@ public class GetOptions {
|
|||
/**
|
||||
* For use in the request header: If-None-Match
|
||||
* <p />
|
||||
* Return the object only if its entity tag (ETag) is different from the one specified, otherwise
|
||||
* Return the object only if its payload tag (ETag) is different from the one specified, otherwise
|
||||
* return a 304 (not modified).
|
||||
*
|
||||
* @see GetOptions#ifETagDoesntMatch(String)
|
||||
|
|
|
@ -65,7 +65,7 @@ public class MarkerFileMkdirStrategy implements MkdirStrategy {
|
|||
TimeUnit.MILLISECONDS)) {
|
||||
Blob blob = connection.newBlob();
|
||||
blob.getMetadata().setName(directory + directorySuffix);
|
||||
blob.setData("");
|
||||
blob.setPayload("");
|
||||
blob.getMetadata().setContentType("application/directory");
|
||||
connection.putBlob(containerName, blob).get(requestTimeoutMilliseconds,
|
||||
TimeUnit.MILLISECONDS);
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.jclouds.util.Utils;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
public class BlobStoreUtils {
|
||||
|
||||
public static Blob newBlob(BlobStore blobStore, ResourceMetadata blobMeta) {
|
||||
Blob blob = blobStore.newBlob();
|
||||
if (blobMeta instanceof BlobMetadata) {
|
||||
|
@ -77,8 +78,8 @@ public class BlobStoreUtils {
|
|||
|
||||
public static String getContentAsStringAndClose(Blob blob) throws IOException {
|
||||
checkNotNull(blob, "blob");
|
||||
checkNotNull(blob.getData(), "blob.data");
|
||||
Object o = blob.getData();
|
||||
checkNotNull(blob.getContent(), "blob.data");
|
||||
Object o = blob.getContent();
|
||||
if (o instanceof InputStream) {
|
||||
return Utils.toStringAndClose((InputStream) o);
|
||||
} else {
|
||||
|
|
|
@ -63,7 +63,7 @@ public class BindBlobToMultipartFormTest {
|
|||
EXPECTS = builder.toString();
|
||||
TEST_BLOB = blobProvider.create(null);
|
||||
TEST_BLOB.getMetadata().setName("hello");
|
||||
TEST_BLOB.setData("hello");
|
||||
TEST_BLOB.setPayload("hello");
|
||||
TEST_BLOB.getMetadata().setContentType(MediaType.TEXT_PLAIN);
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ public class BindBlobToMultipartFormTest {
|
|||
HttpRequest request = new HttpRequest("GET", URI.create("http://localhost:8001"));
|
||||
binder.bindToRequest(request, TEST_BLOB);
|
||||
|
||||
assertEquals(Utils.toStringAndClose((InputStream) request.getEntity()), EXPECTS);
|
||||
assertEquals(Utils.toStringAndClose((InputStream) request.getPayload().getRawContent()), EXPECTS);
|
||||
assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH), 131 + "");
|
||||
|
||||
assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE),
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.jclouds.blobstore.domain.ResourceMetadata;
|
|||
import org.jclouds.blobstore.util.BlobStoreUtils;
|
||||
import org.jclouds.encryption.internal.JCEEncryptionService;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.http.Payloads;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
@ -302,7 +303,7 @@ public class BaseBlobIntegrationTest<A, S> extends BaseBlobStoreIntegrationTest<
|
|||
throws InterruptedException, IOException {
|
||||
Blob object = newBlob(key);
|
||||
object.getMetadata().setContentType(type);
|
||||
object.setData(content);
|
||||
object.setPayload(Payloads.newPayload(content));
|
||||
if (content instanceof InputStream) {
|
||||
object.generateMD5();
|
||||
}
|
||||
|
@ -323,7 +324,7 @@ public class BaseBlobIntegrationTest<A, S> extends BaseBlobStoreIntegrationTest<
|
|||
String key = "hello";
|
||||
|
||||
Blob object = newBlob(key);
|
||||
object.setData(TEST_STRING);
|
||||
object.setPayload(TEST_STRING);
|
||||
object.getMetadata().setContentType("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
|
||||
|
|
|
@ -71,7 +71,7 @@ public class BaseBlobLiveTest<A, S> extends BaseBlobStoreIntegrationTest<A, S> {
|
|||
InputStream input = connection.getInputStream();
|
||||
|
||||
Blob object = newBlob(key);
|
||||
object.setData(input);
|
||||
object.setPayload(input);
|
||||
object.setContentLength(length);
|
||||
object.getMetadata().setContentMD5(md5);
|
||||
object.getMetadata().setSize(new Long(length));
|
||||
|
|
|
@ -115,7 +115,7 @@ public class BaseBlobMapIntegrationTest<A, S> extends BaseMapIntegrationTest<A,
|
|||
assertEquals(fiveStrings.get(entry.getKey()), BlobStoreUtils
|
||||
.getContentAsStringAndClose(entry.getValue()));
|
||||
Blob value = entry.getValue();
|
||||
value.setData("");
|
||||
value.setPayload("");
|
||||
value.generateMD5();
|
||||
entry.setValue(value);
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ public class BaseBlobMapIntegrationTest<A, S> extends BaseMapIntegrationTest<A,
|
|||
Map<String, Blob> map = createMap(context, bucketName);
|
||||
putStringWithMD5(map, "one", "apple");
|
||||
Blob object = newBlob("one");
|
||||
object.setData("apple");
|
||||
object.setPayload("apple");
|
||||
object.generateMD5();
|
||||
assertConsistencyAwareContainsValue(map, object);
|
||||
} finally {
|
||||
|
@ -163,11 +163,11 @@ public class BaseBlobMapIntegrationTest<A, S> extends BaseMapIntegrationTest<A,
|
|||
try {
|
||||
Map<String, Blob> map = createMap(context, bucketName);
|
||||
Blob object = newBlob("one");
|
||||
object.setData(IOUtils.toInputStream("apple"));
|
||||
object.setPayload(IOUtils.toInputStream("apple"));
|
||||
object.generateMD5();
|
||||
Blob old = map.put(object.getMetadata().getName(), object);
|
||||
getOneReturnsAppleAndOldValueIsNull(map, old);
|
||||
object.setData(IOUtils.toInputStream("bear"));
|
||||
object.setPayload(IOUtils.toInputStream("bear"));
|
||||
object.generateMD5();
|
||||
Blob apple = map.put(object.getMetadata().getName(), object);
|
||||
getOneReturnsBearAndOldValueIsApple(map, apple);
|
||||
|
@ -184,7 +184,7 @@ public class BaseBlobMapIntegrationTest<A, S> extends BaseMapIntegrationTest<A,
|
|||
Map<String, Blob> newMap = new HashMap<String, Blob>();
|
||||
for (String key : fiveInputs.keySet()) {
|
||||
Blob object = newBlob(key);
|
||||
object.setData(fiveInputs.get(key));
|
||||
object.setPayload(fiveInputs.get(key));
|
||||
object.setContentLength(new Long(fiveBytes.get(key).length));
|
||||
newMap.put(key, object);
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ public class BaseBlobMapIntegrationTest<A, S> extends BaseMapIntegrationTest<A,
|
|||
@Override
|
||||
protected void putStringWithMD5(Map<String, Blob> map, String key, String value) {
|
||||
Blob object = newBlob(key);
|
||||
object.setData(value);
|
||||
object.setPayload(value);
|
||||
object.generateMD5();
|
||||
map.put(key, object);
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ public class BaseBlobMapIntegrationTest<A, S> extends BaseMapIntegrationTest<A,
|
|||
Map<String, Blob> newMap = new HashMap<String, Blob>();
|
||||
for (Map.Entry<String, String> entry : fiveStrings.entrySet()) {
|
||||
Blob object = newBlob(entry.getKey());
|
||||
object.setData(entry.getValue());
|
||||
object.setPayload(entry.getValue());
|
||||
newMap.put(entry.getKey(), object);
|
||||
}
|
||||
map.putAll(newMap);
|
||||
|
@ -219,7 +219,7 @@ public class BaseBlobMapIntegrationTest<A, S> extends BaseMapIntegrationTest<A,
|
|||
Map<String, Blob> newMap = new HashMap<String, Blob>();
|
||||
for (Map.Entry<String, String> entry : fiveStringsUnderPath.entrySet()) {
|
||||
Blob object = newBlob(entry.getKey());
|
||||
object.setData(entry.getValue());
|
||||
object.setPayload(entry.getValue());
|
||||
newMap.put(entry.getKey(), object);
|
||||
}
|
||||
map.putAll(newMap);
|
||||
|
|
|
@ -263,7 +263,7 @@ public class BaseBlobStoreIntegrationTest<A, S> {
|
|||
protected String addBlobToContainer(String sourceContainer, String key) {
|
||||
Blob sourceObject = newBlob(key);
|
||||
sourceObject.getMetadata().setContentType("text/xml");
|
||||
sourceObject.setData(TEST_STRING);
|
||||
sourceObject.setPayload(TEST_STRING);
|
||||
return addBlobToContainer(sourceContainer, sourceObject);
|
||||
}
|
||||
|
||||
|
@ -272,7 +272,7 @@ public class BaseBlobStoreIntegrationTest<A, S> {
|
|||
fiveStringsUnderPath.entrySet())) {
|
||||
Blob sourceObject = newBlob(entry.getKey());
|
||||
sourceObject.getMetadata().setContentType("text/xml");
|
||||
sourceObject.setData(entry.getValue());
|
||||
sourceObject.setPayload(entry.getValue());
|
||||
addBlobToContainer(sourceContainer, sourceObject);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,7 +202,7 @@ public class BaseContainerIntegrationTest<A, S> extends BaseBlobStoreIntegration
|
|||
protected void addAlphabetUnderRoot(String containerName) throws InterruptedException {
|
||||
for (char letter = 'a'; letter <= 'z'; letter++) {
|
||||
Blob blob = newBlob(letter + "");
|
||||
blob.setData(letter + "content");
|
||||
blob.setPayload(letter + "content");
|
||||
context.getBlobStore().putBlob(containerName, blob);
|
||||
}
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ public class BaseContainerIntegrationTest<A, S> extends BaseBlobStoreIntegration
|
|||
protected void add15UnderRoot(String containerName) throws InterruptedException {
|
||||
for (int i = 0; i < 15; i++) {
|
||||
Blob blob = newBlob(i + "");
|
||||
blob.setData(i + "content");
|
||||
blob.setPayload(i + "content");
|
||||
context.getBlobStore().putBlob(containerName, blob);
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +219,7 @@ public class BaseContainerIntegrationTest<A, S> extends BaseBlobStoreIntegration
|
|||
throws InterruptedException {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Blob blob = newBlob(prefix + "/" + i);
|
||||
blob.setData(i + "content");
|
||||
blob.setPayload(i + "content");
|
||||
context.getBlobStore().putBlob(containerName, blob);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ public class StubAsyncBlobStore implements AsyncBlobStore {
|
|||
|
||||
Blob object = realContents.get(key);
|
||||
Blob returnVal = blobProvider.create(copy(object.getMetadata()));
|
||||
returnVal.setData(new ByteArrayInputStream((byte[]) object.getData()));
|
||||
returnVal.setPayload(object.getContent());
|
||||
return returnVal;
|
||||
}
|
||||
};
|
||||
|
@ -512,7 +512,7 @@ public class StubAsyncBlobStore implements AsyncBlobStore {
|
|||
new RuntimeException("bucketName not found: " + bucketName);
|
||||
}
|
||||
try {
|
||||
byte[] data = toByteArray(object.getData());
|
||||
byte[] data = toByteArray(object.getPayload().getRawContent());
|
||||
object.getMetadata().setSize(data.length);
|
||||
MutableBlobMetadata newMd = copy(object.getMetadata());
|
||||
newMd.setLastModified(new Date());
|
||||
|
@ -523,7 +523,7 @@ public class StubAsyncBlobStore implements AsyncBlobStore {
|
|||
newMd.setContentType(object.getMetadata().getContentType());
|
||||
|
||||
Blob blob = blobProvider.create(newMd);
|
||||
blob.setData(data);
|
||||
blob.setPayload(data);
|
||||
container.put(blob.getMetadata().getName(), blob);
|
||||
|
||||
// Set HTTP headers to match metadata
|
||||
|
@ -592,7 +592,12 @@ public class StubAsyncBlobStore implements AsyncBlobStore {
|
|||
Blob returnVal = copyBlob(object);
|
||||
|
||||
if (options.getRanges() != null && options.getRanges().size() > 0) {
|
||||
byte[] data = (byte[]) returnVal.getData();
|
||||
byte[] data;
|
||||
try {
|
||||
data = IOUtils.toByteArray(returnVal.getPayload().getContent());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
for (String s : options.getRanges()) {
|
||||
if (s.startsWith("-")) {
|
||||
|
@ -612,11 +617,11 @@ public class StubAsyncBlobStore implements AsyncBlobStore {
|
|||
}
|
||||
|
||||
}
|
||||
returnVal.setData(out.toByteArray());
|
||||
returnVal.setPayload(out.toByteArray());
|
||||
returnVal.setContentLength(out.size());
|
||||
returnVal.getMetadata().setSize(new Long(data.length));
|
||||
}
|
||||
returnVal.setData(new ByteArrayInputStream((byte[]) returnVal.getData()));
|
||||
returnVal.setPayload(returnVal.getPayload());
|
||||
return returnVal;
|
||||
}
|
||||
};
|
||||
|
@ -638,7 +643,7 @@ public class StubAsyncBlobStore implements AsyncBlobStore {
|
|||
|
||||
private Blob copyBlob(Blob object) {
|
||||
Blob returnVal = blobProvider.create(copy(object.getMetadata()));
|
||||
returnVal.setData(object.getData());
|
||||
returnVal.setPayload(object.getPayload());
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public class RetryOnNotFoundGetAllBlobsStrategyTest {
|
|||
Future<Blob> futureObject = createMock(Future.class);
|
||||
Blob object = blobProvider.create(null);
|
||||
object.getMetadata().setName("key");
|
||||
object.setData("goo");
|
||||
object.setPayload("goo");
|
||||
expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andThrow(
|
||||
new KeyNotFoundException());
|
||||
context.getInstance(AsyncBlobStore.class).putBlob("container", object).get();
|
||||
|
@ -86,7 +86,7 @@ public class RetryOnNotFoundGetAllBlobsStrategyTest {
|
|||
map.ifNotFoundRetryOtherwiseAddToSet("container", "key", futureObject, objects);
|
||||
// should have retried once
|
||||
assert System.currentTimeMillis() >= time + map.requestRetryMilliseconds;
|
||||
assertEquals(IOUtils.toString((InputStream) objects.iterator().next().getData()), "goo");
|
||||
assertEquals(IOUtils.toString((InputStream) objects.iterator().next().getContent()), "goo");
|
||||
assert !objects.contains(null);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ package org.jclouds.http;
|
|||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -48,7 +50,7 @@ public class HttpRequest extends HttpMessage implements Request<URI> {
|
|||
|
||||
private String method;
|
||||
private URI endpoint;
|
||||
private Object entity;
|
||||
private Payload payload;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -84,10 +86,10 @@ public class HttpRequest extends HttpMessage implements Request<URI> {
|
|||
* If the request is HEAD, this may change to GET due to redirects
|
||||
*/
|
||||
protected HttpRequest(String method, URI endPoint, Multimap<String, String> headers,
|
||||
@Nullable Object entity) {
|
||||
@Nullable Payload payload) {
|
||||
this(method, endPoint);
|
||||
getHeaders().putAll(checkNotNull(headers, "headers"));
|
||||
setEntity(entity);
|
||||
setPayload(payload);
|
||||
}
|
||||
|
||||
public String getRequestLine() {
|
||||
|
@ -104,16 +106,51 @@ public class HttpRequest extends HttpMessage implements Request<URI> {
|
|||
return method;
|
||||
}
|
||||
|
||||
public Object getEntity() {
|
||||
return entity;
|
||||
public Payload getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
public void setEntity(Object content) {
|
||||
if (content instanceof String
|
||||
&& this.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH) == null) {
|
||||
getHeaders().put(HttpHeaders.CONTENT_LENGTH, content.toString().getBytes().length + "");
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setPayload(Payload data) {
|
||||
this.payload = checkNotNull(data, "data");
|
||||
setLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setPayload(InputStream data) {
|
||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setPayload(byte[] data) {
|
||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setPayload(String data) {
|
||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setPayload(File data) {
|
||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
||||
}
|
||||
|
||||
private void setLength() {
|
||||
Long size = getPayload().calculateSize();
|
||||
if (size != null && this.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH) == null) {
|
||||
getHeaders().put(HttpHeaders.CONTENT_LENGTH, size.toString());
|
||||
}
|
||||
this.entity = content;
|
||||
}
|
||||
|
||||
public URI getEndpoint() {
|
||||
|
|
|
@ -26,7 +26,6 @@ package org.jclouds.http;
|
|||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
@ -58,18 +57,6 @@ public class HttpUtils {
|
|||
public static final Pattern URI_PATTERN = Pattern.compile("([a-z0-9]+)://([^:]*):(.*)@(.*)");
|
||||
public static final Pattern PATTERN_THAT_BREAKS_URI = Pattern.compile("[a-z0-9]+://.*/.*@.*"); // slash
|
||||
|
||||
public static Long calculateSize(Object data) {
|
||||
Long size = null;
|
||||
if (data instanceof byte[]) {
|
||||
size = new Long(((byte[]) data).length);
|
||||
} else if (data instanceof String) {
|
||||
size = new Long(((String) data).length());
|
||||
} else if (data instanceof File) {
|
||||
size = ((File) data).length();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Resource
|
||||
protected static Logger logger = Logger.NULL;
|
||||
|
||||
|
|
|
@ -21,22 +21,42 @@
|
|||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.blobstore.functions.impl;
|
||||
package org.jclouds.http;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.blobstore.functions.CalculateSize;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class CalculateSizeByLength implements CalculateSize {
|
||||
public interface Payload {
|
||||
|
||||
public Long apply(Object from) {
|
||||
return HttpUtils.calculateSize(from);
|
||||
}
|
||||
/**
|
||||
* Creates a new InputStream object of the payload.
|
||||
*/
|
||||
InputStream getContent();
|
||||
|
||||
/**
|
||||
* Payload in its original form.
|
||||
*/
|
||||
Object getRawContent();
|
||||
|
||||
/**
|
||||
* Tells if the payload is capable of producing its data more than once.
|
||||
*/
|
||||
boolean isRepeatable();
|
||||
|
||||
/**
|
||||
* Writes the payload content to the output stream.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
void writeTo(OutputStream outstream) throws IOException;
|
||||
|
||||
/**
|
||||
* Attempts to determine the size of the payload
|
||||
*/
|
||||
Long calculateSize();
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package org.jclouds.http;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public interface PayloadEnclosing {
|
||||
|
||||
/**
|
||||
* Sets payload for the request or the content from the response. If size isn't set, this will
|
||||
* attempt to discover it.
|
||||
*
|
||||
* @param data
|
||||
* typically InputStream for downloads, or File, byte [], String, or InputStream for
|
||||
* uploads.
|
||||
*/
|
||||
void setPayload(Payload data);
|
||||
|
||||
void setPayload(File data);
|
||||
|
||||
void setPayload(byte[] data);
|
||||
|
||||
void setPayload(InputStream data);
|
||||
|
||||
void setPayload(String data);
|
||||
|
||||
Payload getPayload();
|
||||
|
||||
/**
|
||||
* @return InputStream, if downloading, or whatever was set during {@link #setPayload(Object)}
|
||||
*/
|
||||
InputStream getContent();
|
||||
|
||||
|
||||
void setContentLength(long contentLength);
|
||||
|
||||
/**
|
||||
* 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 #getContent()}
|
||||
* @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
|
||||
* @see GetObjectOptions
|
||||
*/
|
||||
Long getContentLength();
|
||||
|
||||
/**
|
||||
* generate an MD5 Hash for the current data.
|
||||
* <p/>
|
||||
* <h2>Note</h2>
|
||||
* <p/>
|
||||
* If this is an InputStream, it will be converted to a byte array first.
|
||||
*/
|
||||
void generateMD5();
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package org.jclouds.http;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.jclouds.http.payloads.ByteArrayPayload;
|
||||
import org.jclouds.http.payloads.FilePayload;
|
||||
import org.jclouds.http.payloads.InputStreamPayload;
|
||||
import org.jclouds.http.payloads.StringPayload;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class Payloads {
|
||||
|
||||
public static Payload newPayload(Object data) {
|
||||
checkNotNull(data, "data");
|
||||
if (data instanceof Payload) {
|
||||
return (Payload) data;
|
||||
} else if (data instanceof InputStream) {
|
||||
return newInputStreamPayload((InputStream) data);
|
||||
} else if (data instanceof byte[]) {
|
||||
return newByteArrayPayload((byte[]) data);
|
||||
} else if (data instanceof String) {
|
||||
return newStringPayload((String) data);
|
||||
} else if (data instanceof File) {
|
||||
return newFilePayload((File) data);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("unsupported payload type: " + data.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
public static InputStreamPayload newInputStreamPayload(InputStream data) {
|
||||
return new InputStreamPayload(checkNotNull(data, "data"));
|
||||
}
|
||||
|
||||
public static ByteArrayPayload newByteArrayPayload(byte[] data) {
|
||||
return new ByteArrayPayload(checkNotNull(data, "data"));
|
||||
}
|
||||
|
||||
public static StringPayload newStringPayload(String data) {
|
||||
return new StringPayload(checkNotNull(data, "data"));
|
||||
}
|
||||
|
||||
public static FilePayload newFilePayload(File data) {
|
||||
return new FilePayload(checkNotNull(data, "data"));
|
||||
}
|
||||
|
||||
}
|
|
@ -23,7 +23,6 @@
|
|||
*/
|
||||
package org.jclouds.http;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
@ -127,12 +126,7 @@ public class TransformingHttpCommandImpl<T> implements TransformingHttpCommand<T
|
|||
}
|
||||
|
||||
public boolean isReplayable() {
|
||||
Object content = request.getEntity();
|
||||
if (content != null && content instanceof InputStream) {
|
||||
logger.warn("%1$s: InputStreams are not replayable", toString());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return (request.getPayload() == null) ? true : request.getPayload().isRepeatable();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -140,7 +134,6 @@ public class TransformingHttpCommandImpl<T> implements TransformingHttpCommand<T
|
|||
* IOUtils.closeQuietly(getResponse().getContent()); throw new
|
||||
* IllegalStateException("incorrect code for this operation: " + getResponse()); } }
|
||||
**/
|
||||
|
||||
public HttpRequest getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
package org.jclouds.http.config;
|
||||
|
||||
import org.jclouds.concurrent.SingleThreaded;
|
||||
import org.jclouds.http.HttpCommandExecutorService;
|
||||
import org.jclouds.http.TransformingHttpCommandExecutorService;
|
||||
import org.jclouds.http.TransformingHttpCommandExecutorServiceImpl;
|
||||
|
@ -39,6 +40,7 @@ import com.google.inject.Scopes;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
@ConfiguresHttpCommandExecutorService
|
||||
@SingleThreaded
|
||||
public class JavaUrlHttpCommandExecutorServiceModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -43,14 +43,14 @@ public class ReturnStringIf200 implements Function<HttpResponse,String> {
|
|||
|
||||
public String apply(HttpResponse from) {
|
||||
if (from.getStatusCode() == 200) {
|
||||
InputStream entity = from.getContent();
|
||||
if (entity == null)
|
||||
InputStream payload = from.getContent();
|
||||
if (payload == null)
|
||||
throw new HttpException("no content");
|
||||
String toReturn = null;
|
||||
try {
|
||||
toReturn = Utils.toStringAndClose(entity);
|
||||
toReturn = Utils.toStringAndClose(payload);
|
||||
} catch (IOException e) {
|
||||
throw new HttpException(String.format("Couldn't receive response %1$s, entity: %2$s ",
|
||||
throw new HttpException(String.format("Couldn't receive response %1$s, payload: %2$s ",
|
||||
from, toReturn), e);
|
||||
}
|
||||
return toReturn;
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.jclouds.http.HttpRequest;
|
|||
import org.jclouds.http.HttpRequestFilter;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.http.Payloads;
|
||||
import org.jclouds.http.handlers.DelegatingErrorHandler;
|
||||
import org.jclouds.http.handlers.DelegatingRetryHandler;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
@ -86,8 +87,9 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
|
|||
filter.filter(request);
|
||||
}
|
||||
logger.debug("Sending request %s: %s", request.hashCode(), request.getRequestLine());
|
||||
if (request.getEntity() != null && wire.enabled())
|
||||
request.setEntity(wire.output(request.getEntity()));
|
||||
if (request.getPayload() != null && wire.enabled())
|
||||
request.setPayload(Payloads.newPayload(wire.output(request.getPayload()
|
||||
.getRawContent())));
|
||||
nativeRequest = convert(request);
|
||||
HttpUtils.logRequest(headerLog, request, ">>");
|
||||
response = invoke(nativeRequest);
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
package org.jclouds.http.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.encryption.EncryptionService;
|
||||
import org.jclouds.encryption.EncryptionService.MD5InputStreamResult;
|
||||
import org.jclouds.http.Payload;
|
||||
import org.jclouds.http.PayloadEnclosing;
|
||||
import org.jclouds.http.Payloads;
|
||||
import org.jclouds.http.payloads.InputStreamPayload;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public abstract class BasePayloadEnclosingImpl implements PayloadEnclosing {
|
||||
private final EncryptionService encryptionService;
|
||||
protected Payload payload;
|
||||
protected Long contentLength;
|
||||
|
||||
@Inject
|
||||
public BasePayloadEnclosingImpl(EncryptionService encryptionService) {
|
||||
this.encryptionService = encryptionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate an MD5 Hash for the current data.
|
||||
* <p/>
|
||||
* <h2>Note</h2>
|
||||
* <p/>
|
||||
* If this is an InputStream, it will be converted to a byte array first.
|
||||
*
|
||||
*/
|
||||
public void generateMD5() {
|
||||
checkState(payload != null, "payload");
|
||||
if (payload instanceof InputStreamPayload) {
|
||||
MD5InputStreamResult result = encryptionService
|
||||
.generateMD5Result(((InputStreamPayload) payload).getContent());
|
||||
setContentMD5(result.md5);
|
||||
setContentLength(result.length);
|
||||
setPayload(result.data);
|
||||
} else {
|
||||
setContentMD5(encryptionService.md5(payload.getRawContent()));
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void setContentMD5(byte[] md5);
|
||||
|
||||
/**
|
||||
* @return InputStream, if downloading, or whatever was set during {@link #setPayload(Object)}
|
||||
*/
|
||||
public InputStream getContent() {
|
||||
checkState(payload != null, "payload");
|
||||
return payload.getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Payload getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setPayload(Payload data) {
|
||||
this.payload = checkNotNull(data, "data");
|
||||
setLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setPayload(InputStream data) {
|
||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setPayload(byte[] data) {
|
||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setPayload(String data) {
|
||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setPayload(File data) {
|
||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
||||
}
|
||||
|
||||
private void setLength() {
|
||||
if (getContentLength() == null) {
|
||||
Long size = payload.calculateSize();
|
||||
if (size != null)
|
||||
this.setContentLength(size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 #getContent()}
|
||||
* @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
|
||||
* @see GetObjectOptions
|
||||
*/
|
||||
public Long getContentLength() {
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
public void setContentLength(long contentLength) {
|
||||
this.contentLength = contentLength;
|
||||
}
|
||||
|
||||
}
|
|
@ -23,12 +23,9 @@
|
|||
*/
|
||||
package org.jclouds.http.internal;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
@ -133,23 +130,10 @@ public class JavaUrlHttpCommandExecutorService extends
|
|||
}
|
||||
}
|
||||
connection.setRequestProperty(HttpHeaders.HOST, request.getEndpoint().getHost());
|
||||
if (request.getEntity() != null) {
|
||||
if (request.getPayload() != null) {
|
||||
OutputStream out = connection.getOutputStream();
|
||||
try {
|
||||
if (request.getEntity() instanceof String) {
|
||||
OutputStreamWriter writer = new OutputStreamWriter(out);
|
||||
writer.write((String) request.getEntity());
|
||||
writer.close();
|
||||
} else if (request.getEntity() instanceof InputStream) {
|
||||
IOUtils.copy((InputStream) request.getEntity(), out);
|
||||
} else if (request.getEntity() instanceof File) {
|
||||
IOUtils.copy(new FileInputStream((File) request.getEntity()), out);
|
||||
} else if (request.getEntity() instanceof byte[]) {
|
||||
IOUtils.write((byte[]) request.getEntity(), out);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Content not supported "
|
||||
+ request.getEntity().getClass());
|
||||
}
|
||||
request.getPayload().writeTo(out);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(out);
|
||||
}
|
||||
|
|
|
@ -40,11 +40,11 @@ public class BaseHttpRequestOptions implements HttpRequestOptions {
|
|||
protected Multimap<String, String> formParameters = LinkedHashMultimap.create();
|
||||
protected Multimap<String, String> queryParameters = LinkedHashMultimap.create();
|
||||
protected Multimap<String, String> headers = LinkedHashMultimap.create();
|
||||
protected String entity;
|
||||
protected String payload;
|
||||
protected String pathSuffix;
|
||||
|
||||
public String buildStringEntity() {
|
||||
return entity;
|
||||
public String buildStringPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
protected String getFirstMatrixOrNull(String string) {
|
||||
|
|
|
@ -169,7 +169,7 @@ public class GetOptions extends BaseHttpRequestOptions {
|
|||
* Not compatible with {@link #ifETagDoesntMatch(byte[])} or {@link #ifModifiedSince(Date)}
|
||||
*
|
||||
* @param eTag
|
||||
* hash representing the entity
|
||||
* hash representing the payload
|
||||
* @throws UnsupportedEncodingException
|
||||
* if there was a problem converting this into an S3 eTag string
|
||||
*/
|
||||
|
@ -185,7 +185,7 @@ public class GetOptions extends BaseHttpRequestOptions {
|
|||
/**
|
||||
* For use in the request header: If-Match
|
||||
* <p />
|
||||
* Return the object only if its entity tag (ETag) is the same as the eTag specified, otherwise
|
||||
* Return the object only if its payload tag (ETag) is the same as the eTag specified, otherwise
|
||||
* return a 412 (precondition failed).
|
||||
*
|
||||
* @see GetOptions#ifETagMatches(byte[])
|
||||
|
@ -200,7 +200,7 @@ public class GetOptions extends BaseHttpRequestOptions {
|
|||
* Not compatible with {@link #ifETagMatches(String)} or {@link #ifUnmodifiedSince(Date)}
|
||||
*
|
||||
* @param eTag
|
||||
* hash representing the entity
|
||||
* hash representing the payload
|
||||
* @throws UnsupportedEncodingException
|
||||
* if there was a problem converting this into an S3 eTag string
|
||||
*/
|
||||
|
@ -217,7 +217,7 @@ public class GetOptions extends BaseHttpRequestOptions {
|
|||
/**
|
||||
* For use in the request header: If-None-Match
|
||||
* <p />
|
||||
* Return the object only if its entity tag (ETag) is different from the one specified, otherwise
|
||||
* Return the object only if its payload tag (ETag) is different from the one specified, otherwise
|
||||
* return a 304 (not modified).
|
||||
*
|
||||
* @see GetOptions#ifETagDoesntMatch(byte[])
|
||||
|
|
|
@ -61,7 +61,7 @@ public interface HttpRequestOptions {
|
|||
*/
|
||||
Multimap<String, String> buildMatrixParameters();
|
||||
|
||||
String buildStringEntity();
|
||||
String buildStringPayload();
|
||||
|
||||
String buildPathSuffix();
|
||||
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.http.payloads;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jclouds.http.Payload;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ByteArrayPayload implements Payload {
|
||||
private final byte[] content;
|
||||
|
||||
public ByteArrayPayload(byte[] content) {
|
||||
this.content = checkNotNull(content, "content");
|
||||
}
|
||||
|
||||
public byte[] getRawContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public InputStream getContent() {
|
||||
return new ByteArrayInputStream(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean isRepeatable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void writeTo(OutputStream outstream) throws IOException {
|
||||
IOUtils.write(content, outstream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long calculateSize() {
|
||||
return new Long(content.length);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.http.payloads;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jclouds.http.Payload;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class FilePayload implements Payload {
|
||||
private final File content;
|
||||
|
||||
public FilePayload(File content) {
|
||||
checkArgument(checkNotNull(content, "content").exists(), "file must exist: " + content);
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public File getRawContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public InputStream getContent() {
|
||||
try {
|
||||
return new FileInputStream(content);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new IllegalStateException("file " + content + " does not exist", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean isRepeatable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void writeTo(OutputStream outstream) throws IOException {
|
||||
InputStream in = getContent();
|
||||
try {
|
||||
IOUtils.copy(getContent(), outstream);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(in);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Long calculateSize() {
|
||||
return content.length();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.http.payloads;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jclouds.http.Payload;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class InputStreamPayload implements Payload {
|
||||
private final InputStream content;
|
||||
|
||||
public InputStreamPayload(InputStream content) {
|
||||
this.content = checkNotNull(content, "content");
|
||||
}
|
||||
|
||||
public InputStream getRawContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public InputStream getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean isRepeatable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void writeTo(OutputStream outstream) throws IOException {
|
||||
InputStream in = getContent();
|
||||
try {
|
||||
IOUtils.copy(getContent(), outstream);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(in);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Long calculateSize() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.http.payloads;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jclouds.http.Payload;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class StringPayload implements Payload {
|
||||
private final String content;
|
||||
|
||||
public StringPayload(String content) {
|
||||
this.content = checkNotNull(content, "content");
|
||||
}
|
||||
|
||||
public String getRawContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public InputStream getContent() {
|
||||
return IOUtils.toInputStream(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean isRepeatable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void writeTo(OutputStream outstream) throws IOException {
|
||||
IOUtils.write(content.getBytes(), outstream);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Long calculateSize() {
|
||||
return new Long(content.length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return content;
|
||||
}
|
||||
}
|
|
@ -26,7 +26,7 @@ package org.jclouds.rest;
|
|||
import org.jclouds.http.HttpRequest;
|
||||
|
||||
/**
|
||||
* Adds an entity to a request.
|
||||
* Adds an payload to a request.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
|
|
|
@ -28,7 +28,7 @@ import java.util.Map;
|
|||
import org.jclouds.http.HttpRequest;
|
||||
|
||||
/**
|
||||
* Builds the entity of a Post request.
|
||||
* Builds the payload of a Post request.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
|
@ -36,9 +36,9 @@ import org.jclouds.http.HttpRequest;
|
|||
public interface MapBinder extends Binder {
|
||||
|
||||
/**
|
||||
* creates and binds the POST entity to the request using parameters specified.
|
||||
* creates and binds the POST payload to the request using parameters specified.
|
||||
*
|
||||
* @see MapEntityParam
|
||||
* @see MapPayloadParam
|
||||
*/
|
||||
public void bindToRequest(HttpRequest request, Map<String, String> postParams);
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.lang.annotation.Target;
|
|||
import org.jclouds.rest.Binder;
|
||||
|
||||
/**
|
||||
* Designates that this parameter will modify the request, possibly including adding an entity to
|
||||
* Designates that this parameter will modify the request, possibly including adding an payload to
|
||||
* it.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
|
@ -42,7 +42,7 @@ import org.jclouds.rest.Binder;
|
|||
public @interface BinderParam {
|
||||
|
||||
/**
|
||||
* how to persist this entity.
|
||||
* how to persist this payload.
|
||||
*/
|
||||
Class<? extends Binder> value();
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import java.lang.annotation.Retention;
|
|||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Designates that this parameter will hold the entity for a PUT or POST command.
|
||||
* Designates that this parameter will hold the payload for a PUT or POST command.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
|
@ -39,7 +39,7 @@ import java.lang.annotation.Target;
|
|||
public @interface MapBinder {
|
||||
|
||||
/**
|
||||
* How to bind {@link MapEntityParam} values, if there is no {@link MapBinder} in the method
|
||||
* How to bind {@link MapPayloadParam} values, if there is no {@link MapBinder} in the method
|
||||
* definition
|
||||
*/
|
||||
Class<? extends org.jclouds.rest.MapBinder> value();
|
||||
|
|
|
@ -30,13 +30,13 @@ import java.lang.annotation.Retention;
|
|||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Designates that this parameter will hold the entity for a PUT or POST command.
|
||||
* Designates that this parameter will hold the payload for a PUT or POST command.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Target(PARAMETER)
|
||||
@Retention(RUNTIME)
|
||||
public @interface MapEntityParam {
|
||||
public @interface MapPayloadParam {
|
||||
|
||||
/**
|
||||
* The key used in a map passed to the {@link MapBinder} associated with the request.
|
|
@ -43,7 +43,7 @@ import com.google.gson.Gson;
|
|||
* @author Adrian Cole
|
||||
* @since 4.0
|
||||
*/
|
||||
public class BindToJsonEntity implements MapBinder {
|
||||
public class BindToJsonPayload implements MapBinder {
|
||||
|
||||
@Inject
|
||||
protected Gson gson;
|
||||
|
@ -55,7 +55,7 @@ public class BindToJsonEntity implements MapBinder {
|
|||
public void bindToRequest(HttpRequest request, Object toBind) {
|
||||
checkState(gson != null, "Program error: gson should have been injected at this point");
|
||||
String json = gson.toJson(toBind);
|
||||
request.setEntity(json);
|
||||
request.setPayload(json);
|
||||
request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH,
|
||||
Collections.singletonList(json.getBytes().length + ""));
|
||||
request.getHeaders().replaceValues(HttpHeaders.CONTENT_TYPE,
|
|
@ -32,17 +32,17 @@ import org.jclouds.http.HttpRequest;
|
|||
import org.jclouds.rest.Binder;
|
||||
|
||||
/**
|
||||
* Adds an entity to a request.
|
||||
* Adds an payload to a request.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class BindToStringEntity implements Binder {
|
||||
public void bindToRequest(HttpRequest request, Object entity) {
|
||||
String stringEntity = entity.toString();
|
||||
public class BindToStringPayload implements Binder {
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
String stringPayload = payload.toString();
|
||||
if (request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE) == null)
|
||||
request.getHeaders().put(HttpHeaders.CONTENT_TYPE, "application/unknown");
|
||||
request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH,Collections.singletonList(stringEntity.getBytes().length + ""));
|
||||
request.setEntity(stringEntity);
|
||||
request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH,Collections.singletonList(stringPayload.getBytes().length + ""));
|
||||
request.setPayload(stringPayload);
|
||||
}
|
||||
}
|
|
@ -91,6 +91,8 @@ public class GeneratedHttpRequest<T> extends HttpRequest {
|
|||
}
|
||||
|
||||
public void addFormParam(String name, String... values) {
|
||||
this.setEntity(processor.addFormParam(getEntity().toString(), name, values));
|
||||
this
|
||||
.setPayload(processor.addFormParam(getPayload().getRawContent().toString(), name,
|
||||
values));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ import org.jclouds.rest.annotations.FormParams;
|
|||
import org.jclouds.rest.annotations.Headers;
|
||||
import org.jclouds.rest.annotations.HostPrefixParam;
|
||||
import org.jclouds.rest.annotations.MapBinder;
|
||||
import org.jclouds.rest.annotations.MapEntityParam;
|
||||
import org.jclouds.rest.annotations.MapPayloadParam;
|
||||
import org.jclouds.rest.annotations.MatrixParams;
|
||||
import org.jclouds.rest.annotations.OverrideRequestFilters;
|
||||
import org.jclouds.rest.annotations.ParamParser;
|
||||
|
@ -132,7 +132,7 @@ public class RestAnnotationProcessor<T> {
|
|||
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToFormParamAnnotations = createMethodToIndexOfParamToAnnotation(FormParam.class);
|
||||
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToQueryParamAnnotations = createMethodToIndexOfParamToAnnotation(QueryParam.class);
|
||||
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToPathParamAnnotations = createMethodToIndexOfParamToAnnotation(PathParam.class);
|
||||
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToPostParamAnnotations = createMethodToIndexOfParamToAnnotation(MapEntityParam.class);
|
||||
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToPostParamAnnotations = createMethodToIndexOfParamToAnnotation(MapPayloadParam.class);
|
||||
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToParamParserAnnotations = createMethodToIndexOfParamToAnnotation(ParamParser.class);
|
||||
private final Map<MethodKey, Method> delegationMap = Maps.newHashMap();
|
||||
|
||||
|
@ -329,7 +329,7 @@ public class RestAnnotationProcessor<T> {
|
|||
|
||||
Multimap<String, String> headers = buildHeaders(tokenValues.entries(), method, args);
|
||||
|
||||
String stringEntity = null;
|
||||
String stringPayload = null;
|
||||
HttpRequestOptions options = findOptionsIn(method, args);
|
||||
if (options != null) {
|
||||
injector.injectMembers(options);// TODO test case
|
||||
|
@ -351,7 +351,7 @@ public class RestAnnotationProcessor<T> {
|
|||
if (pathSuffix != null) {
|
||||
builder.path(pathSuffix);
|
||||
}
|
||||
stringEntity = options.buildStringEntity();
|
||||
stringPayload = options.buildStringPayload();
|
||||
}
|
||||
|
||||
if (queryParams.size() > 0) {
|
||||
|
@ -375,13 +375,13 @@ public class RestAnnotationProcessor<T> {
|
|||
if (formParams.size() > 0) {
|
||||
if (headers.get(HttpHeaders.CONTENT_TYPE) != null)
|
||||
headers.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED);
|
||||
request.setEntity(makeQueryLine(formParams, null, skips));
|
||||
request.setPayload(makeQueryLine(formParams, null, skips));
|
||||
}
|
||||
|
||||
if (stringEntity != null) {
|
||||
request.setEntity(stringEntity);
|
||||
if (stringPayload != null) {
|
||||
request.setPayload(stringPayload);
|
||||
if (headers.get(HttpHeaders.CONTENT_LENGTH) != null)
|
||||
headers.put(HttpHeaders.CONTENT_LENGTH, stringEntity.getBytes().length + "");
|
||||
headers.put(HttpHeaders.CONTENT_LENGTH, stringPayload.getBytes().length + "");
|
||||
if (headers.get(HttpHeaders.CONTENT_TYPE) != null)
|
||||
headers.put(HttpHeaders.CONTENT_TYPE, "application/unknown");
|
||||
}
|
||||
|
@ -669,7 +669,7 @@ public class RestAnnotationProcessor<T> {
|
|||
return null;
|
||||
}
|
||||
|
||||
public org.jclouds.rest.MapBinder getMapEntityBinderOrNull(Method method, Object... args) {
|
||||
public org.jclouds.rest.MapBinder getMapPayloadBinderOrNull(Method method, Object... args) {
|
||||
if (args != null) {
|
||||
for (Object arg : args) {
|
||||
if (arg instanceof Object[]) {
|
||||
|
@ -737,11 +737,11 @@ public class RestAnnotationProcessor<T> {
|
|||
}
|
||||
|
||||
public void decorateRequest(GeneratedHttpRequest<T> request) {
|
||||
org.jclouds.rest.MapBinder mapBinder = getMapEntityBinderOrNull(request.getJavaMethod(),
|
||||
org.jclouds.rest.MapBinder mapBinder = getMapPayloadBinderOrNull(request.getJavaMethod(),
|
||||
request.getArgs());
|
||||
Map<String, String> mapParams = buildPostParams(request.getJavaMethod(), request.getArgs());
|
||||
// MapEntityBinder is only useful if there are parameters. We guard here in case the
|
||||
// MapEntityBinder is also an EntityBinder. If so, it can be used with or without
|
||||
// MapPayloadBinder is only useful if there are parameters. We guard here in case the
|
||||
// MapPayloadBinder is also an PayloadBinder. If so, it can be used with or without
|
||||
// parameters.
|
||||
if (mapBinder != null) {
|
||||
mapBinder.bindToRequest(request, mapParams);
|
||||
|
@ -756,8 +756,8 @@ public class RestAnnotationProcessor<T> {
|
|||
}
|
||||
}).entrySet()) {
|
||||
boolean shouldBreak = false;
|
||||
BinderParam entityAnnotation = (BinderParam) entry.getValue().iterator().next();
|
||||
Binder binder = injector.getInstance(entityAnnotation.value());
|
||||
BinderParam payloadAnnotation = (BinderParam) entry.getValue().iterator().next();
|
||||
Binder binder = injector.getInstance(payloadAnnotation.value());
|
||||
if (request.getArgs().length != 0) {
|
||||
Object input;
|
||||
Class<?> parameterType = request.getJavaMethod().getParameterTypes()[entry.getKey()];
|
||||
|
@ -778,8 +778,8 @@ public class RestAnnotationProcessor<T> {
|
|||
} else {
|
||||
input = request.getArgs()[entry.getKey()];
|
||||
if (input.getClass().isArray()) {
|
||||
Object[] entityArray = (Object[]) input;
|
||||
input = entityArray.length > 0 ? entityArray[0] : null;
|
||||
Object[] payloadArray = (Object[]) input;
|
||||
input = payloadArray.length > 0 ? payloadArray[0] : null;
|
||||
}
|
||||
}
|
||||
if (input != null) {
|
||||
|
@ -789,27 +789,29 @@ public class RestAnnotationProcessor<T> {
|
|||
break OUTER;
|
||||
}
|
||||
}
|
||||
if (request.getMethod().equals("PUT") && request.getEntity() == null) {
|
||||
if (request.getMethod().equals("PUT") && request.getPayload() == null) {
|
||||
request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH,
|
||||
Collections.singletonList(0 + ""));
|
||||
}
|
||||
if (request.getPayload() != null)
|
||||
assert request.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH) != null : "no content length";
|
||||
}
|
||||
|
||||
protected Map<Integer, Set<Annotation>> indexWithOnlyOneAnnotation(Method method,
|
||||
String description, Map<Method, Map<Integer, Set<Annotation>>> toRefine) {
|
||||
Map<Integer, Set<Annotation>> indexToEntityAnnotation = Maps.filterValues(toRefine
|
||||
Map<Integer, Set<Annotation>> indexToPayloadAnnotation = Maps.filterValues(toRefine
|
||||
.get(method), new Predicate<Set<Annotation>>() {
|
||||
public boolean apply(Set<Annotation> input) {
|
||||
return input.size() == 1;
|
||||
}
|
||||
});
|
||||
|
||||
if (indexToEntityAnnotation.size() > 1) {
|
||||
if (indexToPayloadAnnotation.size() > 1) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"You must not specify more than one %s annotation on: %s; found %s", description,
|
||||
method.toString(), indexToEntityAnnotation));
|
||||
method.toString(), indexToPayloadAnnotation));
|
||||
}
|
||||
return indexToEntityAnnotation;
|
||||
return indexToPayloadAnnotation;
|
||||
}
|
||||
|
||||
private HttpRequestOptions findOptionsIn(Method method, Object... args) {
|
||||
|
@ -1069,7 +1071,7 @@ public class RestAnnotationProcessor<T> {
|
|||
for (Entry<Integer, Set<Annotation>> entry : indexToPathParam.entrySet()) {
|
||||
for (Annotation key : entry.getValue()) {
|
||||
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
||||
String paramKey = ((MapEntityParam) key).value();
|
||||
String paramKey = ((MapPayloadParam) key).value();
|
||||
String paramValue;
|
||||
if (extractors != null && extractors.size() > 0) {
|
||||
ParamParser extractor = (ParamParser) extractors.iterator().next();
|
||||
|
|
|
@ -41,12 +41,12 @@ import org.jclouds.rest.annotations.BinderParam;
|
|||
import org.jclouds.rest.annotations.Endpoint;
|
||||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.MapBinder;
|
||||
import org.jclouds.rest.annotations.MapEntityParam;
|
||||
import org.jclouds.rest.annotations.MapPayloadParam;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.XMLResponseParser;
|
||||
import org.jclouds.rest.binders.BindMapToMatrixParams;
|
||||
import org.jclouds.rest.binders.BindToJsonEntity;
|
||||
import org.jclouds.rest.binders.BindToStringEntity;
|
||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||
import org.jclouds.rest.binders.BindToStringPayload;
|
||||
import org.jclouds.rest.internal.RestAnnotationProcessorTest.Localhost;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
@ -92,30 +92,30 @@ public interface IntegrationTestAsyncClient {
|
|||
@PUT
|
||||
@Path("objects/{id}")
|
||||
Future<String> upload(@PathParam("id") String id,
|
||||
@BinderParam(BindToStringEntity.class) String toPut);
|
||||
@BinderParam(BindToStringPayload.class) String toPut);
|
||||
|
||||
@POST
|
||||
@Path("objects/{id}")
|
||||
Future<String> post(@PathParam("id") String id,
|
||||
@BinderParam(BindToStringEntity.class) String toPut);
|
||||
@BinderParam(BindToStringPayload.class) String toPut);
|
||||
|
||||
@POST
|
||||
@Path("objects/{id}")
|
||||
Future<String> postAsInputStream(@PathParam("id") String id,
|
||||
@BinderParam(BindToInputStreamEntity.class) String toPut);
|
||||
@BinderParam(BindToInputStreamPayload.class) String toPut);
|
||||
|
||||
static class BindToInputStreamEntity extends BindToStringEntity {
|
||||
static class BindToInputStreamPayload extends BindToStringPayload {
|
||||
@Override
|
||||
public void bindToRequest(HttpRequest request, Object entity) {
|
||||
super.bindToRequest(request, entity);
|
||||
request.setEntity(IOUtils.toInputStream(entity.toString()));
|
||||
public void bindToRequest(HttpRequest request, Object payload) {
|
||||
super.bindToRequest(request, payload);
|
||||
request.setPayload(IOUtils.toInputStream(payload.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("objects/{id}")
|
||||
@MapBinder(BindToJsonEntity.class)
|
||||
Future<String> postJson(@PathParam("id") String id, @MapEntityParam("key") String toPut);
|
||||
@MapBinder(BindToJsonPayload.class)
|
||||
Future<String> postJson(@PathParam("id") String id, @MapPayloadParam("key") String toPut);
|
||||
|
||||
@POST
|
||||
@Path("objects/{id}/action/{action}")
|
||||
|
|
|
@ -27,7 +27,6 @@ import static org.testng.Assert.assertEquals;
|
|||
import static org.testng.Assert.assertNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
@ -55,6 +54,7 @@ public abstract class RestClientTest<T> {
|
|||
protected abstract Module createModule();
|
||||
|
||||
protected abstract void checkFilters(GeneratedHttpRequest<T> httpMethod);
|
||||
|
||||
protected abstract TypeLiteral<RestAnnotationProcessor<T>> createTypeLiteral();
|
||||
|
||||
@BeforeClass
|
||||
|
@ -63,18 +63,16 @@ public abstract class RestClientTest<T> {
|
|||
injector = Guice.createInjector(createModule(), new RestModule(), new ExecutorServiceModule(
|
||||
new WithinThreadExecutorService()), new JavaUrlHttpCommandExecutorServiceModule());
|
||||
|
||||
processor = injector.getInstance(Key
|
||||
.get(createTypeLiteral()));
|
||||
processor = injector.getInstance(Key.get(createTypeLiteral()));
|
||||
}
|
||||
|
||||
protected void assertEntityEquals(GeneratedHttpRequest<T> httpMethod, String toMatch)
|
||||
protected void assertPayloadEquals(GeneratedHttpRequest<T> httpMethod, String toMatch)
|
||||
throws IOException {
|
||||
if (httpMethod.getEntity() == null) {
|
||||
if (httpMethod.getPayload() == null) {
|
||||
assertNull(toMatch);
|
||||
} else {
|
||||
String entity = (httpMethod.getEntity() instanceof String) ? httpMethod.getEntity()
|
||||
.toString() : IOUtils.toString((InputStream) httpMethod.getEntity());
|
||||
assertEquals(entity, toMatch);
|
||||
String payload = IOUtils.toString(httpMethod.getPayload().getContent());
|
||||
assertEquals(payload, toMatch);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,8 +80,7 @@ public abstract class RestClientTest<T> {
|
|||
assertEquals(HttpUtils.sortAndConcatHeadersIntoString(httpMethod.getHeaders()), toMatch);
|
||||
}
|
||||
|
||||
protected void assertRequestLineEquals(GeneratedHttpRequest<T> httpMethod,
|
||||
String toMatch) {
|
||||
protected void assertRequestLineEquals(GeneratedHttpRequest<T> httpMethod, String toMatch) {
|
||||
assertEquals(httpMethod.getRequestLine(), toMatch);
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ import org.jclouds.rest.annotations.FormParams;
|
|||
import org.jclouds.rest.annotations.Headers;
|
||||
import org.jclouds.rest.annotations.HostPrefixParam;
|
||||
import org.jclouds.rest.annotations.MapBinder;
|
||||
import org.jclouds.rest.annotations.MapEntityParam;
|
||||
import org.jclouds.rest.annotations.MapPayloadParam;
|
||||
import org.jclouds.rest.annotations.MatrixParams;
|
||||
import org.jclouds.rest.annotations.OverrideRequestFilters;
|
||||
import org.jclouds.rest.annotations.ParamParser;
|
||||
|
@ -98,8 +98,8 @@ import org.jclouds.rest.annotations.ResponseParser;
|
|||
import org.jclouds.rest.annotations.SkipEncoding;
|
||||
import org.jclouds.rest.annotations.VirtualHost;
|
||||
import org.jclouds.rest.binders.BindMapToMatrixParams;
|
||||
import org.jclouds.rest.binders.BindToJsonEntity;
|
||||
import org.jclouds.rest.binders.BindToStringEntity;
|
||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||
import org.jclouds.rest.binders.BindToStringPayload;
|
||||
import org.jclouds.rest.config.RestModule;
|
||||
import org.jclouds.util.Jsr330;
|
||||
import org.mortbay.jetty.HttpHeaders;
|
||||
|
@ -206,7 +206,7 @@ public class RestAnnotationProcessorTest {
|
|||
}
|
||||
|
||||
@Endpoint(Localhost.class)
|
||||
public interface TestEntityParamVarargs {
|
||||
public interface TestPayloadParamVarargs {
|
||||
@POST
|
||||
public void varargs(HttpRequestOptions... options);
|
||||
|
||||
|
@ -215,19 +215,19 @@ public class RestAnnotationProcessorTest {
|
|||
|
||||
}
|
||||
|
||||
public void testHttpRequestOptionsEntityParam() throws SecurityException, NoSuchMethodException {
|
||||
Method method = TestEntityParamVarargs.class.getMethod("post", HttpRequestOptions.class);
|
||||
public void testHttpRequestOptionsPayloadParam() throws SecurityException, NoSuchMethodException {
|
||||
Method method = TestPayloadParamVarargs.class.getMethod("post", HttpRequestOptions.class);
|
||||
verifyTestPostOptions(method);
|
||||
}
|
||||
|
||||
public void testEntityParamVarargs() throws SecurityException, NoSuchMethodException {
|
||||
Method method = TestEntityParamVarargs.class.getMethod("varargs", Array.newInstance(
|
||||
public void testPayloadParamVarargs() throws SecurityException, NoSuchMethodException {
|
||||
Method method = TestPayloadParamVarargs.class.getMethod("varargs", Array.newInstance(
|
||||
HttpRequestOptions.class, 0).getClass());
|
||||
verifyTestPostOptions(method);
|
||||
}
|
||||
|
||||
private void verifyTestPostOptions(Method method) {
|
||||
GeneratedHttpRequest<?> httpMethod = factory(TestEntityParamVarargs.class).createRequest(
|
||||
GeneratedHttpRequest<?> httpMethod = factory(TestPayloadParamVarargs.class).createRequest(
|
||||
method, new Object[] { new HttpRequestOptions() {
|
||||
|
||||
public Multimap<String, String> buildMatrixParameters() {
|
||||
|
@ -250,7 +250,7 @@ public class RestAnnotationProcessorTest {
|
|||
return LinkedHashMultimap.create();
|
||||
}
|
||||
|
||||
public String buildStringEntity() {
|
||||
public String buildStringPayload() {
|
||||
return "fooya";
|
||||
}
|
||||
|
||||
|
@ -263,7 +263,7 @@ public class RestAnnotationProcessorTest {
|
|||
.singletonList("application/unknown"));
|
||||
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
|
||||
.singletonList("fooya".getBytes().length + ""));
|
||||
assertEquals(httpMethod.getEntity(), "fooya");
|
||||
assertEquals(httpMethod.getPayload().toString(), "fooya");
|
||||
}
|
||||
|
||||
@Endpoint(Localhost.class)
|
||||
|
@ -338,23 +338,23 @@ public class RestAnnotationProcessorTest {
|
|||
@Endpoint(Localhost.class)
|
||||
public class TestPost {
|
||||
@POST
|
||||
public void post(@BinderParam(BindToStringEntity.class) String content) {
|
||||
public void post(@BinderParam(BindToStringPayload.class) String content) {
|
||||
}
|
||||
|
||||
@POST
|
||||
public void postAsJson(@BinderParam(BindToJsonEntity.class) String content) {
|
||||
public void postAsJson(@BinderParam(BindToJsonPayload.class) String content) {
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{foo}")
|
||||
public void postWithPath(@PathParam("foo") @MapEntityParam("fooble") String path,
|
||||
public void postWithPath(@PathParam("foo") @MapPayloadParam("fooble") String path,
|
||||
MapBinder content) {
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{foo}")
|
||||
@MapBinder(BindToJsonEntity.class)
|
||||
public void postWithMethodBinder(@PathParam("foo") @MapEntityParam("fooble") String path) {
|
||||
@MapBinder(BindToJsonPayload.class)
|
||||
public void postWithMethodBinder(@PathParam("foo") @MapPayloadParam("fooble") String path) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,7 +370,7 @@ public class RestAnnotationProcessorTest {
|
|||
.singletonList("application/unknown"));
|
||||
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
|
||||
.singletonList("data".getBytes().length + ""));
|
||||
assertEquals(httpMethod.getEntity(), "data");
|
||||
assertEquals(httpMethod.getPayload().toString(), "data");
|
||||
}
|
||||
|
||||
public void testCreatePostJsonRequest() throws SecurityException, NoSuchMethodException {
|
||||
|
@ -385,7 +385,7 @@ public class RestAnnotationProcessorTest {
|
|||
.singletonList("application/json"));
|
||||
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
|
||||
.singletonList("\"data\"".getBytes().length + ""));
|
||||
assertEquals(httpMethod.getEntity(), "\"data\"");
|
||||
assertEquals(httpMethod.getPayload().toString(), "\"data\"");
|
||||
}
|
||||
|
||||
public void testCreatePostWithPathRequest() throws SecurityException, NoSuchMethodException {
|
||||
|
@ -393,7 +393,7 @@ public class RestAnnotationProcessorTest {
|
|||
GeneratedHttpRequest<?> httpMethod = factory(TestPost.class).createRequest(method,
|
||||
new Object[] { "data", new org.jclouds.rest.MapBinder() {
|
||||
public void bindToRequest(HttpRequest request, Map<String, String> postParams) {
|
||||
request.setEntity(postParams.get("fooble"));
|
||||
request.setPayload(postParams.get("fooble"));
|
||||
}
|
||||
|
||||
public void bindToRequest(HttpRequest request, Object toBind) {
|
||||
|
@ -404,7 +404,7 @@ public class RestAnnotationProcessorTest {
|
|||
assertEquals(httpMethod.getEndpoint().getPath(), "/data");
|
||||
assertEquals(httpMethod.getMethod(), HttpMethod.POST);
|
||||
assertEquals(httpMethod.getHeaders().size(), 1);
|
||||
assertEquals(httpMethod.getEntity(), "data");
|
||||
assertEquals(httpMethod.getPayload().toString(), "data");
|
||||
}
|
||||
|
||||
public void testCreatePostWithMethodBinder() throws SecurityException, NoSuchMethodException {
|
||||
|
@ -420,30 +420,30 @@ public class RestAnnotationProcessorTest {
|
|||
String expected = "{\"fooble\":\"data\"}";
|
||||
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
|
||||
.singletonList(expected.getBytes().length + ""));
|
||||
assertEquals(httpMethod.getEntity(), expected);
|
||||
assertEquals(httpMethod.getPayload().toString(), expected);
|
||||
}
|
||||
|
||||
@Endpoint(Localhost.class)
|
||||
public class TestPut {
|
||||
@PUT
|
||||
@Path("{foo}")
|
||||
@MapBinder(BindToJsonEntity.class)
|
||||
public void putWithMethodBinder(@PathParam("foo") @MapEntityParam("fooble") String path) {
|
||||
@MapBinder(BindToJsonPayload.class)
|
||||
public void putWithMethodBinder(@PathParam("foo") @MapPayloadParam("fooble") String path) {
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{foo}")
|
||||
@Produces(MediaType.TEXT_PLAIN)
|
||||
public void putWithMethodBinderProduces(
|
||||
@PathParam("foo") @BinderParam(BindToStringEntity.class) String path) {
|
||||
@PathParam("foo") @BinderParam(BindToStringPayload.class) String path) {
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{foo}")
|
||||
@MapBinder(BindToJsonEntity.class)
|
||||
@MapBinder(BindToJsonPayload.class)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void putWithMethodBinderConsumes(
|
||||
@PathParam("foo") @MapEntityParam("fooble") String path) {
|
||||
@PathParam("foo") @MapPayloadParam("fooble") String path) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,7 +460,7 @@ public class RestAnnotationProcessorTest {
|
|||
String expected = "{\"fooble\":\"data\"}";
|
||||
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
|
||||
.singletonList(expected.getBytes().length + ""));
|
||||
assertEquals(httpMethod.getEntity(), expected);
|
||||
assertEquals(httpMethod.getPayload().toString(), expected);
|
||||
}
|
||||
|
||||
public void testCreatePutWithMethodProduces() throws SecurityException, NoSuchMethodException {
|
||||
|
@ -475,7 +475,7 @@ public class RestAnnotationProcessorTest {
|
|||
.singletonList("text/plain"));
|
||||
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
|
||||
.singletonList("data".getBytes().length + ""));
|
||||
assertEquals(httpMethod.getEntity(), "data");
|
||||
assertEquals(httpMethod.getPayload().toString(), "data");
|
||||
}
|
||||
|
||||
public void testCreatePutWithMethodConsumes() throws SecurityException, NoSuchMethodException {
|
||||
|
@ -493,7 +493,7 @@ public class RestAnnotationProcessorTest {
|
|||
String expected = "{\"fooble\":\"data\"}";
|
||||
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
|
||||
.singletonList(expected.getBytes().length + ""));
|
||||
assertEquals(httpMethod.getEntity(), expected);
|
||||
assertEquals(httpMethod.getPayload().toString(), expected);
|
||||
}
|
||||
|
||||
static class TestRequestFilter1 implements HttpRequestFilter {
|
||||
|
@ -589,7 +589,7 @@ public class RestAnnotationProcessorTest {
|
|||
assertRequestLineEquals(httpMethod,
|
||||
"GET http://localhost:8080/v1/ralphie/1/localhost HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, "");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
}
|
||||
|
||||
@Endpoint(Localhost.class)
|
||||
|
@ -650,7 +650,7 @@ public class RestAnnotationProcessorTest {
|
|||
new Object[] { "localhost" });
|
||||
assertRequestLineEquals(httpMethod, "GET http://localhost:8080/l HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, "");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -661,7 +661,7 @@ public class RestAnnotationProcessorTest {
|
|||
"localhost");
|
||||
assertRequestLineEquals(httpMethod, "GET http://localhost:8080/?one=l HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, "");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -672,7 +672,7 @@ public class RestAnnotationProcessorTest {
|
|||
new Object[] { "localhost" });
|
||||
assertRequestLineEquals(httpMethod, "GET http://localhost:8080/;one=l HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, "");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -684,7 +684,7 @@ public class RestAnnotationProcessorTest {
|
|||
assertRequestLineEquals(httpMethod, "POST http://localhost:8080/ HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod,
|
||||
"Content-Length: 5\nContent-Type: application/x-www-form-urlencoded\n");
|
||||
assertEntityEquals(httpMethod, "one=l");
|
||||
assertPayloadEquals(httpMethod, "one=l");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1149,7 +1149,7 @@ public class RestAnnotationProcessorTest {
|
|||
@PUT
|
||||
@Path("/{id}")
|
||||
public Future<String> put(@PathParam("id") @ParamParser(FirstCharacter.class) String id,
|
||||
@BinderParam(BindToStringEntity.class) String payload) {
|
||||
@BinderParam(BindToStringPayload.class) String payload) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1165,7 +1165,7 @@ public class RestAnnotationProcessorTest {
|
|||
@Headers(keys = "foo", values = "--{id}--")
|
||||
@ResponseParser(ReturnTrueIf2xx.class)
|
||||
public Future<String> putHeader(@PathParam("id") String id,
|
||||
@BinderParam(BindToStringEntity.class) String payload) {
|
||||
@BinderParam(BindToStringPayload.class) String payload) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1221,7 +1221,7 @@ public class RestAnnotationProcessorTest {
|
|||
new Object[] { "1", options });
|
||||
assertRequestLineEquals(httpMethod, "GET http://localhost:8080/1?prefix=1 HTTP/1.1");
|
||||
assertHeadersEqual(httpMethod, "Host: localhost\n");
|
||||
assertEntityEquals(httpMethod, null);
|
||||
assertPayloadEquals(httpMethod, null);
|
||||
}
|
||||
|
||||
public void testCreateGetQuery() throws SecurityException, NoSuchMethodException {
|
||||
|
@ -1247,16 +1247,16 @@ public class RestAnnotationProcessorTest {
|
|||
}
|
||||
|
||||
@Endpoint(Localhost.class)
|
||||
public class EntityOptions extends BaseHttpRequestOptions {
|
||||
public class PayloadOptions extends BaseHttpRequestOptions {
|
||||
@Override
|
||||
public String buildStringEntity() {
|
||||
public String buildStringPayload() {
|
||||
return "foo";
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateGetOptionsThatProducesEntity() throws SecurityException,
|
||||
public void testCreateGetOptionsThatProducesPayload() throws SecurityException,
|
||||
NoSuchMethodException {
|
||||
EntityOptions options = new EntityOptions();
|
||||
PayloadOptions options = new PayloadOptions();
|
||||
Method method = TestRequest.class.getMethod("putOptions", String.class,
|
||||
HttpRequestOptions.class);
|
||||
GeneratedHttpRequest<?> httpMethod = factory(TestRequest.class).createRequest(method,
|
||||
|
@ -1267,7 +1267,7 @@ public class RestAnnotationProcessorTest {
|
|||
assertEquals(httpMethod.getHeaders().size(), 3);
|
||||
assertEquals(httpMethod.getHeaders().get(HttpHeaders.HOST), Collections
|
||||
.singletonList("localhost"));
|
||||
assertEquals(httpMethod.getEntity(), "foo");
|
||||
assertEquals(httpMethod.getPayload().toString(), "foo");
|
||||
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections
|
||||
.singletonList("application/unknown"));
|
||||
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
|
||||
|
@ -1307,7 +1307,7 @@ public class RestAnnotationProcessorTest {
|
|||
.singletonList("application/unknown"));
|
||||
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
|
||||
.singletonList("data".getBytes().length + ""));
|
||||
assertEquals(httpMethod.getEntity(), "data");
|
||||
assertEquals(httpMethod.getPayload().toString(), "data");
|
||||
}
|
||||
|
||||
public void testCreatePutHeader() throws SecurityException, NoSuchMethodException {
|
||||
|
@ -1323,7 +1323,7 @@ public class RestAnnotationProcessorTest {
|
|||
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
|
||||
.singletonList("data".getBytes().length + ""));
|
||||
assertEquals(httpMethod.getHeaders().get("foo"), Collections.singletonList("--1--"));
|
||||
assertEquals(httpMethod.getEntity(), "data");
|
||||
assertEquals(httpMethod.getPayload().toString(), "data");
|
||||
}
|
||||
|
||||
@Endpoint(Localhost.class)
|
||||
|
@ -1480,28 +1480,28 @@ public class RestAnnotationProcessorTest {
|
|||
}
|
||||
|
||||
@Endpoint(Localhost.class)
|
||||
public interface TestEntity {
|
||||
public interface TestPayload {
|
||||
@PUT
|
||||
public void put(@BinderParam(BindToStringEntity.class) String content);
|
||||
public void put(@BinderParam(BindToStringPayload.class) String content);
|
||||
|
||||
@PUT
|
||||
@Path("{foo}")
|
||||
public Future<Void> putWithPath(@PathParam("foo") String path,
|
||||
@BinderParam(BindToStringEntity.class) String content);
|
||||
@BinderParam(BindToStringPayload.class) String content);
|
||||
|
||||
@PUT
|
||||
public void twoEntities(@BinderParam(BindToStringEntity.class) String entity1,
|
||||
@BinderParam(BindToStringEntity.class) String entity2);
|
||||
public void twoEntities(@BinderParam(BindToStringPayload.class) String payload1,
|
||||
@BinderParam(BindToStringPayload.class) String payload2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPut() throws SecurityException, NoSuchMethodException {
|
||||
RestAnnotationProcessor<TestEntity> processor = factory(TestEntity.class);
|
||||
Method method = TestEntity.class.getMethod("put", String.class);
|
||||
GeneratedHttpRequest<TestEntity> request = new GeneratedHttpRequest<TestEntity>("GET", URI
|
||||
.create("http://localhost"), processor, TestEntity.class, method, "test");
|
||||
RestAnnotationProcessor<TestPayload> processor = factory(TestPayload.class);
|
||||
Method method = TestPayload.class.getMethod("put", String.class);
|
||||
GeneratedHttpRequest<TestPayload> request = new GeneratedHttpRequest<TestPayload>("GET", URI
|
||||
.create("http://localhost"), processor, TestPayload.class, method, "test");
|
||||
processor.decorateRequest(request);
|
||||
assertEquals(request.getEntity(), "test");
|
||||
assertEquals(request.getPayload().toString(), "test");
|
||||
assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections
|
||||
.singletonList("application/unknown"));
|
||||
assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
|
||||
|
@ -1513,12 +1513,12 @@ public class RestAnnotationProcessorTest {
|
|||
@Test
|
||||
public void putWithPath() throws SecurityException, NoSuchMethodException {
|
||||
|
||||
RestAnnotationProcessor<TestEntity> processor = factory(TestEntity.class);
|
||||
Method method = TestEntity.class.getMethod("putWithPath", String.class, String.class);
|
||||
GeneratedHttpRequest<TestEntity> request = new GeneratedHttpRequest<TestEntity>("GET", URI
|
||||
.create("http://localhost"), processor, TestEntity.class, method, "rabble", "test");
|
||||
RestAnnotationProcessor<TestPayload> processor = factory(TestPayload.class);
|
||||
Method method = TestPayload.class.getMethod("putWithPath", String.class, String.class);
|
||||
GeneratedHttpRequest<TestPayload> request = new GeneratedHttpRequest<TestPayload>("GET", URI
|
||||
.create("http://localhost"), processor, TestPayload.class, method, "rabble", "test");
|
||||
processor.decorateRequest(request);
|
||||
assertEquals(request.getEntity(), "test");
|
||||
assertEquals(request.getPayload().toString(), "test");
|
||||
assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections
|
||||
.singletonList("application/unknown"));
|
||||
assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
|
||||
|
@ -1566,7 +1566,7 @@ public class RestAnnotationProcessorTest {
|
|||
UnsupportedEncodingException {
|
||||
Method oneForm = TestFormReplace.class.getMethod("twoForm", String.class);
|
||||
String form = factory(TestFormReplace.class).createRequest(oneForm, new Object[] { "robot" })
|
||||
.getEntity().toString();
|
||||
.getPayload().toString().toString();
|
||||
assertEquals(form, "slash=/robot&hyphen=-robot");
|
||||
}
|
||||
|
||||
|
@ -1584,7 +1584,7 @@ public class RestAnnotationProcessorTest {
|
|||
UnsupportedEncodingException {
|
||||
Method oneForm = TestClassForm.class.getMethod("oneForm", String.class);
|
||||
String form = factory(TestClassForm.class).createRequest(oneForm, new Object[] { "robot" })
|
||||
.getEntity().toString();
|
||||
.getPayload().toString().toString();
|
||||
assertEquals(form, "x-amz-copy-source=/robot");
|
||||
}
|
||||
|
||||
|
@ -1593,7 +1593,7 @@ public class RestAnnotationProcessorTest {
|
|||
UnsupportedEncodingException {
|
||||
Method oneForm = TestFormReplace.class.getMethod("oneForm", String.class);
|
||||
String form = factory(TestFormReplace.class).createRequest(oneForm, new Object[] { "robot" })
|
||||
.getEntity().toString();
|
||||
.getPayload().toString().toString();
|
||||
assertEquals(form, "x-amz-copy-source=/robot");
|
||||
}
|
||||
|
||||
|
@ -1602,7 +1602,7 @@ public class RestAnnotationProcessorTest {
|
|||
UnsupportedEncodingException {
|
||||
Method twoForms = TestFormReplace.class.getMethod("twoForms", String.class, String.class);
|
||||
String form = factory(TestFormReplace.class).createRequest(twoForms,
|
||||
new Object[] { "robot", "eggs" }).getEntity().toString();
|
||||
new Object[] { "robot", "eggs" }).getPayload().toString().toString();
|
||||
assertEquals(form, "x-amz-copy-source=/robot/eggs");
|
||||
}
|
||||
|
||||
|
@ -1612,7 +1612,7 @@ public class RestAnnotationProcessorTest {
|
|||
Method twoFormsOutOfOrder = TestFormReplace.class.getMethod("twoFormsOutOfOrder",
|
||||
String.class, String.class);
|
||||
String form = factory(TestFormReplace.class).createRequest(twoFormsOutOfOrder,
|
||||
new Object[] { "robot", "eggs" }).getEntity().toString();
|
||||
new Object[] { "robot", "eggs" }).getPayload().toString().toString();
|
||||
assertEquals(form, "x-amz-copy-source=/eggs/robot");
|
||||
}
|
||||
|
||||
|
@ -1646,14 +1646,13 @@ public class RestAnnotationProcessorTest {
|
|||
|
||||
}
|
||||
|
||||
protected void assertEntityEquals(GeneratedHttpRequest<?> httpMethod, String toMatch)
|
||||
protected void assertPayloadEquals(GeneratedHttpRequest<?> httpMethod, String toMatch)
|
||||
throws IOException {
|
||||
if (httpMethod.getEntity() == null) {
|
||||
if (httpMethod.getPayload() == null) {
|
||||
assertNull(toMatch);
|
||||
} else {
|
||||
String entity = (httpMethod.getEntity() instanceof String) ? httpMethod.getEntity()
|
||||
.toString() : IOUtils.toString((InputStream) httpMethod.getEntity());
|
||||
assertEquals(entity, toMatch);
|
||||
String payload = IOUtils.toString(httpMethod.getPayload().getContent());
|
||||
assertEquals(payload, toMatch);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ public class StoreTweetsController extends HttpServlet {
|
|||
Blob to = map.newBlob();
|
||||
to.getMetadata().setContentType(MediaType.TEXT_PLAIN);
|
||||
to.getMetadata().setName(from.getId() + "");
|
||||
to.setData(from.getText());
|
||||
to.setPayload(from.getText());
|
||||
to.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME,
|
||||
from.getUser().getScreenName());
|
||||
return to;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue