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:
adrian.f.cole 2009-12-13 20:46:48 +00:00
parent 74be2180d3
commit 4a22f808d1
183 changed files with 1588 additions and 1527 deletions

View File

@ -64,7 +64,7 @@ public class ${clientName}AsyncClientTest extends RestClientTest<${clientName}As
assertRequestLineEquals(httpMethod, "TODO: insert expected request"); assertRequestLineEquals(httpMethod, "TODO: insert expected request");
assertHeadersEqual(httpMethod, ""); assertHeadersEqual(httpMethod, "");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseStatusesFromJsonResponse.class); assertResponseParserClassEquals(method, httpMethod, ParseStatusesFromJsonResponse.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);

View File

@ -36,7 +36,7 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType; 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.AtmosObject;
import org.jclouds.atmosonline.saas.domain.BoundedSortedSet; import org.jclouds.atmosonline.saas.domain.BoundedSortedSet;
import org.jclouds.atmosonline.saas.domain.DirectoryEntry; import org.jclouds.atmosonline.saas.domain.DirectoryEntry;
@ -117,7 +117,7 @@ public interface AtmosStorageAsyncClient {
@Consumes(MediaType.WILDCARD) @Consumes(MediaType.WILDCARD)
Future<URI> createFile( Future<URI> createFile(
@PathParam("parent") String parent, @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 * @see AtmosStorageClient#updateFile
@ -128,7 +128,7 @@ public interface AtmosStorageAsyncClient {
@Consumes(MediaType.WILDCARD) @Consumes(MediaType.WILDCARD)
Future<Void> updateFile( Future<Void> updateFile(
@PathParam("parent") String parent, @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 * @see AtmosStorageClient#readFile

View File

@ -33,21 +33,21 @@ import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder; import org.jclouds.rest.Binder;
public class BindAtmosObjectToEntityAndMetadataToHeaders implements Binder { public class BindAtmosObjectToPayloadAndMetadataToHeaders implements Binder {
private final BindUserMetadataToHeaders metaBinder; private final BindUserMetadataToHeaders metaBinder;
private final EncryptionService encryptionService; private final EncryptionService encryptionService;
@Inject @Inject
protected BindAtmosObjectToEntityAndMetadataToHeaders(BindUserMetadataToHeaders metaBinder, protected BindAtmosObjectToPayloadAndMetadataToHeaders(BindUserMetadataToHeaders metaBinder,
EncryptionService encryptionService) { EncryptionService encryptionService) {
this.metaBinder = metaBinder; this.metaBinder = metaBinder;
this.encryptionService = encryptionService; this.encryptionService = encryptionService;
} }
public void bindToRequest(HttpRequest request, Object entity) { public void bindToRequest(HttpRequest request, Object payload) {
AtmosObject object = (AtmosObject) entity; AtmosObject object = (AtmosObject) payload;
request.setEntity(checkNotNull(object.getData(), "object.getContent()")); request.setPayload(checkNotNull(object.getPayload(), "object.getPayload()"));
request.getHeaders().put( request.getHeaders().put(
HttpHeaders.CONTENT_TYPE, HttpHeaders.CONTENT_TYPE,
checkNotNull(object.getContentMetadata().getContentType(), checkNotNull(object.getContentMetadata().getContentType(),

View File

@ -35,8 +35,8 @@ import org.jclouds.rest.Binder;
public class BindUserMetadataToHeaders implements Binder { public class BindUserMetadataToHeaders implements Binder {
public void bindToRequest(HttpRequest request, Object entity) { public void bindToRequest(HttpRequest request, Object payload) {
UserMetadata md = (UserMetadata) checkNotNull(entity, "entity"); UserMetadata md = (UserMetadata) checkNotNull(payload, "payload");
if (md.getMetadata().size() > 0) { if (md.getMetadata().size() > 0) {
String header = join(md.getMetadata()); String header = join(md.getMetadata());
request.getHeaders().put("x-emc-meta", header); request.getHeaders().put("x-emc-meta", header);

View File

@ -45,7 +45,7 @@ public class BlobToObject implements Function<Blob, AtmosObject> {
public AtmosObject apply(Blob from) { public AtmosObject apply(Blob from) {
AtmosObject object = blobMd2Object.apply(from.getMetadata()); AtmosObject object = blobMd2Object.apply(from.getMetadata());
object.setData(from.getData()); object.setPayload(from.getPayload());
object.setAllHeaders(from.getAllHeaders()); object.setAllHeaders(from.getAllHeaders());
return object; return object;
} }

View File

@ -50,7 +50,7 @@ public class ObjectToBlob implements Function<AtmosObject, Blob> {
Blob blob = blobFactory.create(object2BlobMd.apply(from)); Blob blob = blobFactory.create(object2BlobMd.apply(from));
if (from.getContentMetadata().getContentLength() != null) if (from.getContentMetadata().getContentLength() != null)
blob.setContentLength(from.getContentMetadata().getContentLength()); blob.setContentLength(from.getContentMetadata().getContentLength());
blob.setData(from.getData()); blob.setPayload(from.getPayload());
blob.setAllHeaders(from.getAllHeaders()); blob.setAllHeaders(from.getAllHeaders());
return blob; return blob;
} }

View File

@ -31,9 +31,7 @@ import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
import org.jclouds.atmosonline.saas.domain.SystemMetadata; import org.jclouds.atmosonline.saas.domain.SystemMetadata;
import org.jclouds.atmosonline.saas.domain.UserMetadata; import org.jclouds.atmosonline.saas.domain.UserMetadata;
import org.jclouds.atmosonline.saas.domain.internal.AtmosObjectImpl; import org.jclouds.atmosonline.saas.domain.internal.AtmosObjectImpl;
import org.jclouds.blobstore.functions.CalculateSize; import org.jclouds.encryption.EncryptionService;
import org.jclouds.blobstore.functions.GenerateMD5;
import org.jclouds.blobstore.functions.GenerateMD5Result;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
@ -57,28 +55,24 @@ public class AtmosObjectModule extends AbstractModule {
private static class AtmosObjectFactory implements AtmosObject.Factory { private static class AtmosObjectFactory implements AtmosObject.Factory {
@Inject @Inject
GenerateMD5Result generateMD5Result; EncryptionService encryptionService;
@Inject
GenerateMD5 generateMD5;
@Inject
CalculateSize calculateSize;
@Inject @Inject
Provider<MutableContentMetadata> metadataProvider; Provider<MutableContentMetadata> metadataProvider;
public AtmosObject create(MutableContentMetadata contentMetadata) { public AtmosObject create(MutableContentMetadata contentMetadata) {
return new AtmosObjectImpl(generateMD5Result, generateMD5, calculateSize, return new AtmosObjectImpl(encryptionService, contentMetadata != null ? contentMetadata
contentMetadata != null ? contentMetadata : metadataProvider.get()); : metadataProvider.get());
} }
public AtmosObject create(SystemMetadata systemMetadata, UserMetadata userMetadata) { public AtmosObject create(SystemMetadata systemMetadata, UserMetadata userMetadata) {
return new AtmosObjectImpl(generateMD5Result, generateMD5, calculateSize, metadataProvider return new AtmosObjectImpl(encryptionService, metadataProvider.get(), systemMetadata,
.get(), systemMetadata, userMetadata); userMetadata);
} }
public AtmosObject create(MutableContentMetadata contentMetadata, public AtmosObject create(MutableContentMetadata contentMetadata,
SystemMetadata systemMetadata, UserMetadata userMetadata) { SystemMetadata systemMetadata, UserMetadata userMetadata) {
return new AtmosObjectImpl(generateMD5Result, generateMD5, calculateSize, contentMetadata, return new AtmosObjectImpl(encryptionService, contentMetadata, systemMetadata,
systemMetadata, userMetadata); userMetadata);
} }
} }

View File

@ -23,14 +23,14 @@
*/ */
package org.jclouds.atmosonline.saas.domain; package org.jclouds.atmosonline.saas.domain;
import java.io.IOException; import org.jclouds.http.PayloadEnclosing;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.inject.internal.Nullable; import com.google.inject.internal.Nullable;
/** /**
* Amazon Atmos is designed to store objects. Objects are stored in buckets and consist of a * 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. * {@link ObjectMetadata#getUserMetadata() metadata}, and an access control policy.
* *
* @author Adrian Cole * @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" * 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 { public interface Factory {
AtmosObject create(@Nullable MutableContentMetadata contentMetadata); 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(); MutableContentMetadata getContentMetadata();
/** /**

View File

@ -51,7 +51,7 @@ public class MutableContentMetadata {
* Chunking is only used when org.jclouds.http.GetOptions is called with options like tail, * Chunking is only used when org.jclouds.http.GetOptions is called with options like tail,
* range, or startAt. * 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 org.jclouds.http.HttpHeaders#CONTENT_LENGTH
* @see GetObjectOptions * @see GetObjectOptions
*/ */

View File

@ -24,18 +24,13 @@
package org.jclouds.atmosonline.saas.domain.internal; package org.jclouds.atmosonline.saas.domain.internal;
import static com.google.common.base.Preconditions.checkNotNull; 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.AtmosObject;
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata; import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
import org.jclouds.atmosonline.saas.domain.SystemMetadata; import org.jclouds.atmosonline.saas.domain.SystemMetadata;
import org.jclouds.atmosonline.saas.domain.UserMetadata; import org.jclouds.atmosonline.saas.domain.UserMetadata;
import org.jclouds.blobstore.domain.MD5InputStreamResult; import org.jclouds.encryption.EncryptionService;
import org.jclouds.blobstore.functions.CalculateSize; import org.jclouds.http.internal.BasePayloadEnclosingImpl;
import org.jclouds.blobstore.functions.GenerateMD5;
import org.jclouds.blobstore.functions.GenerateMD5Result;
import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
@ -45,67 +40,28 @@ import com.google.common.collect.Multimap;
* *
* @author Adrian Cole * @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 UserMetadata userMetadata;
private final GenerateMD5Result generateMD5Result;
private final GenerateMD5 generateMD5;
private final CalculateSize calculateSize;
private final MutableContentMetadata contentMetadata; private final MutableContentMetadata contentMetadata;
private final SystemMetadata systemMetadata; private final SystemMetadata systemMetadata;
private Object data;
private Multimap<String, String> allHeaders = LinkedHashMultimap.create(); private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
public AtmosObjectImpl(GenerateMD5Result generateMD5Result, GenerateMD5 generateMD5, public AtmosObjectImpl(EncryptionService encryptionService,
CalculateSize calculateSize, MutableContentMetadata contentMetadata) { MutableContentMetadata contentMetadata) {
this(generateMD5Result, generateMD5, calculateSize, contentMetadata, null, new UserMetadata()); this(encryptionService, contentMetadata, null, new UserMetadata());
} }
public AtmosObjectImpl(GenerateMD5Result generateMD5Result, GenerateMD5 generateMD5, public AtmosObjectImpl(EncryptionService encryptionService,
CalculateSize calculateSize, MutableContentMetadata contentMetadata, MutableContentMetadata contentMetadata, SystemMetadata systemMetadata,
SystemMetadata systemMetadata, UserMetadata userMetadata) { UserMetadata userMetadata) {
this.generateMD5Result = generateMD5Result; super(encryptionService);
this.generateMD5 = generateMD5;
this.calculateSize = calculateSize;
this.contentMetadata = contentMetadata; this.contentMetadata = contentMetadata;
this.systemMetadata = systemMetadata; this.systemMetadata = systemMetadata;
this.userMetadata = userMetadata; 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} * {@inheritDoc}
*/ */
@ -148,4 +104,19 @@ public class AtmosObjectImpl implements AtmosObject, Comparable<AtmosObject> {
return userMetadata; 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);
}
} }

View File

@ -67,7 +67,7 @@ public class ParseObjectFromHeadersAndHttpContent implements Function<HttpRespon
AtmosObject object = objectProvider.create(systemMetadataParser.apply(from), AtmosObject object = objectProvider.create(systemMetadataParser.apply(from),
userMetadataParser.apply(from)); userMetadataParser.apply(from));
addAllHeadersTo(from, object); addAllHeadersTo(from, object);
object.setData(from.getContent()); object.setPayload(from.getContent());
String contentLength = from.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH); String contentLength = from.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH);
if (contentLength != null) { if (contentLength != null) {
object.getContentMetadata().setContentLength(Long.parseLong(contentLength)); object.getContentMetadata().setContentLength(Long.parseLong(contentLength));

View File

@ -27,7 +27,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.UndeclaredThrowableException; import java.lang.reflect.UndeclaredThrowableException;
import java.net.URI; import java.net.URI;
import java.security.SecureRandom; import java.security.SecureRandom;
@ -47,6 +46,8 @@ import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest; import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
import org.jclouds.blobstore.strategy.ClearContainerStrategy; import org.jclouds.blobstore.strategy.ClearContainerStrategy;
import org.jclouds.http.HttpResponseException; 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.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
@ -225,7 +226,7 @@ public class AtmosStorageClientLiveTest {
// Test PUT with string data, ETag hash, and a piece of metadata // Test PUT with string data, ETag hash, and a piece of metadata
AtmosObject object = connection.newObject(); AtmosObject object = connection.newObject();
object.getContentMetadata().setName(name); object.getContentMetadata().setName(name);
object.setData(data); object.setPayload(Payloads.newPayload(data));
object.getContentMetadata().setContentLength(16); object.getContentMetadata().setContentLength(16);
object.generateMD5(); object.generateMD5();
object.getContentMetadata().setContentType("text/plain"); object.getContentMetadata().setContentType("text/plain");
@ -273,7 +274,7 @@ public class AtmosStorageClientLiveTest {
String metadataValue) throws InterruptedException, ExecutionException, String metadataValue) throws InterruptedException, ExecutionException,
TimeoutException, IOException { TimeoutException, IOException {
AtmosObject getBlob = connection.headFile(path); AtmosObject getBlob = connection.headFile(path);
assertEquals(IOUtils.toString((InputStream) getBlob.getData()), ""); assertEquals(IOUtils.toString(getBlob.getContent()), "");
verifyMetadata(metadataValue, getBlob); verifyMetadata(metadataValue, getBlob);
} }
@ -281,8 +282,7 @@ public class AtmosStorageClientLiveTest {
String metadataValue) throws InterruptedException, ExecutionException, String metadataValue) throws InterruptedException, ExecutionException,
TimeoutException, IOException { TimeoutException, IOException {
AtmosObject getBlob = connection.readFile(path); AtmosObject getBlob = connection.readFile(path);
assertEquals(getBlob.getData() instanceof String ? getBlob.getData() : IOUtils assertEquals(IOUtils.toString(getBlob.getContent()), compare);
.toString((InputStream) getBlob.getData()), compare);
verifyMetadata(metadataValue, getBlob); verifyMetadata(metadataValue, getBlob);
} }
@ -326,14 +326,14 @@ public class AtmosStorageClientLiveTest {
try { try {
connection.createFile(privateDirectory, object); connection.createFile(privateDirectory, object);
System.err.printf("%s %s; %dms%n", "created", System.err.printf("%s %s; %dms%n", "created",
object.getData() instanceof InputStream ? "stream" : "string", System object.getPayload() instanceof InputStreamPayload ? "stream" : "string", System
.currentTimeMillis() .currentTimeMillis()
- time); - time);
} catch (Exception e) { } catch (Exception e) {
String message = (e.getCause().getCause() != null) ? e.getCause().getCause().getMessage() String message = (e.getCause().getCause() != null) ? e.getCause().getCause().getMessage()
: e.getCause().getMessage(); : e.getCause().getMessage();
System.err.printf("failure %s %s; %dms: [%s]%n", "creating", 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() .currentTimeMillis()
- time, message); - time, message);
throw e; throw e;
@ -386,7 +386,7 @@ public class AtmosStorageClientLiveTest {
} }
if (failures > 0) if (failures > 0)
System.err.printf("%d failures create/replacing %s%n", failures, 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) private void checkSystemMetadataAndPutIfPresentReplaceStrategy(AtmosObject object)
@ -404,14 +404,14 @@ public class AtmosStorageClientLiveTest {
else else
connection.createFile(privateDirectory, object); connection.createFile(privateDirectory, object);
System.err.printf("%s %s; %dms%n", update ? "updated" : "created", 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() .currentTimeMillis()
- time); - time);
} catch (Exception e) { } catch (Exception e) {
String message = (e.getCause().getCause() != null) ? e.getCause().getCause().getMessage() String message = (e.getCause().getCause() != null) ? e.getCause().getCause().getMessage()
: e.getCause().getMessage(); : e.getCause().getMessage();
System.err.printf("failure %s %s; %dms: [%s]%n", update ? "updating" : "creating", object 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() .currentTimeMillis()
- time, message); - time, message);
throw e; throw e;

View File

@ -82,7 +82,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
assertRequestLineEquals(httpMethod, assertRequestLineEquals(httpMethod,
"GET http://accesspoint.emccis.com/rest/namespace HTTP/1.1"); "GET http://accesspoint.emccis.com/rest/namespace HTTP/1.1");
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": text/xml\n"); assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": text/xml\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, assertResponseParserClassEquals(method, httpMethod,
ParseDirectoryListFromContentAndHeaders.class); ParseDirectoryListFromContentAndHeaders.class);
@ -101,7 +101,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
assertRequestLineEquals(httpMethod, assertRequestLineEquals(httpMethod,
"GET http://accesspoint.emccis.com/rest/namespace/directory/ HTTP/1.1"); "GET http://accesspoint.emccis.com/rest/namespace/directory/ HTTP/1.1");
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": text/xml\n"); assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": text/xml\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, assertResponseParserClassEquals(method, httpMethod,
ParseDirectoryListFromContentAndHeaders.class); ParseDirectoryListFromContentAndHeaders.class);
@ -122,7 +122,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
"GET http://accesspoint.emccis.com/rest/namespace HTTP/1.1"); "GET http://accesspoint.emccis.com/rest/namespace HTTP/1.1");
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT
+ ": text/xml\nx-emc-limit: 1\nx-emc-token: asda\n"); + ": text/xml\nx-emc-limit: 1\nx-emc-token: asda\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, assertResponseParserClassEquals(method, httpMethod,
ParseDirectoryListFromContentAndHeaders.class); ParseDirectoryListFromContentAndHeaders.class);
@ -143,7 +143,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
"GET http://accesspoint.emccis.com/rest/namespace/directory/ HTTP/1.1"); "GET http://accesspoint.emccis.com/rest/namespace/directory/ HTTP/1.1");
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT
+ ": text/xml\nx-emc-limit: 1\nx-emc-token: asda\n"); + ": text/xml\nx-emc-limit: 1\nx-emc-token: asda\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, assertResponseParserClassEquals(method, httpMethod,
ParseDirectoryListFromContentAndHeaders.class); ParseDirectoryListFromContentAndHeaders.class);
@ -161,7 +161,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
assertRequestLineEquals(httpMethod, assertRequestLineEquals(httpMethod,
"POST http://accesspoint.emccis.com/rest/namespace/dir/ HTTP/1.1"); "POST http://accesspoint.emccis.com/rest/namespace/dir/ HTTP/1.1");
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": */*\n"); assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": */*\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, assertResponseParserClassEquals(method, httpMethod,
ParseURIFromListOrLocationHeaderIf20x.class); ParseURIFromListOrLocationHeaderIf20x.class);
@ -181,7 +181,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
"POST http://accesspoint.emccis.com/rest/namespace/dir/hello HTTP/1.1"); "POST http://accesspoint.emccis.com/rest/namespace/dir/hello HTTP/1.1");
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT
+ ": */*\nContent-Length: 5\nContent-Type: text/plain\n"); + ": */*\nContent-Length: 5\nContent-Type: text/plain\n");
assertEntityEquals(httpMethod, "hello"); assertPayloadEquals(httpMethod, "hello");
assertResponseParserClassEquals(method, httpMethod, assertResponseParserClassEquals(method, httpMethod,
ParseURIFromListOrLocationHeaderIf20x.class); ParseURIFromListOrLocationHeaderIf20x.class);
@ -201,7 +201,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
"PUT http://accesspoint.emccis.com/rest/namespace/dir/hello HTTP/1.1"); "PUT http://accesspoint.emccis.com/rest/namespace/dir/hello HTTP/1.1");
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT
+ ": */*\nContent-Length: 5\nContent-Type: text/plain\n"); + ": */*\nContent-Length: 5\nContent-Type: text/plain\n");
assertEntityEquals(httpMethod, "hello"); assertPayloadEquals(httpMethod, "hello");
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
@ -219,7 +219,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
assertRequestLineEquals(httpMethod, assertRequestLineEquals(httpMethod,
"GET http://accesspoint.emccis.com/rest/namespace/dir/file HTTP/1.1"); "GET http://accesspoint.emccis.com/rest/namespace/dir/file HTTP/1.1");
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": */*\n"); assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": */*\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, assertResponseParserClassEquals(method, httpMethod,
ParseObjectFromHeadersAndHttpContent.class); ParseObjectFromHeadersAndHttpContent.class);
@ -237,7 +237,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
assertRequestLineEquals(httpMethod, assertRequestLineEquals(httpMethod,
"HEAD http://accesspoint.emccis.com/rest/namespace/dir/file HTTP/1.1"); "HEAD http://accesspoint.emccis.com/rest/namespace/dir/file HTTP/1.1");
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": */*\n"); assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": */*\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseSystemMetadataFromHeaders.class); assertResponseParserClassEquals(method, httpMethod, ParseSystemMetadataFromHeaders.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
@ -254,7 +254,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
assertRequestLineEquals(httpMethod, assertRequestLineEquals(httpMethod,
"DELETE http://accesspoint.emccis.com/rest/namespace/dir/file HTTP/1.1"); "DELETE http://accesspoint.emccis.com/rest/namespace/dir/file HTTP/1.1");
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": */*\n"); assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": */*\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);

View File

@ -103,13 +103,13 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
checkNotNull(request.getFirstHeaderOrNull(HttpHeaders.HOST), checkNotNull(request.getFirstHeaderOrNull(HttpHeaders.HOST),
"request is not ready to sign; host not present"); "request is not ready to sign; host not present");
Multimap<String, String> decodedParams = RestAnnotationProcessor.parseQueryToMap(request Multimap<String, String> decodedParams = RestAnnotationProcessor.parseQueryToMap(request
.getEntity().toString()); .getPayload().getRawContent().toString());
addSigningParams(decodedParams); addSigningParams(decodedParams);
validateParams(decodedParams); validateParams(decodedParams);
String stringToSign = createStringToSign(request, decodedParams); String stringToSign = createStringToSign(request, decodedParams);
String signature = signString(stringToSign); String signature = signString(stringToSign);
addSignature(decodedParams, signature); addSignature(decodedParams, signature);
setEntity(request, decodedParams); setPayload(request, decodedParams);
HttpUtils.logRequest(signatureLog, request, "<<"); HttpUtils.logRequest(signatureLog, request, "<<");
} }
@ -128,8 +128,8 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
return parts; return parts;
} }
void setEntity(GeneratedHttpRequest<?> request, Multimap<String, String> decodedParams) { void setPayload(GeneratedHttpRequest<?> request, Multimap<String, String> decodedParams) {
request.setEntity(RestAnnotationProcessor.makeQueryLine(decodedParams, request.setPayload(RestAnnotationProcessor.makeQueryLine(decodedParams,
new Comparator<Map.Entry<String, String>>() { new Comparator<Map.Entry<String, String>>() {
public int compare(Entry<String, String> o1, Entry<String, String> o2) { public int compare(Entry<String, String> o1, Entry<String, String> o2) {
if (o1.getKey().startsWith("Action") if (o1.getKey().startsWith("Action")
@ -209,8 +209,8 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
} }
public String createStringToSign(HttpRequest input) { public String createStringToSign(HttpRequest input) {
return createStringToSign(input, RestAnnotationProcessor.parseQueryToMap(input.getEntity() return createStringToSign(input, RestAnnotationProcessor.parseQueryToMap(input.getPayload()
.toString())); .getRawContent().toString()));
} }
} }

View File

@ -36,8 +36,8 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import org.jclouds.aws.s3.binders.BindACLToXMLEntity; import org.jclouds.aws.s3.binders.BindACLToXMLPayload;
import org.jclouds.aws.s3.binders.BindS3ObjectToEntity; import org.jclouds.aws.s3.binders.BindS3ObjectToPayload;
import org.jclouds.aws.s3.domain.AccessControlList; import org.jclouds.aws.s3.domain.AccessControlList;
import org.jclouds.aws.s3.domain.BucketMetadata; import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ListBucketResponse; import org.jclouds.aws.s3.domain.ListBucketResponse;
@ -139,7 +139,7 @@ public interface S3AsyncClient {
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
Future<String> putObject( Future<String> putObject(
@HostPrefixParam String bucketName, @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); PutObjectOptions... options);
/** /**
@ -214,7 +214,7 @@ public interface S3AsyncClient {
@Path("/") @Path("/")
@QueryParams(keys = "acl") @QueryParams(keys = "acl")
Future<Boolean> putBucketACL(@HostPrefixParam String bucketName, Future<Boolean> putBucketACL(@HostPrefixParam String bucketName,
@BinderParam(BindACLToXMLEntity.class) AccessControlList acl); @BinderParam(BindACLToXMLPayload.class) AccessControlList acl);
/** /**
* @see S3Client#getObjectACL * @see S3Client#getObjectACL
@ -234,6 +234,6 @@ public interface S3AsyncClient {
@QueryParams(keys = "acl") @QueryParams(keys = "acl")
@Path("{key}") @Path("{key}")
Future<Boolean> putObjectACL(@HostPrefixParam String bucketName, @PathParam("key") String key, Future<Boolean> putObjectACL(@HostPrefixParam String bucketName, @PathParam("key") String key,
@BinderParam(BindACLToXMLEntity.class) AccessControlList acl); @BinderParam(BindACLToXMLPayload.class) AccessControlList acl);
} }

View File

@ -42,17 +42,17 @@ import org.jclouds.util.Utils;
import com.jamesmurty.utils.XMLBuilder; import com.jamesmurty.utils.XMLBuilder;
public class BindACLToXMLEntity implements Binder { public class BindACLToXMLPayload implements Binder {
public void bindToRequest(HttpRequest request, Object entity) { public void bindToRequest(HttpRequest request, Object payload) {
AccessControlList from = (AccessControlList) entity; AccessControlList from = (AccessControlList) payload;
Properties outputProperties = new Properties(); Properties outputProperties = new Properties();
outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes"); outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
try { 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_TYPE, MediaType.TEXT_XML);
request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, stringEntity.getBytes().length + ""); request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, stringPayload.getBytes().length + "");
request.setEntity(stringEntity); request.setPayload(stringPayload);
} catch (Exception e) { } catch (Exception e) {
Utils.rethrowIfRuntime(e); Utils.rethrowIfRuntime(e);
throw new RuntimeException("error transforming acl: " + from, e); throw new RuntimeException("error transforming acl: " + from, e);

View File

@ -31,23 +31,23 @@ import javax.ws.rs.core.HttpHeaders;
import org.jclouds.aws.s3.blobstore.functions.ObjectToBlob; import org.jclouds.aws.s3.blobstore.functions.ObjectToBlob;
import org.jclouds.aws.s3.domain.S3Object; 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.http.HttpRequest;
import org.jclouds.rest.Binder; import org.jclouds.rest.Binder;
public class BindS3ObjectToEntity implements Binder { public class BindS3ObjectToPayload implements Binder {
private final BindBlobToEntityAndUserMetadataToHeadersWithPrefix blobBinder; private final BindBlobToPayloadAndUserMetadataToHeadersWithPrefix blobBinder;
private final ObjectToBlob object2Blob; private final ObjectToBlob object2Blob;
@Inject @Inject
public BindS3ObjectToEntity(ObjectToBlob object2Blob, public BindS3ObjectToPayload(ObjectToBlob object2Blob,
BindBlobToEntityAndUserMetadataToHeadersWithPrefix blobBinder) { BindBlobToPayloadAndUserMetadataToHeadersWithPrefix blobBinder) {
this.blobBinder = blobBinder; this.blobBinder = blobBinder;
this.object2Blob = object2Blob; this.object2Blob = object2Blob;
} }
public void bindToRequest(HttpRequest request, Object entity) { public void bindToRequest(HttpRequest request, Object payload) {
S3Object s3Object = (S3Object) entity; S3Object s3Object = (S3Object) payload;
checkNotNull(s3Object.getContentLength(), "contentLength"); checkNotNull(s3Object.getContentLength(), "contentLength");
checkArgument(s3Object.getContentLength() <= 5 * 1024 * 1024 * 1024, checkArgument(s3Object.getContentLength() <= 5 * 1024 * 1024 * 1024,
"maximum size for put object is 5GB"); "maximum size for put object is 5GB");

View File

@ -49,7 +49,7 @@ public class BlobToObject implements Function<Blob, S3Object> {
S3Object object = objectProvider.create(blob2ObjectMd.apply(from.getMetadata())); S3Object object = objectProvider.create(blob2ObjectMd.apply(from.getMetadata()));
if (from.getContentLength() != null) if (from.getContentLength() != null)
object.setContentLength(from.getContentLength()); object.setContentLength(from.getContentLength());
object.setData(from.getData()); object.setPayload(from.getPayload());
object.setAllHeaders(from.getAllHeaders()); object.setAllHeaders(from.getAllHeaders());
return object; return object;
} }

View File

@ -50,7 +50,7 @@ public class ObjectToBlob implements Function<S3Object, Blob> {
Blob blob = blobFactory.create(object2BlobMd.apply(from.getMetadata())); Blob blob = blobFactory.create(object2BlobMd.apply(from.getMetadata()));
if (from.getContentLength() != null) if (from.getContentLength() != null)
blob.setContentLength(from.getContentLength()); blob.setContentLength(from.getContentLength());
blob.setData(from.getData()); blob.setPayload(from.getPayload());
blob.setAllHeaders(from.getAllHeaders()); blob.setAllHeaders(from.getAllHeaders());
return blob; return blob;
} }

View File

@ -29,9 +29,7 @@ import javax.inject.Provider;
import org.jclouds.aws.s3.domain.MutableObjectMetadata; import org.jclouds.aws.s3.domain.MutableObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.internal.S3ObjectImpl; import org.jclouds.aws.s3.domain.internal.S3ObjectImpl;
import org.jclouds.blobstore.functions.CalculateSize; import org.jclouds.encryption.EncryptionService;
import org.jclouds.blobstore.functions.GenerateMD5;
import org.jclouds.blobstore.functions.GenerateMD5Result;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
@ -44,7 +42,6 @@ import com.google.inject.Scopes;
*/ */
public class S3ObjectModule extends AbstractModule { public class S3ObjectModule extends AbstractModule {
/** /**
* explicit factories are created here as it has been shown that Assisted Inject is extremely * 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 * 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 { private static class S3ObjectFactory implements S3Object.Factory {
@Inject @Inject
GenerateMD5Result generateMD5Result; EncryptionService encryptionService;
@Inject
GenerateMD5 generateMD5;
@Inject
CalculateSize calculateSize;
@Inject @Inject
Provider<MutableObjectMetadata> metadataProvider; Provider<MutableObjectMetadata> metadataProvider;
public S3Object create(MutableObjectMetadata metadata) { public S3Object create(MutableObjectMetadata metadata) {
return new S3ObjectImpl(generateMD5Result, generateMD5, calculateSize, return new S3ObjectImpl(encryptionService, metadata != null ? metadata : metadataProvider
metadata != null ? metadata : metadataProvider.get()); .get());
} }
} }

View File

@ -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. * 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 * 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 * 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 * @author James Murty

View File

@ -23,66 +23,25 @@
*/ */
package org.jclouds.aws.s3.domain; package org.jclouds.aws.s3.domain;
import java.io.IOException; import org.jclouds.http.PayloadEnclosing;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.inject.internal.Nullable; import com.google.inject.internal.Nullable;
/** /**
* Amazon S3 is designed to store objects. Objects are stored in buckets and consist of a * 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. * {@link ObjectMetadata#getUserMetadata() metadata}, and an access control policy.
* *
* @author Adrian Cole * @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html" * @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 { public interface Factory {
S3Object create(@Nullable MutableObjectMetadata metadata); 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. * @return System and User metadata relevant to this object.
*/ */

View File

@ -24,19 +24,14 @@
package org.jclouds.aws.s3.domain.internal; package org.jclouds.aws.s3.domain.internal;
import static com.google.common.base.Preconditions.checkNotNull; 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 javax.inject.Inject;
import org.jclouds.aws.s3.domain.AccessControlList; import org.jclouds.aws.s3.domain.AccessControlList;
import org.jclouds.aws.s3.domain.MutableObjectMetadata; import org.jclouds.aws.s3.domain.MutableObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.domain.MD5InputStreamResult; import org.jclouds.encryption.EncryptionService;
import org.jclouds.blobstore.functions.CalculateSize; import org.jclouds.http.internal.BasePayloadEnclosingImpl;
import org.jclouds.blobstore.functions.GenerateMD5;
import org.jclouds.blobstore.functions.GenerateMD5Result;
import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
@ -46,25 +41,22 @@ import com.google.common.collect.Multimap;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class S3ObjectImpl implements S3Object, Comparable<S3Object> { public class S3ObjectImpl extends BasePayloadEnclosingImpl implements S3Object,
private final GenerateMD5Result generateMD5Result; Comparable<S3Object> {
private final GenerateMD5 generateMD5;
private final CalculateSize calculateSize;
private final MutableObjectMetadata metadata; private final MutableObjectMetadata metadata;
private Object data;
private Multimap<String, String> allHeaders = LinkedHashMultimap.create(); private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
private Long contentLength; private AccessControlList accessControlList;
@Inject @Inject
public S3ObjectImpl(GenerateMD5Result generateMD5Result, GenerateMD5 generateMD5, public S3ObjectImpl(EncryptionService encryptionService, MutableObjectMetadata metadata) {
CalculateSize calculateSize, MutableObjectMetadata metadata) { super(encryptionService);
this.generateMD5Result = generateMD5Result;
this.generateMD5 = generateMD5;
this.calculateSize = calculateSize;
this.metadata = metadata; this.metadata = metadata;
} }
private AccessControlList accessControlList; @Override
protected void setContentMD5(byte[] md5) {
getMetadata().setContentMD5(md5);
}
/** /**
* {@inheritDoc} * {@inheritDoc}
@ -80,54 +72,6 @@ public class S3ObjectImpl implements S3Object, Comparable<S3Object> {
return this.accessControlList; 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} * {@inheritDoc}
*/ */
@ -165,7 +109,7 @@ public class S3ObjectImpl implements S3Object, Comparable<S3Object> {
result = prime * result + ((accessControlList == null) ? 0 : accessControlList.hashCode()); result = prime * result + ((accessControlList == null) ? 0 : accessControlList.hashCode());
result = prime * result + ((allHeaders == null) ? 0 : allHeaders.hashCode()); result = prime * result + ((allHeaders == null) ? 0 : allHeaders.hashCode());
result = prime * result + ((contentLength == null) ? 0 : contentLength.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()); result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
return result; return result;
} }
@ -194,10 +138,10 @@ public class S3ObjectImpl implements S3Object, Comparable<S3Object> {
return false; return false;
} else if (!contentLength.equals(other.contentLength)) } else if (!contentLength.equals(other.contentLength))
return false; return false;
if (data == null) { if (payload == null) {
if (other.data != null) if (other.payload != null)
return false; return false;
} else if (!data.equals(other.data)) } else if (!payload.equals(other.payload))
return false; return false;
if (metadata == null) { if (metadata == null) {
if (other.metadata != null) if (other.metadata != null)

View File

@ -66,7 +66,7 @@ public class ParseObjectFromHeadersAndHttpContent implements Function<HttpRespon
public S3Object apply(HttpResponse from) { public S3Object apply(HttpResponse from) {
S3Object object = objectProvider.create(metadataParser.apply(from)); S3Object object = objectProvider.create(metadataParser.apply(from));
addAllHeadersTo(from, object); addAllHeadersTo(from, object);
object.setData(from.getContent()); object.setPayload(from.getContent());
attemptToParseSizeAndRangeFromHeaders(from, object); attemptToParseSizeAndRangeFromHeaders(from, object);
return object; return object;
} }

View File

@ -145,7 +145,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
/** /**
* For use in the request header: x-amz-copy-source-if-match * For use in the request header: x-amz-copy-source-if-match
* <p/> * <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). * (precondition failed).
* <p/> * <p/>
* This header can be used with x-amz-copy-source-if-unmodified-since, but cannot be used with * 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 * For use in the request header: x-amz-copy-source-if-none-match
* <p/> * <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). * returns a 412 (failed condition).
* <p/> * <p/>
* This header can be used with x-amz-copy-source-if-modified-since, but cannot be used with * 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)} * {@link #ifSourceModifiedSince(Date)}
* *
* @param eTag * @param eTag
* hash representing the entity * hash representing the payload
*/ */
public CopyObjectOptions ifSourceETagMatches(String eTag) throws UnsupportedEncodingException { public CopyObjectOptions ifSourceETagMatches(String eTag) throws UnsupportedEncodingException {
checkState(getIfNoneMatch() == null, checkState(getIfNoneMatch() == null,
@ -240,7 +240,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
* {@link #ifSourceUnmodifiedSince(Date)} * {@link #ifSourceUnmodifiedSince(Date)}
* *
* @param eTag * @param eTag
* hash representing the entity * hash representing the payload
* @throws UnsupportedEncodingException * @throws UnsupportedEncodingException
* if there was a problem converting this into an S3 eTag string * if there was a problem converting this into an S3 eTag string
*/ */

View File

@ -61,7 +61,7 @@ public class PutBucketOptions extends BaseHttpRequestOptions {
*/ */
public PutBucketOptions createIn(LocationConstraint constraint) { public PutBucketOptions createIn(LocationConstraint constraint) {
this.constraint = checkNotNull(constraint, "constraint"); this.constraint = checkNotNull(constraint, "constraint");
this.entity = String this.payload = String
.format( .format(
"<CreateBucketConfiguration><LocationConstraint>%1$s</LocationConstraint></CreateBucketConfiguration>", "<CreateBucketConfiguration><LocationConstraint>%1$s</LocationConstraint></CreateBucketConfiguration>",
constraint.toString()); constraint.toString());

View File

@ -83,9 +83,9 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 40\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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); filter.filter(httpMethod);
assertEntityEquals( assertPayloadEquals(
httpMethod, 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"); "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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 107\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "Content-Length: 107\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
assertEntityEquals( assertPayloadEquals(
httpMethod, httpMethod,
"Version=2009-08-15&Action=DescribeImages&ExecutableBy=me&Owner.1=fred&Owner.2=nancy&ImageId.1=1&ImageId.2=2"); "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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 93\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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"); "Version=2009-08-15&Action=DescribeImageAttribute&ImageId=imageId&Attribute=blockDeviceMapping");
filter.filter(httpMethod); filter.filter(httpMethod);
assertEntityEquals( assertPayloadEquals(
httpMethod, 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"); "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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 43\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, DescribeInstancesResponseHandler.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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 43\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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"); "Version=2009-08-15&Action=DescribeInstances&InstanceId.1=1&InstanceId.2=2");
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); 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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 59\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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"); "Version=2009-08-15&Action=TerminateInstances&InstanceId.0=1&InstanceId.1=2");
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); 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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 76\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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"); "Version=2009-08-15&Action=RunInstances&ImageId=ami-voo&MaxCount=1&MinCount=1");
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); 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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 118\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "Content-Length: 118\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
assertEntityEquals( assertPayloadEquals(
httpMethod, httpMethod,
"Version=2009-08-15&Action=RunInstances&ImageId=ami-voo&MaxCount=5&MinCount=1&KernelId=kernelId&Monitoring.Enabled=true"); "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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 53\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, KeyPairResponseHandler.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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 64\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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"); "Version=2009-08-15&Action=DisassociateAddress&PublicIp=127.0.0.1");
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); 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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 75\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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"); "Version=2009-08-15&Action=AssociateAddress&PublicIp=127.0.0.1&InstanceId=me");
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); 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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 59\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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); assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
@ -315,7 +315,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 43\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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"); "Version=2009-08-15&Action=DescribeAddresses&PublicIp.1=127.0.0.1");
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); 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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 41\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, AllocateAddressResponseHandler.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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 53\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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); assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
@ -365,7 +365,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 42\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, DescribeKeyPairsResponseHandler.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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 42\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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"); "Version=2009-08-15&Action=DescribeKeyPairs&KeyName.1=1&KeyName.2=2");
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); 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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 60\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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); assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
@ -419,7 +419,7 @@ public class EC2ClientTest extends RestClientTest<EC2AsyncClient> {
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 89\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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"); "Version=2009-08-15&Action=CreateSecurityGroup&GroupName=name&GroupDescription=description");
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); 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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 48\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, DescribeSecurityGroupsResponseHandler.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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 48\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "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"); "Version=2009-08-15&Action=DescribeSecurityGroups&GroupName.1=1&GroupName.2=2");
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); 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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 71\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "Content-Length: 71\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
assertEntityEquals( assertPayloadEquals(
httpMethod, httpMethod,
"Version=2009-08-15&Action=AuthorizeSecurityGroupIngress&GroupName=group&SourceSecurityGroupOwnerId=sourceUser&SourceSecurityGroupName=sourceGroup"); "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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 131\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "Content-Length: 131\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
assertEntityEquals( assertPayloadEquals(
httpMethod, httpMethod,
"Version=2009-08-15&Action=AuthorizeSecurityGroupIngress&GroupName=group&FromPort=6000&IpProtocol=tcp&ToPort=7000&CidrIp=0.0.0.0%2F0"); "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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 68\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "Content-Length: 68\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
assertEntityEquals( assertPayloadEquals(
httpMethod, httpMethod,
"Version=2009-08-15&Action=RevokeSecurityGroupIngress&GroupName=group&SourceSecurityGroupOwnerId=sourceUser&SourceSecurityGroupName=sourceGroup"); "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"); assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 128\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n"); "Content-Length: 128\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
assertEntityEquals( assertPayloadEquals(
httpMethod, httpMethod,
"Version=2009-08-15&Action=RevokeSecurityGroupIngress&GroupName=group&FromPort=6000&IpProtocol=tcp&ToPort=7000&CidrIp=0.0.0.0%2F0"); "Version=2009-08-15&Action=RevokeSecurityGroupIngress&GroupName=group&FromPort=6000&IpProtocol=tcp&ToPort=7000&CidrIp=0.0.0.0%2F0");

View File

@ -43,7 +43,6 @@ import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URL; import java.net.URL;
import java.util.Date; import java.util.Date;
@ -104,7 +103,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
String key = "hello"; String key = "hello";
S3Object object = context.getApi().newS3Object(); S3Object object = context.getApi().newS3Object();
object.getMetadata().setKey(key); object.getMetadata().setKey(key);
object.setData(TEST_STRING); object.setPayload(TEST_STRING);
context.getApi().putObject(containerName, object, context.getApi().putObject(containerName, object,
withAcl(CannedAccessPolicy.PUBLIC_READ)); withAcl(CannedAccessPolicy.PUBLIC_READ));
@ -149,7 +148,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
try { try {
S3Object object = context.getApi().newS3Object(); S3Object object = context.getApi().newS3Object();
object.getMetadata().setKey(publicReadWriteObjectKey); object.getMetadata().setKey(publicReadWriteObjectKey);
object.setData(""); object.setPayload("");
// Public Read-Write object // Public Read-Write object
context.getApi().putObject(containerName, object, context.getApi().putObject(containerName, object,
new PutObjectOptions().withAcl(CannedAccessPolicy.PUBLIC_READ_WRITE)); new PutObjectOptions().withAcl(CannedAccessPolicy.PUBLIC_READ_WRITE));
@ -252,7 +251,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
try { try {
S3Object object = context.getApi().newS3Object(); S3Object object = context.getApi().newS3Object();
object.getMetadata().setKey(publicReadObjectKey); object.getMetadata().setKey(publicReadObjectKey);
object.setData(""); object.setPayload("");
context.getApi().putObject(containerName, object, context.getApi().putObject(containerName, object,
new PutObjectOptions().withAcl(CannedAccessPolicy.PUBLIC_READ)); new PutObjectOptions().withAcl(CannedAccessPolicy.PUBLIC_READ));
@ -284,7 +283,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
S3Object sourceObject = context.getApi().newS3Object(); S3Object sourceObject = context.getApi().newS3Object();
sourceObject.getMetadata().setKey(key); sourceObject.getMetadata().setKey(key);
sourceObject.getMetadata().setContentType("text/xml"); sourceObject.getMetadata().setContentType("text/xml");
sourceObject.setData(TEST_STRING); sourceObject.setPayload(TEST_STRING);
return context.getApi().putObject(sourceContainer, sourceObject); return context.getApi().putObject(sourceContainer, sourceObject);
} }
@ -293,7 +292,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
assertConsistencyAwareContainerSize(sourceContainer, 1); assertConsistencyAwareContainerSize(sourceContainer, 1);
S3Object newObject = context.getApi().getObject(sourceContainer, key); S3Object newObject = context.getApi().getObject(sourceContainer, key);
assert newObject != null; assert newObject != null;
assertEquals(Utils.toStringAndClose((InputStream) newObject.getData()), TEST_STRING); assertEquals(Utils.toStringAndClose(newObject.getContent()), TEST_STRING);
return newObject; return newObject;
} }
@ -302,7 +301,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
S3Object object = context.getApi().newS3Object(); S3Object object = context.getApi().newS3Object();
object.getMetadata().setKey(key); object.getMetadata().setKey(key);
object.setData(TEST_STRING); object.setPayload(TEST_STRING);
object.getMetadata().setCacheControl("no-cache"); object.getMetadata().setCacheControl("no-cache");
object.getMetadata().setContentDisposition("attachment; filename=hello.txt"); object.getMetadata().setContentDisposition("attachment; filename=hello.txt");
String containerName = getContainerName(); String containerName = getContainerName();
@ -325,7 +324,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
S3Object object = context.getApi().newS3Object(); S3Object object = context.getApi().newS3Object();
object.getMetadata().setKey(key); object.getMetadata().setKey(key);
object.setData(TEST_STRING); object.setPayload(TEST_STRING);
object.getMetadata().setContentEncoding("x-compress"); object.getMetadata().setContentEncoding("x-compress");
String containerName = getContainerName(); String containerName = getContainerName();
try { try {
@ -619,7 +618,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
for (char letter = 'a'; letter <= 'z'; letter++) { for (char letter = 'a'; letter <= 'z'; letter++) {
S3Object blob = context.getApi().newS3Object(); S3Object blob = context.getApi().newS3Object();
blob.getMetadata().setKey(letter + ""); blob.getMetadata().setKey(letter + "");
blob.setData(letter + "content"); blob.setPayload(letter + "content");
context.getApi().putObject(containerName, blob); context.getApi().putObject(containerName, blob);
} }
} }
@ -694,7 +693,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
for (int i = 0; i < 15; i++) { for (int i = 0; i < 15; i++) {
S3Object blob = context.getApi().newS3Object(); S3Object blob = context.getApi().newS3Object();
blob.getMetadata().setKey(i + ""); blob.getMetadata().setKey(i + "");
blob.setData(i + "content"); blob.setPayload(i + "content");
context.getApi().putObject(containerName, blob); context.getApi().putObject(containerName, blob);
} }
} }
@ -703,7 +702,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3AsyncClient
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
S3Object blob = context.getApi().newS3Object(); S3Object blob = context.getApi().newS3Object();
blob.getMetadata().setKey(prefix + "/" + i); blob.getMetadata().setKey(prefix + "/" + i);
blob.setData(i + "content"); blob.setPayload(i + "content");
context.getApi().putObject(containerName, blob); context.getApi().putObject(containerName, blob);
} }
} }

View File

@ -91,7 +91,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
assertRequestLineEquals(httpMethod, "GET http://bucket.stub:8080/ HTTP/1.1"); assertRequestLineEquals(httpMethod, "GET http://bucket.stub:8080/ HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n"); assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, ListBucketHandler.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"); assertRequestLineEquals(httpMethod, "HEAD http://bucket.stub:8080/?max-keys=0 HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n"); assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class); assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
@ -127,7 +127,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
"PUT http://destinationBucket.stub:8080/destinationObject HTTP/1.1"); "PUT http://destinationBucket.stub:8080/destinationObject HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 0\nHost: destinationBucket.stub\nx-amz-copy-source: /sourceBucket/sourceObject\n"); "Content-Length: 0\nHost: destinationBucket.stub\nx-amz-copy-source: /sourceBucket/sourceObject\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, CopyObjectHandler.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"); assertRequestLineEquals(httpMethod, "DELETE http://bucket.stub:8080/ HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n"); assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class); assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
@ -159,7 +159,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
assertRequestLineEquals(httpMethod, "DELETE http://bucket.stub:8080/object HTTP/1.1"); assertRequestLineEquals(httpMethod, "DELETE http://bucket.stub:8080/object HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n"); assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class); assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
@ -175,7 +175,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
assertRequestLineEquals(httpMethod, "GET http://bucket.stub:8080/?acl HTTP/1.1"); assertRequestLineEquals(httpMethod, "GET http://bucket.stub:8080/?acl HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n"); assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, AccessControlListHandler.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"); assertRequestLineEquals(httpMethod, "GET http://bucket.stub:8080/object HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n"); assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, assertResponseParserClassEquals(method, httpMethod,
ParseObjectFromHeadersAndHttpContent.class); ParseObjectFromHeadersAndHttpContent.class);
@ -211,7 +211,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
assertRequestLineEquals(httpMethod, "GET http://bucket.stub:8080/object?acl HTTP/1.1"); assertRequestLineEquals(httpMethod, "GET http://bucket.stub:8080/object?acl HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n"); assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, AccessControlListHandler.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"); assertRequestLineEquals(httpMethod, "HEAD http://bucket.stub:8080/object HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n"); assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseObjectMetadataFromHeaders.class); assertResponseParserClassEquals(method, httpMethod, ParseObjectMetadataFromHeaders.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
@ -243,7 +243,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
assertRequestLineEquals(httpMethod, "GET http://stub:8080/ HTTP/1.1"); assertRequestLineEquals(httpMethod, "GET http://stub:8080/ HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: stub\n"); assertHeadersEqual(httpMethod, "Host: stub\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseSax.class); assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, ListAllMyBucketsHandler.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"); assertRequestLineEquals(httpMethod, "PUT http://bucket.stub:8080/?acl HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 321\nContent-Type: text/xml\nHost: bucket.stub\n"); "Content-Length: 321\nContent-Type: text/xml\nHost: bucket.stub\n");
assertEntityEquals( assertPayloadEquals(
httpMethod, 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>"); "<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"); assertRequestLineEquals(httpMethod, "PUT http://bucket.stub:8080/ HTTP/1.1");
assertHeadersEqual(httpMethod, "Content-Length: 0\nHost: bucket.stub\n"); assertHeadersEqual(httpMethod, "Content-Length: 0\nHost: bucket.stub\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class); assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class);
assertSaxResponseParserClassEquals(method, null); assertSaxResponseParserClassEquals(method, null);
@ -305,7 +305,7 @@ public class S3ClientTest extends RestClientTest<S3AsyncClient> {
assertRequestLineEquals(httpMethod, "PUT http://bucket.stub:8080/hello HTTP/1.1"); assertRequestLineEquals(httpMethod, "PUT http://bucket.stub:8080/hello HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 5\nContent-Type: text/plain\nHost: bucket.stub\n"); "Content-Length: 5\nContent-Type: text/plain\nHost: bucket.stub\n");
assertEntityEquals(httpMethod, "hello"); assertPayloadEquals(httpMethod, "hello");
assertResponseParserClassEquals(method, httpMethod, ParseETagHeader.class); assertResponseParserClassEquals(method, httpMethod, ParseETagHeader.class);
assertSaxResponseParserClassEquals(method, null); 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"); assertRequestLineEquals(httpMethod, "PUT http://bucket.stub:8080/key?acl HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 321\nContent-Type: text/xml\nHost: bucket.stub\n"); "Content-Length: 321\nContent-Type: text/xml\nHost: bucket.stub\n");
assertEntityEquals( assertPayloadEquals(
httpMethod, 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>"); "<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>");

View File

@ -187,7 +187,7 @@ public class StubS3AsyncClient implements S3AsyncClient {
newMd.setLastModified(new Date()); newMd.setLastModified(new Date());
Blob newBlob = blobProvider.create(newMd); Blob newBlob = blobProvider.create(newMd);
newBlob.setData(sourceS3.getData()); newBlob.setPayload(sourceS3.getContent());
dest.put(destinationObject, newBlob); dest.put(destinationObject, newBlob);
return blob2ObjectMetadata.apply(blobStore.copy(newMd)); return blob2ObjectMetadata.apply(blobStore.copy(newMd));
} }

View File

@ -54,11 +54,11 @@ public class PutBucketOptionsTest {
} }
@Test @Test
public void testEntity() { public void testPayload() {
PutBucketOptions options = new PutBucketOptions(); PutBucketOptions options = new PutBucketOptions();
options.createIn(LocationConstraint.EU); options.createIn(LocationConstraint.EU);
assertEquals( assertEquals(
options.buildStringEntity(), options.buildStringPayload(),
"<CreateBucketConfiguration><LocationConstraint>EU</LocationConstraint></CreateBucketConfiguration>"); "<CreateBucketConfiguration><LocationConstraint>EU</LocationConstraint></CreateBucketConfiguration>");
} }

View File

@ -65,7 +65,7 @@ public class MainApp {
Blob blob = blobStore.newBlob(); Blob blob = blobStore.newBlob();
blob.getMetadata().setName("test"); blob.getMetadata().setName("test");
blob.setData("testdata"); blob.setPayload("testdata");
blobStore.putBlob(containerName, blob); blobStore.putBlob(containerName, blob);
// List Container // List Container

View File

@ -23,7 +23,6 @@
*/ */
package org.jclouds.aws.s3.jets3t; package org.jclouds.aws.s3.jets3t;
import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
@ -114,8 +113,8 @@ public class Util {
public static S3Object convertObject(org.jclouds.aws.s3.domain.S3Object jcObject) { public static S3Object convertObject(org.jclouds.aws.s3.domain.S3Object jcObject) {
S3Object jsObject = convertObjectHead(jcObject.getMetadata()); S3Object jsObject = convertObjectHead(jcObject.getMetadata());
if (jcObject.getData() != null) { if (jcObject.getContent() != null) {
jsObject.setDataInputStream((InputStream) jcObject.getData()); jsObject.setDataInputStream(jcObject.getContent());
} }
return jsObject; return jsObject;
} }
@ -149,9 +148,9 @@ public class Util {
} }
if (jsObject.getDataInputStream() != null) { if (jsObject.getDataInputStream() != null) {
jcObject.setData(jsObject.getDataInputStream()); jcObject.setPayload(jsObject.getDataInputStream());
} else { } 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) { if (jsObject.getContentType() != null) {

View File

@ -134,7 +134,7 @@ public class JCloudsS3ServiceLiveTest extends BaseBlobStoreIntegrationTest<S3Asy
String objectValue = "test"; String objectValue = "test";
Blob blob = context.getAsyncBlobStore().newBlob(); Blob blob = context.getAsyncBlobStore().newBlob();
blob.getMetadata().setName(objectKey); blob.getMetadata().setName(objectKey);
blob.setData(objectValue); blob.setPayload(objectValue);
addBlobToContainer(bucketName, blob); addBlobToContainer(bucketName, blob);
service.deleteObject(bucketName, objectKey); service.deleteObject(bucketName, objectKey);
@ -155,7 +155,7 @@ public class JCloudsS3ServiceLiveTest extends BaseBlobStoreIntegrationTest<S3Asy
Blob blob = context.getAsyncBlobStore().newBlob(); Blob blob = context.getAsyncBlobStore().newBlob();
blob.getMetadata().setName(objectKey); blob.getMetadata().setName(objectKey);
blob.setData(objectValue); blob.setPayload(objectValue);
blob.getMetadata().getUserMetadata().put(metadataName, metadataValue); blob.getMetadata().getUserMetadata().put(metadataName, metadataValue);
addBlobToContainer(bucketName, blob); addBlobToContainer(bucketName, blob);
@ -182,7 +182,7 @@ public class JCloudsS3ServiceLiveTest extends BaseBlobStoreIntegrationTest<S3Asy
Blob blob = context.getAsyncBlobStore().newBlob(); Blob blob = context.getAsyncBlobStore().newBlob();
blob.getMetadata().setName(objectKey); blob.getMetadata().setName(objectKey);
blob.setData(objectValue); blob.setPayload(objectValue);
blob.getMetadata().getUserMetadata().put(metadataName, metadataValue); blob.getMetadata().getUserMetadata().put(metadataName, metadataValue);
addBlobToContainer(bucketName, blob); addBlobToContainer(bucketName, blob);
@ -441,7 +441,7 @@ public class JCloudsS3ServiceLiveTest extends BaseBlobStoreIntegrationTest<S3Asy
Blob blob = context.getAsyncBlobStore().newBlob(); Blob blob = context.getAsyncBlobStore().newBlob();
blob.getMetadata().setName(sourceObjectKey); blob.getMetadata().setName(sourceObjectKey);
blob.setData(data); blob.setPayload(data);
blob.getMetadata().getUserMetadata().put(metadataName, sourceMetadataValue); blob.getMetadata().getUserMetadata().put(metadataName, sourceMetadataValue);
addBlobToContainer(bucketName, blob); addBlobToContainer(bucketName, blob);

View File

@ -44,8 +44,8 @@ public abstract class BaseJCloudsPerformanceLiveTest extends BasePerformanceLive
// object.setKey(id + ""); // object.setKey(id + "");
// //object.setContentType("text/plain"); // //object.setContentType("text/plain");
// object.setContentType("application/octetstream"); // object.setContentType("application/octetstream");
// //object.setData("this is a test"); // //object.setPayload("this is a test");
// object.setData(test); // object.setPayload(test);
// return context.getApi()Provider.getObject(s3Bucket, // return context.getApi()Provider.getObject(s3Bucket,
// object.getKey()).get(120,TimeUnit.SECONDS) != // object.getKey()).get(120,TimeUnit.SECONDS) !=
// S3Object.NOT_FOUND; // S3Object.NOT_FOUND;
@ -57,7 +57,7 @@ public abstract class BaseJCloudsPerformanceLiveTest extends BasePerformanceLive
throws Exception { throws Exception {
S3Object object = newObject(key); S3Object object = newObject(key);
object.getMetadata().setContentType(contentType); object.getMetadata().setContentType(contentType);
object.setData(data); object.setPayload(data);
return context.getApi().putObject(bucket, object) != null; return context.getApi().putObject(bucket, object) != null;
} }
@ -66,7 +66,7 @@ public abstract class BaseJCloudsPerformanceLiveTest extends BasePerformanceLive
throws Exception { throws Exception {
S3Object object = newObject(key); S3Object object = newObject(key);
object.getMetadata().setContentType(contentType); object.getMetadata().setContentType(contentType);
object.setData(data); object.setPayload(data);
return context.getApi().putObject(bucket, object) != null; return context.getApi().putObject(bucket, object) != null;
} }
@ -81,7 +81,7 @@ public abstract class BaseJCloudsPerformanceLiveTest extends BasePerformanceLive
throws Exception { throws Exception {
S3Object object = newObject(key); S3Object object = newObject(key);
object.getMetadata().setContentType(contentType); object.getMetadata().setContentType(contentType);
object.setData(data); object.setPayload(data);
object.setContentLength(new Long(data.available())); object.setContentLength(new Long(data.available()));
return context.getApi().putObject(bucket, object) != null; return context.getApi().putObject(bucket, object) != null;
} }
@ -91,7 +91,7 @@ public abstract class BaseJCloudsPerformanceLiveTest extends BasePerformanceLive
throws Exception { throws Exception {
S3Object object = newObject(key); S3Object object = newObject(key);
object.getMetadata().setContentType(contentType); object.getMetadata().setContentType(contentType);
object.setData(data); object.setPayload(data);
return context.getApi().putObject(bucket, object) != null; return context.getApi().putObject(bucket, object) != null;
} }
} }

View File

@ -35,7 +35,7 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import org.jclouds.azure.storage.AzureBlob; 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.BlobProperties;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse; import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ListableContainerProperties; import org.jclouds.azure.storage.blob.domain.ListableContainerProperties;
@ -193,7 +193,7 @@ public interface AzureBlobAsyncClient {
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
Future<String> putBlob( Future<String> putBlob(
@PathParam("container") String container, @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 * @see AzureBlobClient#getBlob

View File

@ -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. * it as a set of blocks. For more information, see the Put Block and Put Block List operations.
* <p/> * <p/>
* If you attempt to upload a blob that is larger than 64 MB, the service returns status code 413 * 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. * error in the response, including the maximum blob size permitted in bytes.
* <p/> * <p/>
* A Put Blob operation is permitted 10 minutes per MB to complete. If the operation is taking * A Put Blob operation is permitted 10 minutes per MB to complete. If the operation is taking

View File

@ -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.blobstore.functions.AzureBlobToBlob;
import org.jclouds.azure.storage.blob.domain.AzureBlob; import org.jclouds.azure.storage.blob.domain.AzureBlob;
import org.jclouds.azure.storage.blob.reference.AzureBlobConstants; 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.encryption.EncryptionService;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
public class BindAzureBlobToEntity extends BindBlobToEntityAndUserMetadataToHeadersWithPrefix { public class BindAzureBlobToPayload extends BindBlobToPayloadAndUserMetadataToHeadersWithPrefix {
private final AzureBlobToBlob azureBlob2Blob; private final AzureBlobToBlob azureBlob2Blob;
@Inject @Inject
public BindAzureBlobToEntity(AzureBlobToBlob azureBlob2Blob, public BindAzureBlobToPayload(AzureBlobToBlob azureBlob2Blob,
@Named(AzureBlobConstants.PROPERTY_AZUREBLOB_METADATA_PREFIX) String prefix, @Named(AzureBlobConstants.PROPERTY_AZUREBLOB_METADATA_PREFIX) String prefix,
EncryptionService encryptionService) { EncryptionService encryptionService) {
super(prefix, encryptionService); super(prefix, encryptionService);
this.azureBlob2Blob = azureBlob2Blob; this.azureBlob2Blob = azureBlob2Blob;
} }
public void bindToRequest(HttpRequest request, Object entity) { public void bindToRequest(HttpRequest request, Object payload) {
AzureBlob object = (AzureBlob) entity; AzureBlob object = (AzureBlob) payload;
checkArgument(object.getProperties().getSize() >= 0, "size must be set"); checkArgument(object.getProperties().getSize() >= 0, "size must be set");
checkArgument( checkArgument(
checkNotNull(object.getContentLength(), "object.getContentLength()") <= 64 * 1024 * 1024, checkNotNull(object.getContentLength(), "object.getContentLength()") <= 64 * 1024 * 1024,

View File

@ -50,7 +50,7 @@ public class AzureBlobToBlob implements Function<AzureBlob, Blob> {
Blob blob = blobFactory.create(blobPr2BlobMd.apply(from.getProperties())); Blob blob = blobFactory.create(blobPr2BlobMd.apply(from.getProperties()));
if (from.getContentLength() != null) if (from.getContentLength() != null)
blob.setContentLength(from.getContentLength()); blob.setContentLength(from.getContentLength());
blob.setData(from.getData()); blob.setPayload(from.getPayload());
blob.setAllHeaders(from.getAllHeaders()); blob.setAllHeaders(from.getAllHeaders());
return blob; return blob;
} }

View File

@ -49,7 +49,7 @@ public class BlobToAzureBlob implements Function<Blob, AzureBlob> {
AzureBlob object = objectProvider.create(blob2ObjectMd.apply(from.getMetadata())); AzureBlob object = objectProvider.create(blob2ObjectMd.apply(from.getMetadata()));
if (from.getContentLength() != null) if (from.getContentLength() != null)
object.setContentLength(from.getContentLength()); object.setContentLength(from.getContentLength());
object.setData(from.getData()); object.setPayload(from.getPayload());
object.setAllHeaders(from.getAllHeaders()); object.setAllHeaders(from.getAllHeaders());
return object; return object;
} }

View File

@ -29,9 +29,7 @@ import javax.inject.Provider;
import org.jclouds.azure.storage.blob.domain.AzureBlob; import org.jclouds.azure.storage.blob.domain.AzureBlob;
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties; import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
import org.jclouds.azure.storage.blob.domain.internal.AzureBlobImpl; import org.jclouds.azure.storage.blob.domain.internal.AzureBlobImpl;
import org.jclouds.blobstore.functions.CalculateSize; import org.jclouds.encryption.EncryptionService;
import org.jclouds.blobstore.functions.GenerateMD5;
import org.jclouds.blobstore.functions.GenerateMD5Result;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
@ -44,7 +42,6 @@ import com.google.inject.Scopes;
*/ */
public class AzureBlobModule extends AbstractModule { public class AzureBlobModule extends AbstractModule {
/** /**
* explicit factories are created here as it has been shown that Assisted Inject is extremely * 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 * 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 { private static class AzureBlobFactory implements AzureBlob.Factory {
@Inject @Inject
GenerateMD5Result generateMD5Result; EncryptionService encryptionService;
@Inject
GenerateMD5 generateMD5;
@Inject
CalculateSize calculateSize;
@Inject @Inject
Provider<MutableBlobProperties> metadataProvider; Provider<MutableBlobProperties> metadataProvider;
public AzureBlob create(MutableBlobProperties metadata) { public AzureBlob create(MutableBlobProperties metadata) {
return new AzureBlobImpl(generateMD5Result, generateMD5, calculateSize, return new AzureBlobImpl(encryptionService, metadata != null ? metadata : metadataProvider
metadata != null ? metadata : metadataProvider.get()); .get());
} }
} }

View File

@ -23,66 +23,25 @@
*/ */
package org.jclouds.azure.storage.blob.domain; 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.common.collect.Multimap;
import com.google.inject.internal.Nullable; import com.google.inject.internal.Nullable;
/** /**
* Amazon S3 is designed to store objects. Objects are stored in buckets and consist of a * 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. * {@link ObjectProperties#getUserProperties() metadata}, and an access control policy.
* *
* @author Adrian Cole * @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html" * @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 { public interface Factory {
AzureBlob create(@Nullable MutableBlobProperties properties); 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. * @return System and User metadata relevant to this object.
*/ */

View File

@ -24,18 +24,13 @@
package org.jclouds.azure.storage.blob.domain.internal; package org.jclouds.azure.storage.blob.domain.internal;
import static com.google.common.base.Preconditions.checkNotNull; 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 javax.inject.Inject;
import org.jclouds.azure.storage.blob.domain.AzureBlob; import org.jclouds.azure.storage.blob.domain.AzureBlob;
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties; import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
import org.jclouds.blobstore.domain.MD5InputStreamResult; import org.jclouds.encryption.EncryptionService;
import org.jclouds.blobstore.functions.CalculateSize; import org.jclouds.http.internal.BasePayloadEnclosingImpl;
import org.jclouds.blobstore.functions.GenerateMD5;
import org.jclouds.blobstore.functions.GenerateMD5Result;
import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
@ -45,70 +40,20 @@ import com.google.common.collect.Multimap;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class AzureBlobImpl implements AzureBlob, Comparable<AzureBlob> { public class AzureBlobImpl extends BasePayloadEnclosingImpl implements AzureBlob,
private final GenerateMD5Result generateMD5Result; Comparable<AzureBlob> {
private final GenerateMD5 generateMD5;
private final CalculateSize calculateSize;
private final MutableBlobProperties properties; private final MutableBlobProperties properties;
private Object data;
private Multimap<String, String> allHeaders = LinkedHashMultimap.create(); private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
private Long contentLength;
@Inject @Inject
public AzureBlobImpl(GenerateMD5Result generateMD5Result, GenerateMD5 generateMD5, public AzureBlobImpl(EncryptionService encryptionService, MutableBlobProperties properties) {
CalculateSize calculateSize, MutableBlobProperties properties) { super(encryptionService);
this.generateMD5Result = generateMD5Result;
this.generateMD5 = generateMD5;
this.calculateSize = calculateSize;
this.properties = properties; 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));
}
}
/** @Override
* {@inheritDoc} protected void setContentMD5(byte[] md5) {
*/ getProperties().setContentMD5(md5);
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;
} }
/** /**
@ -147,7 +92,7 @@ public class AzureBlobImpl implements AzureBlob, Comparable<AzureBlob> {
int result = 1; int result = 1;
result = prime * result + ((allHeaders == null) ? 0 : allHeaders.hashCode()); result = prime * result + ((allHeaders == null) ? 0 : allHeaders.hashCode());
result = prime * result + ((contentLength == null) ? 0 : contentLength.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()); result = prime * result + ((properties == null) ? 0 : properties.hashCode());
return result; return result;
} }
@ -171,10 +116,10 @@ public class AzureBlobImpl implements AzureBlob, Comparable<AzureBlob> {
return false; return false;
} else if (!contentLength.equals(other.contentLength)) } else if (!contentLength.equals(other.contentLength))
return false; return false;
if (data == null) { if (payload == null) {
if (other.data != null) if (other.payload != null)
return false; return false;
} else if (!data.equals(other.data)) } else if (!payload.equals(other.payload))
return false; return false;
if (properties == null) { if (properties == null) {
if (other.properties != null) if (other.properties != null)

View File

@ -66,7 +66,7 @@ public class ParseBlobFromHeadersAndHttpContent implements Function<HttpResponse
public AzureBlob apply(HttpResponse from) { public AzureBlob apply(HttpResponse from) {
AzureBlob object = objectProvider.create(metadataParser.apply(from)); AzureBlob object = objectProvider.create(metadataParser.apply(from));
addAllHeadersTo(from, object); addAllHeadersTo(from, object);
object.setData(from.getContent()); object.setPayload(from.getContent());
attemptToParseSizeAndRangeFromHeaders(from, object); attemptToParseSizeAndRangeFromHeaders(from, object);
return object; return object;
} }

View File

@ -27,7 +27,6 @@ import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.reflect.UndeclaredThrowableException; import java.lang.reflect.UndeclaredThrowableException;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
@ -229,7 +228,7 @@ public class AzureBlobClientLiveTest {
// Test PUT with string data, ETag hash, and a piece of metadata // Test PUT with string data, ETag hash, and a piece of metadata
AzureBlob object = connection.newBlob(); AzureBlob object = connection.newBlob();
object.getProperties().setName("object"); object.getProperties().setName("object");
object.setData(data); object.setPayload(data);
object.setContentLength(data.length()); object.setContentLength(data.length());
object.generateMD5(); object.generateMD5();
object.getProperties().setContentType("text/plain"); object.getProperties().setContentType("text/plain");
@ -281,7 +280,7 @@ public class AzureBlobClientLiveTest {
} }
// Test GET of object (including updated metadata) // Test GET of object (including updated metadata)
AzureBlob getBlob = connection.getBlob(privateContainer, object.getProperties().getName()); 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()); // TODO assertEquals(getBlob.getName(), object.getProperties().getName());
assertEquals(getBlob.getContentLength(), new Long(data.length())); assertEquals(getBlob.getContentLength(), new Long(data.length()));
assertEquals(getBlob.getProperties().getContentType(), "text/plain"); assertEquals(getBlob.getProperties().getContentType(), "text/plain");
@ -313,7 +312,7 @@ public class AzureBlobClientLiveTest {
ByteArrayInputStream bais = new ByteArrayInputStream(data.getBytes("UTF-8")); ByteArrayInputStream bais = new ByteArrayInputStream(data.getBytes("UTF-8"));
object = connection.newBlob(); object = connection.newBlob();
object.getProperties().setName("chunked-object"); object.getProperties().setName("chunked-object");
object.setData(bais); object.setPayload(bais);
object.setContentLength(new Long(data.getBytes().length)); object.setContentLength(new Long(data.getBytes().length));
newEtag = connection.putBlob(privateContainer, object); newEtag = connection.putBlob(privateContainer, object);
assertEquals(encryptionService.toHexString(md5), encryptionService.toHexString(getBlob assertEquals(encryptionService.toHexString(md5), encryptionService.toHexString(getBlob

View File

@ -48,18 +48,17 @@ public class BindBlobToMultipartForm implements Binder {
public static final String BOUNDARY = "--JCLOUDS--"; public static final String BOUNDARY = "--JCLOUDS--";
public void bindToRequest(HttpRequest request, Object entity) { public void bindToRequest(HttpRequest request, Object payload) {
Blob object = (Blob) entity; Blob object = (Blob) payload;
File file = new File(object.getMetadata().getName()); File file = new File(object.getMetadata().getName());
Multimap<String, String> partHeaders = ImmutableMultimap.of("Content-Disposition", String Multimap<String, String> partHeaders = ImmutableMultimap.of("Content-Disposition", String
.format("form-data; name=\"%s\"; filename=\"%s\"", file.getName(), file.getName()), .format("form-data; name=\"%s\"; filename=\"%s\"", file.getName(), file.getName()),
HttpHeaders.CONTENT_TYPE, checkNotNull(object.getMetadata().getContentType(), HttpHeaders.CONTENT_TYPE, checkNotNull(object.getMetadata().getContentType(),
"object.metadata.contentType()")); "object.metadata.contentType()"));
Object data = checkNotNull(object.getData(), "object.getData()"); Object data = checkNotNull(object.getPayload(), "object.getPayload()").getRawContent();
Part part; Part part;
try { try {
if (data instanceof byte[]) { if (data instanceof byte[]) {
part = new Part(partHeaders, (byte[]) data); part = new Part(partHeaders, (byte[]) data);
} else if (data instanceof String) { } else if (data instanceof String) {
@ -77,7 +76,7 @@ public class BindBlobToMultipartForm implements Binder {
} }
MultipartForm form = new MultipartForm(BOUNDARY, part); MultipartForm form = new MultipartForm(BOUNDARY, part);
request.setEntity(form.getData()); request.setPayload(form.getData());
request.getHeaders().put(HttpHeaders.CONTENT_TYPE, request.getHeaders().put(HttpHeaders.CONTENT_TYPE,
"multipart/form-data; boundary=" + BOUNDARY); "multipart/form-data; boundary=" + BOUNDARY);

View File

@ -37,18 +37,18 @@ import org.jclouds.rest.Binder;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class BindBlobToEntity implements Binder { public class BindBlobToPayload implements Binder {
private final EncryptionService encryptionService; private final EncryptionService encryptionService;
@Inject @Inject
public BindBlobToEntity(EncryptionService encryptionService) { public BindBlobToPayload(EncryptionService encryptionService) {
this.encryptionService = encryptionService; this.encryptionService = encryptionService;
} }
public void bindToRequest(HttpRequest request, Object entity) { public void bindToRequest(HttpRequest request, Object payload) {
Blob object = (Blob) entity; Blob object = (Blob) payload;
request.setEntity(checkNotNull(object.getData(), "object.getContent()")); request.setPayload(checkNotNull(object.getContent(), "object.getContent()"));
request.getHeaders() request.getHeaders()
.put( .put(
HttpHeaders.CONTENT_TYPE, HttpHeaders.CONTENT_TYPE,

View File

@ -36,24 +36,24 @@ import org.jclouds.http.HttpRequest;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class BindBlobToEntityAndUserMetadataToHeadersWithPrefix extends BindBlobToEntity { public class BindBlobToPayloadAndUserMetadataToHeadersWithPrefix extends BindBlobToPayload {
private final String metadataPrefix; private final String metadataPrefix;
@Inject @Inject
public BindBlobToEntityAndUserMetadataToHeadersWithPrefix( public BindBlobToPayloadAndUserMetadataToHeadersWithPrefix(
@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix, @Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix,
EncryptionService encryptionService) { EncryptionService encryptionService) {
super(encryptionService); super(encryptionService);
this.metadataPrefix = metadataPrefix; this.metadataPrefix = metadataPrefix;
} }
public void bindToRequest(HttpRequest request, Object entity) { public void bindToRequest(HttpRequest request, Object payload) {
Blob object = (Blob) entity; Blob object = (Blob) payload;
for (String key : object.getMetadata().getUserMetadata().keySet()) { for (String key : object.getMetadata().getUserMetadata().keySet()) {
request.getHeaders().put(key.startsWith(metadataPrefix) ? key : metadataPrefix + key, request.getHeaders().put(key.startsWith(metadataPrefix) ? key : metadataPrefix + key,
object.getMetadata().getUserMetadata().get(key)); object.getMetadata().getUserMetadata().get(key));
} }
super.bindToRequest(request, entity); super.bindToRequest(request, payload);
} }
} }

View File

@ -43,8 +43,8 @@ public class BindMapToHeadersWithPrefix implements Binder {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void bindToRequest(HttpRequest request, Object entity) { public void bindToRequest(HttpRequest request, Object payload) {
Map<String, String> userMetadata = (Map<String, String>) entity; Map<String, String> userMetadata = (Map<String, String>) payload;
for (Entry<String, String> entry : userMetadata.entrySet()) { for (Entry<String, String> entry : userMetadata.entrySet()) {
if (entry.getKey().startsWith(metadataPrefix)) { if (entry.getKey().startsWith(metadataPrefix)) {
request.getHeaders().put(entry.getKey().toLowerCase(), entry.getValue()); request.getHeaders().put(entry.getKey().toLowerCase(), entry.getValue());

View File

@ -29,9 +29,7 @@ import javax.inject.Provider;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.MutableBlobMetadata; import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.internal.BlobImpl; import org.jclouds.blobstore.domain.internal.BlobImpl;
import org.jclouds.blobstore.functions.CalculateSize; import org.jclouds.encryption.EncryptionService;
import org.jclouds.blobstore.functions.GenerateMD5;
import org.jclouds.blobstore.functions.GenerateMD5Result;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
@ -55,17 +53,13 @@ public class BlobStoreObjectModule extends AbstractModule {
private static class BlobFactory implements Blob.Factory { private static class BlobFactory implements Blob.Factory {
@Inject @Inject
GenerateMD5Result generateMD5Result; EncryptionService encryptionService;
@Inject
GenerateMD5 generateMD5;
@Inject
CalculateSize calculateSize;
@Inject @Inject
Provider<MutableBlobMetadata> metadataProvider; Provider<MutableBlobMetadata> metadataProvider;
public Blob create(MutableBlobMetadata metadata) { public Blob create(MutableBlobMetadata metadata) {
return new BlobImpl(generateMD5Result, generateMD5, calculateSize, return new BlobImpl(encryptionService, metadata != null ? metadata : metadataProvider
metadata != null ? metadata : metadataProvider.get()); .get());
} }
} }

View File

@ -23,60 +23,24 @@
*/ */
package org.jclouds.blobstore.domain; package org.jclouds.blobstore.domain;
import org.jclouds.http.PayloadEnclosing;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.inject.internal.Nullable; import com.google.inject.internal.Nullable;
/** /**
* Value type for an HTTP Blob service. Blobs are stored in containers and consist * 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} * @link Blob.Metadata#getUserMetadata() metadata}
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public interface Blob extends Comparable<Blob> { public interface Blob extends PayloadEnclosing, Comparable<Blob> {
public interface Factory { public interface Factory {
Blob create(@Nullable MutableBlobMetadata metadata); 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. * @return System and User metadata relevant to this object.
*/ */

View File

@ -24,109 +24,39 @@
package org.jclouds.blobstore.domain.internal; package org.jclouds.blobstore.domain.internal;
import static com.google.common.base.Preconditions.checkNotNull; 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 javax.inject.Inject;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.MD5InputStreamResult;
import org.jclouds.blobstore.domain.MutableBlobMetadata; import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.ResourceMetadata; import org.jclouds.blobstore.domain.ResourceMetadata;
import org.jclouds.blobstore.functions.CalculateSize; import org.jclouds.encryption.EncryptionService;
import org.jclouds.blobstore.functions.GenerateMD5; import org.jclouds.http.internal.BasePayloadEnclosingImpl;
import org.jclouds.blobstore.functions.GenerateMD5Result;
import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
/** /**
* Value type for an HTTP Blob service. Blobs are stored in {@link ResourceMetadata containers} and consist * 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} * @link Blob.Metadata#getUserMetadata() metadata}
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class BlobImpl implements Blob, Comparable<Blob> { public class BlobImpl extends BasePayloadEnclosingImpl implements Blob, Comparable<Blob> {
private final GenerateMD5Result generateMD5Result;
private final GenerateMD5 generateMD5;
private final CalculateSize calculateSize;
private final MutableBlobMetadata metadata; private final MutableBlobMetadata metadata;
private Object data;
private Multimap<String, String> allHeaders = LinkedHashMultimap.create(); private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
private Long contentLength;
@Inject @Inject
public BlobImpl(GenerateMD5Result generateMD5Result, GenerateMD5 generateMD5, public BlobImpl(EncryptionService encryptionService, MutableBlobMetadata metadata) {
CalculateSize calculateSize, MutableBlobMetadata metadata) { super(encryptionService);
this.generateMD5Result = generateMD5Result;
this.generateMD5 = generateMD5;
this.calculateSize = calculateSize;
this.metadata = metadata; this.metadata = metadata;
} }
/** @Override
* generate an MD5 Hash for the current data. protected void setContentMD5(byte[] md5) {
* <p/> getMetadata().setContentMD5(checkNotNull(md5, "md5"));
* <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;
} }
/** /**
@ -159,7 +89,7 @@ public class BlobImpl implements Blob, Comparable<Blob> {
int result = 1; int result = 1;
result = prime * result + ((allHeaders == null) ? 0 : allHeaders.hashCode()); result = prime * result + ((allHeaders == null) ? 0 : allHeaders.hashCode());
result = prime * result + ((contentLength == null) ? 0 : contentLength.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()); result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
return result; return result;
} }
@ -183,10 +113,10 @@ public class BlobImpl implements Blob, Comparable<Blob> {
return false; return false;
} else if (!contentLength.equals(other.contentLength)) } else if (!contentLength.equals(other.contentLength))
return false; return false;
if (data == null) { if (payload == null) {
if (other.data != null) if (other.payload != null)
return false; return false;
} else if (!data.equals(other.data)) } else if (!payload.equals(other.payload))
return false; return false;
if (metadata == null) { if (metadata == null) {
if (other.metadata != null) if (other.metadata != null)

View File

@ -35,7 +35,7 @@ import org.jclouds.blobstore.domain.ResourceType;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
/** /**
* Identity of the object * Idpayload of the object
* *
* @author Adrian Cole * @author Adrian Cole
*/ */

View File

@ -36,7 +36,7 @@ import org.jclouds.blobstore.domain.ResourceType;
import com.google.inject.internal.Nullable; import com.google.inject.internal.Nullable;
/** /**
* Identity of the object * Idpayload of the object
* *
* @author Adrian Cole * @author Adrian Cole
*/ */

View File

@ -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> {
}

View File

@ -26,6 +26,7 @@ package org.jclouds.blobstore.functions;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.Payloads;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -44,7 +45,7 @@ public class ObjectMD5 implements Function<Object, byte[]> {
object = (Blob) from; object = (Blob) from;
} else { } else {
object = blobFactory.create(null); object = blobFactory.create(null);
object.setData(from); object.setPayload(Payloads.newPayload(from));
} }
if (object.getMetadata().getContentMD5() == null) if (object.getMetadata().getContentMD5() == null)
object.generateMD5(); object.generateMD5();

View File

@ -66,7 +66,7 @@ public class ParseBlobFromHeadersAndHttpContent implements Function<HttpResponse
MutableBlobMetadata metadata = metadataParser.apply(from); MutableBlobMetadata metadata = metadataParser.apply(from);
Blob object = blobFactory.create(metadata); Blob object = blobFactory.create(metadata);
addAllHeadersTo(from, object); addAllHeadersTo(from, object);
object.setData(from.getContent()); object.setPayload(from.getContent());
assert object.getMetadata() == metadata; assert object.getMetadata() == metadata;
attemptToParseSizeAndRangeFromHeaders(from, object); attemptToParseSizeAndRangeFromHeaders(from, object);
return object; return object;

View File

@ -44,6 +44,12 @@ import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
import org.jclouds.blobstore.strategy.CountListStrategy; import org.jclouds.blobstore.strategy.CountListStrategy;
import org.jclouds.blobstore.strategy.GetBlobsInListStrategy; import org.jclouds.blobstore.strategy.GetBlobsInListStrategy;
import org.jclouds.blobstore.strategy.ListBlobMetadataStrategy; 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 org.jclouds.util.Utils;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
@ -81,7 +87,7 @@ public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements Inpu
String realKey = prefixer.apply(o.toString()); String realKey = prefixer.apply(o.toString());
try { try {
return (InputStream) (connection.getBlob(containerName, realKey).get( return (InputStream) (connection.getBlob(containerName, realKey).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).getData(); requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).getContent();
} catch (KeyNotFoundException e) { } catch (KeyNotFoundException e) {
return null; return null;
} catch (Exception e) { } catch (Exception e) {
@ -129,7 +135,7 @@ public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements Inpu
return Collections2.transform(getAllBlobs.execute(containerName, options), return Collections2.transform(getAllBlobs.execute(containerName, options),
new Function<Blob, InputStream>() { new Function<Blob, InputStream>() {
public InputStream apply(Blob from) { 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>>(); Set<Map.Entry<String, InputStream>> entrySet = new HashSet<Map.Entry<String, InputStream>>();
for (Blob object : this.getAllBlobs.execute(containerName, options)) { for (Blob object : this.getAllBlobs.execute(containerName, options)) {
entrySet.add(new Entry(pathStripper.apply(object.getMetadata().getName()), entrySet.add(new Entry(pathStripper.apply(object.getMetadata().getName()),
(InputStream) object.getData())); (InputStream) object.getContent()));
} }
return entrySet; return entrySet;
} }
@ -226,7 +232,7 @@ public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements Inpu
for (Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) { for (Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
Blob object = connection.newBlob(); Blob object = connection.newBlob();
object.getMetadata().setName(prefixer.apply(entry.getKey())); object.getMetadata().setName(prefixer.apply(entry.getKey()));
object.setData(entry.getValue()); object.setPayload(Payloads.newPayload(entry.getValue()));
object.generateMD5(); object.generateMD5();
puts.add(connection.putBlob(containerName, object)); puts.add(connection.putBlob(containerName, object));
// / ParamExtractor Funcion<?,String> // / ParamExtractor Funcion<?,String>
@ -248,7 +254,7 @@ public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements Inpu
* @see #putInternal(String, Object) * @see #putInternal(String, Object)
*/ */
public InputStream putString(String key, String value) { 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) * @see #putInternal(String, Object)
*/ */
public InputStream putFile(String key, File value) { 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) * @see #putInternal(String, Object)
*/ */
public InputStream putBytes(String key, byte[] value) { 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) * @see #putInternal(String, Object)
*/ */
public InputStream put(String key, InputStream value) { 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) * @see S3Client#put(String, Blob)
*/ */
@VisibleForTesting @VisibleForTesting
InputStream putInternal(String s, Object o) { InputStream putInternal(String s, Payload payload) {
Blob object = connection.newBlob(); Blob object = connection.newBlob();
object.getMetadata().setName(prefixer.apply(s)); object.getMetadata().setName(prefixer.apply(s));
try { try {
InputStream returnVal = containsKey(s) ? get(s) : null; InputStream returnVal = containsKey(s) ? get(s) : null;
object.setData(o); object.setPayload(payload);
object.generateMD5(); object.generateMD5();
connection.putBlob(containerName, object).get(requestTimeoutMilliseconds, connection.putBlob(containerName, object).get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);

View File

@ -133,7 +133,7 @@ public class GetOptions {
* Not compatible with {@link #ifETagDoesntMatch(String)} or {@link #ifModifiedSince(Date)} * Not compatible with {@link #ifETagDoesntMatch(String)} or {@link #ifModifiedSince(Date)}
* *
* @param eTag * @param eTag
* hash representing the entity * hash representing the payload
*/ */
public GetOptions ifETagMatches(String eTag) { public GetOptions ifETagMatches(String eTag) {
checkArgument(getIfNoneMatch() == null, checkArgument(getIfNoneMatch() == null,
@ -147,7 +147,7 @@ public class GetOptions {
/** /**
* For use in the request header: If-Match * For use in the request header: If-Match
* <p /> * <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). * return a 412 (precondition failed).
* *
* @see GetOptions#ifETagMatches(String) * @see GetOptions#ifETagMatches(String)
@ -162,7 +162,7 @@ public class GetOptions {
* Not compatible with {@link #ifETagMatches(String)} or {@link #ifUnmodifiedSince(Date)} * Not compatible with {@link #ifETagMatches(String)} or {@link #ifUnmodifiedSince(Date)}
* *
* @param eTag * @param eTag
* hash representing the entity * hash representing the payload
*/ */
public GetOptions ifETagDoesntMatch(String eTag) { public GetOptions ifETagDoesntMatch(String eTag) {
checkArgument(getIfMatch() == null, checkArgument(getIfMatch() == null,
@ -176,7 +176,7 @@ public class GetOptions {
/** /**
* For use in the request header: If-None-Match * For use in the request header: If-None-Match
* <p /> * <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). * return a 304 (not modified).
* *
* @see GetOptions#ifETagDoesntMatch(String) * @see GetOptions#ifETagDoesntMatch(String)

View File

@ -65,7 +65,7 @@ public class MarkerFileMkdirStrategy implements MkdirStrategy {
TimeUnit.MILLISECONDS)) { TimeUnit.MILLISECONDS)) {
Blob blob = connection.newBlob(); Blob blob = connection.newBlob();
blob.getMetadata().setName(directory + directorySuffix); blob.getMetadata().setName(directory + directorySuffix);
blob.setData(""); blob.setPayload("");
blob.getMetadata().setContentType("application/directory"); blob.getMetadata().setContentType("application/directory");
connection.putBlob(containerName, blob).get(requestTimeoutMilliseconds, connection.putBlob(containerName, blob).get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);

View File

@ -40,6 +40,7 @@ import org.jclouds.util.Utils;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class BlobStoreUtils { public class BlobStoreUtils {
public static Blob newBlob(BlobStore blobStore, ResourceMetadata blobMeta) { public static Blob newBlob(BlobStore blobStore, ResourceMetadata blobMeta) {
Blob blob = blobStore.newBlob(); Blob blob = blobStore.newBlob();
if (blobMeta instanceof BlobMetadata) { if (blobMeta instanceof BlobMetadata) {
@ -77,8 +78,8 @@ public class BlobStoreUtils {
public static String getContentAsStringAndClose(Blob blob) throws IOException { public static String getContentAsStringAndClose(Blob blob) throws IOException {
checkNotNull(blob, "blob"); checkNotNull(blob, "blob");
checkNotNull(blob.getData(), "blob.data"); checkNotNull(blob.getContent(), "blob.data");
Object o = blob.getData(); Object o = blob.getContent();
if (o instanceof InputStream) { if (o instanceof InputStream) {
return Utils.toStringAndClose((InputStream) o); return Utils.toStringAndClose((InputStream) o);
} else { } else {

View File

@ -63,7 +63,7 @@ public class BindBlobToMultipartFormTest {
EXPECTS = builder.toString(); EXPECTS = builder.toString();
TEST_BLOB = blobProvider.create(null); TEST_BLOB = blobProvider.create(null);
TEST_BLOB.getMetadata().setName("hello"); TEST_BLOB.getMetadata().setName("hello");
TEST_BLOB.setData("hello"); TEST_BLOB.setPayload("hello");
TEST_BLOB.getMetadata().setContentType(MediaType.TEXT_PLAIN); TEST_BLOB.getMetadata().setContentType(MediaType.TEXT_PLAIN);
} }
@ -76,7 +76,7 @@ public class BindBlobToMultipartFormTest {
HttpRequest request = new HttpRequest("GET", URI.create("http://localhost:8001")); HttpRequest request = new HttpRequest("GET", URI.create("http://localhost:8001"));
binder.bindToRequest(request, TEST_BLOB); 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_LENGTH), 131 + "");
assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE), assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE),

View File

@ -47,6 +47,7 @@ import org.jclouds.blobstore.domain.ResourceMetadata;
import org.jclouds.blobstore.util.BlobStoreUtils; import org.jclouds.blobstore.util.BlobStoreUtils;
import org.jclouds.encryption.internal.JCEEncryptionService; import org.jclouds.encryption.internal.JCEEncryptionService;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.jclouds.http.Payloads;
import org.testng.annotations.DataProvider; import org.testng.annotations.DataProvider;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -302,7 +303,7 @@ public class BaseBlobIntegrationTest<A, S> extends BaseBlobStoreIntegrationTest<
throws InterruptedException, IOException { throws InterruptedException, IOException {
Blob object = newBlob(key); Blob object = newBlob(key);
object.getMetadata().setContentType(type); object.getMetadata().setContentType(type);
object.setData(content); object.setPayload(Payloads.newPayload(content));
if (content instanceof InputStream) { if (content instanceof InputStream) {
object.generateMD5(); object.generateMD5();
} }
@ -323,7 +324,7 @@ public class BaseBlobIntegrationTest<A, S> extends BaseBlobStoreIntegrationTest<
String key = "hello"; String key = "hello";
Blob object = newBlob(key); Blob object = newBlob(key);
object.setData(TEST_STRING); object.setPayload(TEST_STRING);
object.getMetadata().setContentType("text/plain"); object.getMetadata().setContentType("text/plain");
object.getMetadata().setSize(new Long(TEST_STRING.length())); object.getMetadata().setSize(new Long(TEST_STRING.length()));
// NOTE all metadata in jclouds comes out as lowercase, in an effort to normalize the // NOTE all metadata in jclouds comes out as lowercase, in an effort to normalize the

View File

@ -71,7 +71,7 @@ public class BaseBlobLiveTest<A, S> extends BaseBlobStoreIntegrationTest<A, S> {
InputStream input = connection.getInputStream(); InputStream input = connection.getInputStream();
Blob object = newBlob(key); Blob object = newBlob(key);
object.setData(input); object.setPayload(input);
object.setContentLength(length); object.setContentLength(length);
object.getMetadata().setContentMD5(md5); object.getMetadata().setContentMD5(md5);
object.getMetadata().setSize(new Long(length)); object.getMetadata().setSize(new Long(length));

View File

@ -115,7 +115,7 @@ public class BaseBlobMapIntegrationTest<A, S> extends BaseMapIntegrationTest<A,
assertEquals(fiveStrings.get(entry.getKey()), BlobStoreUtils assertEquals(fiveStrings.get(entry.getKey()), BlobStoreUtils
.getContentAsStringAndClose(entry.getValue())); .getContentAsStringAndClose(entry.getValue()));
Blob value = entry.getValue(); Blob value = entry.getValue();
value.setData(""); value.setPayload("");
value.generateMD5(); value.generateMD5();
entry.setValue(value); entry.setValue(value);
} }
@ -135,7 +135,7 @@ public class BaseBlobMapIntegrationTest<A, S> extends BaseMapIntegrationTest<A,
Map<String, Blob> map = createMap(context, bucketName); Map<String, Blob> map = createMap(context, bucketName);
putStringWithMD5(map, "one", "apple"); putStringWithMD5(map, "one", "apple");
Blob object = newBlob("one"); Blob object = newBlob("one");
object.setData("apple"); object.setPayload("apple");
object.generateMD5(); object.generateMD5();
assertConsistencyAwareContainsValue(map, object); assertConsistencyAwareContainsValue(map, object);
} finally { } finally {
@ -163,11 +163,11 @@ public class BaseBlobMapIntegrationTest<A, S> extends BaseMapIntegrationTest<A,
try { try {
Map<String, Blob> map = createMap(context, bucketName); Map<String, Blob> map = createMap(context, bucketName);
Blob object = newBlob("one"); Blob object = newBlob("one");
object.setData(IOUtils.toInputStream("apple")); object.setPayload(IOUtils.toInputStream("apple"));
object.generateMD5(); object.generateMD5();
Blob old = map.put(object.getMetadata().getName(), object); Blob old = map.put(object.getMetadata().getName(), object);
getOneReturnsAppleAndOldValueIsNull(map, old); getOneReturnsAppleAndOldValueIsNull(map, old);
object.setData(IOUtils.toInputStream("bear")); object.setPayload(IOUtils.toInputStream("bear"));
object.generateMD5(); object.generateMD5();
Blob apple = map.put(object.getMetadata().getName(), object); Blob apple = map.put(object.getMetadata().getName(), object);
getOneReturnsBearAndOldValueIsApple(map, apple); getOneReturnsBearAndOldValueIsApple(map, apple);
@ -184,7 +184,7 @@ public class BaseBlobMapIntegrationTest<A, S> extends BaseMapIntegrationTest<A,
Map<String, Blob> newMap = new HashMap<String, Blob>(); Map<String, Blob> newMap = new HashMap<String, Blob>();
for (String key : fiveInputs.keySet()) { for (String key : fiveInputs.keySet()) {
Blob object = newBlob(key); Blob object = newBlob(key);
object.setData(fiveInputs.get(key)); object.setPayload(fiveInputs.get(key));
object.setContentLength(new Long(fiveBytes.get(key).length)); object.setContentLength(new Long(fiveBytes.get(key).length));
newMap.put(key, object); newMap.put(key, object);
} }
@ -200,7 +200,7 @@ public class BaseBlobMapIntegrationTest<A, S> extends BaseMapIntegrationTest<A,
@Override @Override
protected void putStringWithMD5(Map<String, Blob> map, String key, String value) { protected void putStringWithMD5(Map<String, Blob> map, String key, String value) {
Blob object = newBlob(key); Blob object = newBlob(key);
object.setData(value); object.setPayload(value);
object.generateMD5(); object.generateMD5();
map.put(key, object); map.put(key, object);
} }
@ -209,7 +209,7 @@ public class BaseBlobMapIntegrationTest<A, S> extends BaseMapIntegrationTest<A,
Map<String, Blob> newMap = new HashMap<String, Blob>(); Map<String, Blob> newMap = new HashMap<String, Blob>();
for (Map.Entry<String, String> entry : fiveStrings.entrySet()) { for (Map.Entry<String, String> entry : fiveStrings.entrySet()) {
Blob object = newBlob(entry.getKey()); Blob object = newBlob(entry.getKey());
object.setData(entry.getValue()); object.setPayload(entry.getValue());
newMap.put(entry.getKey(), object); newMap.put(entry.getKey(), object);
} }
map.putAll(newMap); map.putAll(newMap);
@ -219,7 +219,7 @@ public class BaseBlobMapIntegrationTest<A, S> extends BaseMapIntegrationTest<A,
Map<String, Blob> newMap = new HashMap<String, Blob>(); Map<String, Blob> newMap = new HashMap<String, Blob>();
for (Map.Entry<String, String> entry : fiveStringsUnderPath.entrySet()) { for (Map.Entry<String, String> entry : fiveStringsUnderPath.entrySet()) {
Blob object = newBlob(entry.getKey()); Blob object = newBlob(entry.getKey());
object.setData(entry.getValue()); object.setPayload(entry.getValue());
newMap.put(entry.getKey(), object); newMap.put(entry.getKey(), object);
} }
map.putAll(newMap); map.putAll(newMap);

View File

@ -263,7 +263,7 @@ public class BaseBlobStoreIntegrationTest<A, S> {
protected String addBlobToContainer(String sourceContainer, String key) { protected String addBlobToContainer(String sourceContainer, String key) {
Blob sourceObject = newBlob(key); Blob sourceObject = newBlob(key);
sourceObject.getMetadata().setContentType("text/xml"); sourceObject.getMetadata().setContentType("text/xml");
sourceObject.setData(TEST_STRING); sourceObject.setPayload(TEST_STRING);
return addBlobToContainer(sourceContainer, sourceObject); return addBlobToContainer(sourceContainer, sourceObject);
} }
@ -272,7 +272,7 @@ public class BaseBlobStoreIntegrationTest<A, S> {
fiveStringsUnderPath.entrySet())) { fiveStringsUnderPath.entrySet())) {
Blob sourceObject = newBlob(entry.getKey()); Blob sourceObject = newBlob(entry.getKey());
sourceObject.getMetadata().setContentType("text/xml"); sourceObject.getMetadata().setContentType("text/xml");
sourceObject.setData(entry.getValue()); sourceObject.setPayload(entry.getValue());
addBlobToContainer(sourceContainer, sourceObject); addBlobToContainer(sourceContainer, sourceObject);
} }
} }

View File

@ -202,7 +202,7 @@ public class BaseContainerIntegrationTest<A, S> extends BaseBlobStoreIntegration
protected void addAlphabetUnderRoot(String containerName) throws InterruptedException { protected void addAlphabetUnderRoot(String containerName) throws InterruptedException {
for (char letter = 'a'; letter <= 'z'; letter++) { for (char letter = 'a'; letter <= 'z'; letter++) {
Blob blob = newBlob(letter + ""); Blob blob = newBlob(letter + "");
blob.setData(letter + "content"); blob.setPayload(letter + "content");
context.getBlobStore().putBlob(containerName, blob); context.getBlobStore().putBlob(containerName, blob);
} }
} }
@ -210,7 +210,7 @@ public class BaseContainerIntegrationTest<A, S> extends BaseBlobStoreIntegration
protected void add15UnderRoot(String containerName) throws InterruptedException { protected void add15UnderRoot(String containerName) throws InterruptedException {
for (int i = 0; i < 15; i++) { for (int i = 0; i < 15; i++) {
Blob blob = newBlob(i + ""); Blob blob = newBlob(i + "");
blob.setData(i + "content"); blob.setPayload(i + "content");
context.getBlobStore().putBlob(containerName, blob); context.getBlobStore().putBlob(containerName, blob);
} }
} }
@ -219,7 +219,7 @@ public class BaseContainerIntegrationTest<A, S> extends BaseBlobStoreIntegration
throws InterruptedException { throws InterruptedException {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
Blob blob = newBlob(prefix + "/" + i); Blob blob = newBlob(prefix + "/" + i);
blob.setData(i + "content"); blob.setPayload(i + "content");
context.getBlobStore().putBlob(containerName, blob); context.getBlobStore().putBlob(containerName, blob);
} }
} }

View File

@ -168,7 +168,7 @@ public class StubAsyncBlobStore implements AsyncBlobStore {
Blob object = realContents.get(key); Blob object = realContents.get(key);
Blob returnVal = blobProvider.create(copy(object.getMetadata())); Blob returnVal = blobProvider.create(copy(object.getMetadata()));
returnVal.setData(new ByteArrayInputStream((byte[]) object.getData())); returnVal.setPayload(object.getContent());
return returnVal; return returnVal;
} }
}; };
@ -512,7 +512,7 @@ public class StubAsyncBlobStore implements AsyncBlobStore {
new RuntimeException("bucketName not found: " + bucketName); new RuntimeException("bucketName not found: " + bucketName);
} }
try { try {
byte[] data = toByteArray(object.getData()); byte[] data = toByteArray(object.getPayload().getRawContent());
object.getMetadata().setSize(data.length); object.getMetadata().setSize(data.length);
MutableBlobMetadata newMd = copy(object.getMetadata()); MutableBlobMetadata newMd = copy(object.getMetadata());
newMd.setLastModified(new Date()); newMd.setLastModified(new Date());
@ -523,7 +523,7 @@ public class StubAsyncBlobStore implements AsyncBlobStore {
newMd.setContentType(object.getMetadata().getContentType()); newMd.setContentType(object.getMetadata().getContentType());
Blob blob = blobProvider.create(newMd); Blob blob = blobProvider.create(newMd);
blob.setData(data); blob.setPayload(data);
container.put(blob.getMetadata().getName(), blob); container.put(blob.getMetadata().getName(), blob);
// Set HTTP headers to match metadata // Set HTTP headers to match metadata
@ -592,7 +592,12 @@ public class StubAsyncBlobStore implements AsyncBlobStore {
Blob returnVal = copyBlob(object); Blob returnVal = copyBlob(object);
if (options.getRanges() != null && options.getRanges().size() > 0) { 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(); ByteArrayOutputStream out = new ByteArrayOutputStream();
for (String s : options.getRanges()) { for (String s : options.getRanges()) {
if (s.startsWith("-")) { 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.setContentLength(out.size());
returnVal.getMetadata().setSize(new Long(data.length)); returnVal.getMetadata().setSize(new Long(data.length));
} }
returnVal.setData(new ByteArrayInputStream((byte[]) returnVal.getData())); returnVal.setPayload(returnVal.getPayload());
return returnVal; return returnVal;
} }
}; };
@ -638,7 +643,7 @@ public class StubAsyncBlobStore implements AsyncBlobStore {
private Blob copyBlob(Blob object) { private Blob copyBlob(Blob object) {
Blob returnVal = blobProvider.create(copy(object.getMetadata())); Blob returnVal = blobProvider.create(copy(object.getMetadata()));
returnVal.setData(object.getData()); returnVal.setPayload(object.getPayload());
return returnVal; return returnVal;
} }

View File

@ -76,7 +76,7 @@ public class RetryOnNotFoundGetAllBlobsStrategyTest {
Future<Blob> futureObject = createMock(Future.class); Future<Blob> futureObject = createMock(Future.class);
Blob object = blobProvider.create(null); Blob object = blobProvider.create(null);
object.getMetadata().setName("key"); object.getMetadata().setName("key");
object.setData("goo"); object.setPayload("goo");
expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andThrow( expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andThrow(
new KeyNotFoundException()); new KeyNotFoundException());
context.getInstance(AsyncBlobStore.class).putBlob("container", object).get(); context.getInstance(AsyncBlobStore.class).putBlob("container", object).get();
@ -86,7 +86,7 @@ public class RetryOnNotFoundGetAllBlobsStrategyTest {
map.ifNotFoundRetryOtherwiseAddToSet("container", "key", futureObject, objects); map.ifNotFoundRetryOtherwiseAddToSet("container", "key", futureObject, objects);
// should have retried once // should have retried once
assert System.currentTimeMillis() >= time + map.requestRetryMilliseconds; 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); assert !objects.contains(null);
} }

View File

@ -26,6 +26,8 @@ package org.jclouds.http;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.io.File;
import java.io.InputStream;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
@ -48,7 +50,7 @@ public class HttpRequest extends HttpMessage implements Request<URI> {
private String method; private String method;
private URI endpoint; 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 * If the request is HEAD, this may change to GET due to redirects
*/ */
protected HttpRequest(String method, URI endPoint, Multimap<String, String> headers, protected HttpRequest(String method, URI endPoint, Multimap<String, String> headers,
@Nullable Object entity) { @Nullable Payload payload) {
this(method, endPoint); this(method, endPoint);
getHeaders().putAll(checkNotNull(headers, "headers")); getHeaders().putAll(checkNotNull(headers, "headers"));
setEntity(entity); setPayload(payload);
} }
public String getRequestLine() { public String getRequestLine() {
@ -104,16 +106,51 @@ public class HttpRequest extends HttpMessage implements Request<URI> {
return method; return method;
} }
public Object getEntity() { public Payload getPayload() {
return entity; return payload;
} }
public void setEntity(Object content) { /**
if (content instanceof String * {@inheritDoc}
&& this.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH) == null) { */
getHeaders().put(HttpHeaders.CONTENT_LENGTH, content.toString().getBytes().length + ""); 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() { public URI getEndpoint() {

View File

@ -26,7 +26,6 @@ package org.jclouds.http;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; 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 URI_PATTERN = Pattern.compile("([a-z0-9]+)://([^:]*):(.*)@(.*)");
public static final Pattern PATTERN_THAT_BREAKS_URI = Pattern.compile("[a-z0-9]+://.*/.*@.*"); // slash 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 @Resource
protected static Logger logger = Logger.NULL; protected static Logger logger = Logger.NULL;

View File

@ -21,22 +21,42 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.blobstore.functions.impl; package org.jclouds.http;
import javax.inject.Singleton; import java.io.IOException;
import java.io.InputStream;
import org.jclouds.blobstore.functions.CalculateSize; import java.io.OutputStream;
import org.jclouds.http.HttpUtils;
/** /**
*
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton public interface Payload {
public class CalculateSizeByLength implements CalculateSize {
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();
}

View File

@ -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();
}

View File

@ -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"));
}
}

View File

@ -23,7 +23,6 @@
*/ */
package org.jclouds.http; package org.jclouds.http;
import java.io.InputStream;
import java.util.Collections; import java.util.Collections;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -127,12 +126,7 @@ public class TransformingHttpCommandImpl<T> implements TransformingHttpCommand<T
} }
public boolean isReplayable() { public boolean isReplayable() {
Object content = request.getEntity(); return (request.getPayload() == null) ? true : request.getPayload().isRepeatable();
if (content != null && content instanceof InputStream) {
logger.warn("%1$s: InputStreams are not replayable", toString());
return false;
}
return true;
} }
/** /**
@ -140,7 +134,6 @@ public class TransformingHttpCommandImpl<T> implements TransformingHttpCommand<T
* IOUtils.closeQuietly(getResponse().getContent()); throw new * IOUtils.closeQuietly(getResponse().getContent()); throw new
* IllegalStateException("incorrect code for this operation: " + getResponse()); } } * IllegalStateException("incorrect code for this operation: " + getResponse()); } }
**/ **/
public HttpRequest getRequest() { public HttpRequest getRequest() {
return request; return request;
} }

View File

@ -23,6 +23,7 @@
*/ */
package org.jclouds.http.config; package org.jclouds.http.config;
import org.jclouds.concurrent.SingleThreaded;
import org.jclouds.http.HttpCommandExecutorService; import org.jclouds.http.HttpCommandExecutorService;
import org.jclouds.http.TransformingHttpCommandExecutorService; import org.jclouds.http.TransformingHttpCommandExecutorService;
import org.jclouds.http.TransformingHttpCommandExecutorServiceImpl; import org.jclouds.http.TransformingHttpCommandExecutorServiceImpl;
@ -39,6 +40,7 @@ import com.google.inject.Scopes;
* @author Adrian Cole * @author Adrian Cole
*/ */
@ConfiguresHttpCommandExecutorService @ConfiguresHttpCommandExecutorService
@SingleThreaded
public class JavaUrlHttpCommandExecutorServiceModule extends AbstractModule { public class JavaUrlHttpCommandExecutorServiceModule extends AbstractModule {
@Override @Override

View File

@ -43,14 +43,14 @@ public class ReturnStringIf200 implements Function<HttpResponse,String> {
public String apply(HttpResponse from) { public String apply(HttpResponse from) {
if (from.getStatusCode() == 200) { if (from.getStatusCode() == 200) {
InputStream entity = from.getContent(); InputStream payload = from.getContent();
if (entity == null) if (payload == null)
throw new HttpException("no content"); throw new HttpException("no content");
String toReturn = null; String toReturn = null;
try { try {
toReturn = Utils.toStringAndClose(entity); toReturn = Utils.toStringAndClose(payload);
} catch (IOException e) { } 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); from, toReturn), e);
} }
return toReturn; return toReturn;

View File

@ -38,6 +38,7 @@ import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.http.Payloads;
import org.jclouds.http.handlers.DelegatingErrorHandler; import org.jclouds.http.handlers.DelegatingErrorHandler;
import org.jclouds.http.handlers.DelegatingRetryHandler; import org.jclouds.http.handlers.DelegatingRetryHandler;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
@ -86,8 +87,9 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
filter.filter(request); filter.filter(request);
} }
logger.debug("Sending request %s: %s", request.hashCode(), request.getRequestLine()); logger.debug("Sending request %s: %s", request.hashCode(), request.getRequestLine());
if (request.getEntity() != null && wire.enabled()) if (request.getPayload() != null && wire.enabled())
request.setEntity(wire.output(request.getEntity())); request.setPayload(Payloads.newPayload(wire.output(request.getPayload()
.getRawContent())));
nativeRequest = convert(request); nativeRequest = convert(request);
HttpUtils.logRequest(headerLog, request, ">>"); HttpUtils.logRequest(headerLog, request, ">>");
response = invoke(nativeRequest); response = invoke(nativeRequest);

View File

@ -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;
}
}

View File

@ -23,12 +23,9 @@
*/ */
package org.jclouds.http.internal; package org.jclouds.http.internal;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.util.Map; import java.util.Map;
@ -133,23 +130,10 @@ public class JavaUrlHttpCommandExecutorService extends
} }
} }
connection.setRequestProperty(HttpHeaders.HOST, request.getEndpoint().getHost()); connection.setRequestProperty(HttpHeaders.HOST, request.getEndpoint().getHost());
if (request.getEntity() != null) { if (request.getPayload() != null) {
OutputStream out = connection.getOutputStream(); OutputStream out = connection.getOutputStream();
try { try {
if (request.getEntity() instanceof String) { request.getPayload().writeTo(out);
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());
}
} finally { } finally {
IOUtils.closeQuietly(out); IOUtils.closeQuietly(out);
} }

View File

@ -40,11 +40,11 @@ public class BaseHttpRequestOptions implements HttpRequestOptions {
protected Multimap<String, String> formParameters = LinkedHashMultimap.create(); protected Multimap<String, String> formParameters = LinkedHashMultimap.create();
protected Multimap<String, String> queryParameters = LinkedHashMultimap.create(); protected Multimap<String, String> queryParameters = LinkedHashMultimap.create();
protected Multimap<String, String> headers = LinkedHashMultimap.create(); protected Multimap<String, String> headers = LinkedHashMultimap.create();
protected String entity; protected String payload;
protected String pathSuffix; protected String pathSuffix;
public String buildStringEntity() { public String buildStringPayload() {
return entity; return payload;
} }
protected String getFirstMatrixOrNull(String string) { protected String getFirstMatrixOrNull(String string) {

View File

@ -169,7 +169,7 @@ public class GetOptions extends BaseHttpRequestOptions {
* Not compatible with {@link #ifETagDoesntMatch(byte[])} or {@link #ifModifiedSince(Date)} * Not compatible with {@link #ifETagDoesntMatch(byte[])} or {@link #ifModifiedSince(Date)}
* *
* @param eTag * @param eTag
* hash representing the entity * hash representing the payload
* @throws UnsupportedEncodingException * @throws UnsupportedEncodingException
* if there was a problem converting this into an S3 eTag string * 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 * For use in the request header: If-Match
* <p /> * <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). * return a 412 (precondition failed).
* *
* @see GetOptions#ifETagMatches(byte[]) * @see GetOptions#ifETagMatches(byte[])
@ -200,7 +200,7 @@ public class GetOptions extends BaseHttpRequestOptions {
* Not compatible with {@link #ifETagMatches(String)} or {@link #ifUnmodifiedSince(Date)} * Not compatible with {@link #ifETagMatches(String)} or {@link #ifUnmodifiedSince(Date)}
* *
* @param eTag * @param eTag
* hash representing the entity * hash representing the payload
* @throws UnsupportedEncodingException * @throws UnsupportedEncodingException
* if there was a problem converting this into an S3 eTag string * 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 * For use in the request header: If-None-Match
* <p /> * <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). * return a 304 (not modified).
* *
* @see GetOptions#ifETagDoesntMatch(byte[]) * @see GetOptions#ifETagDoesntMatch(byte[])

View File

@ -61,7 +61,7 @@ public interface HttpRequestOptions {
*/ */
Multimap<String, String> buildMatrixParameters(); Multimap<String, String> buildMatrixParameters();
String buildStringEntity(); String buildStringPayload();
String buildPathSuffix(); String buildPathSuffix();

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -26,7 +26,7 @@ package org.jclouds.rest;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
/** /**
* Adds an entity to a request. * Adds an payload to a request.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */

View File

@ -28,7 +28,7 @@ import java.util.Map;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
/** /**
* Builds the entity of a Post request. * Builds the payload of a Post request.
* *
* @author Adrian Cole * @author Adrian Cole
* *
@ -36,9 +36,9 @@ import org.jclouds.http.HttpRequest;
public interface MapBinder extends Binder { 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); public void bindToRequest(HttpRequest request, Map<String, String> postParams);

View File

@ -32,7 +32,7 @@ import java.lang.annotation.Target;
import org.jclouds.rest.Binder; 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. * it.
* *
* @author Adrian Cole * @author Adrian Cole
@ -42,7 +42,7 @@ import org.jclouds.rest.Binder;
public @interface BinderParam { public @interface BinderParam {
/** /**
* how to persist this entity. * how to persist this payload.
*/ */
Class<? extends Binder> value(); Class<? extends Binder> value();
} }

View File

@ -30,7 +30,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.Target; 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 * @author Adrian Cole
*/ */
@ -39,7 +39,7 @@ import java.lang.annotation.Target;
public @interface MapBinder { 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 * definition
*/ */
Class<? extends org.jclouds.rest.MapBinder> value(); Class<? extends org.jclouds.rest.MapBinder> value();

View File

@ -30,13 +30,13 @@ import java.lang.annotation.Retention;
import java.lang.annotation.Target; 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 * @author Adrian Cole
*/ */
@Target(PARAMETER) @Target(PARAMETER)
@Retention(RUNTIME) @Retention(RUNTIME)
public @interface MapEntityParam { public @interface MapPayloadParam {
/** /**
* The key used in a map passed to the {@link MapBinder} associated with the request. * The key used in a map passed to the {@link MapBinder} associated with the request.

View File

@ -43,7 +43,7 @@ import com.google.gson.Gson;
* @author Adrian Cole * @author Adrian Cole
* @since 4.0 * @since 4.0
*/ */
public class BindToJsonEntity implements MapBinder { public class BindToJsonPayload implements MapBinder {
@Inject @Inject
protected Gson gson; protected Gson gson;
@ -55,7 +55,7 @@ public class BindToJsonEntity implements MapBinder {
public void bindToRequest(HttpRequest request, Object toBind) { public void bindToRequest(HttpRequest request, Object toBind) {
checkState(gson != null, "Program error: gson should have been injected at this point"); checkState(gson != null, "Program error: gson should have been injected at this point");
String json = gson.toJson(toBind); String json = gson.toJson(toBind);
request.setEntity(json); request.setPayload(json);
request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH, request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH,
Collections.singletonList(json.getBytes().length + "")); Collections.singletonList(json.getBytes().length + ""));
request.getHeaders().replaceValues(HttpHeaders.CONTENT_TYPE, request.getHeaders().replaceValues(HttpHeaders.CONTENT_TYPE,

View File

@ -32,17 +32,17 @@ import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder; import org.jclouds.rest.Binder;
/** /**
* Adds an entity to a request. * Adds an payload to a request.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class BindToStringEntity implements Binder { public class BindToStringPayload implements Binder {
public void bindToRequest(HttpRequest request, Object entity) { public void bindToRequest(HttpRequest request, Object payload) {
String stringEntity = entity.toString(); String stringPayload = payload.toString();
if (request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE) == null) if (request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE) == null)
request.getHeaders().put(HttpHeaders.CONTENT_TYPE, "application/unknown"); request.getHeaders().put(HttpHeaders.CONTENT_TYPE, "application/unknown");
request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH,Collections.singletonList(stringEntity.getBytes().length + "")); request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH,Collections.singletonList(stringPayload.getBytes().length + ""));
request.setEntity(stringEntity); request.setPayload(stringPayload);
} }
} }

View File

@ -91,6 +91,8 @@ public class GeneratedHttpRequest<T> extends HttpRequest {
} }
public void addFormParam(String name, String... values) { public void addFormParam(String name, String... values) {
this.setEntity(processor.addFormParam(getEntity().toString(), name, values)); this
.setPayload(processor.addFormParam(getPayload().getRawContent().toString(), name,
values));
} }
} }

View File

@ -84,7 +84,7 @@ import org.jclouds.rest.annotations.FormParams;
import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.HostPrefixParam; import org.jclouds.rest.annotations.HostPrefixParam;
import org.jclouds.rest.annotations.MapBinder; 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.MatrixParams;
import org.jclouds.rest.annotations.OverrideRequestFilters; import org.jclouds.rest.annotations.OverrideRequestFilters;
import org.jclouds.rest.annotations.ParamParser; 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>>> methodToIndexOfParamToFormParamAnnotations = createMethodToIndexOfParamToAnnotation(FormParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToQueryParamAnnotations = createMethodToIndexOfParamToAnnotation(QueryParam.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>>> 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<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToParamParserAnnotations = createMethodToIndexOfParamToAnnotation(ParamParser.class);
private final Map<MethodKey, Method> delegationMap = Maps.newHashMap(); 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); Multimap<String, String> headers = buildHeaders(tokenValues.entries(), method, args);
String stringEntity = null; String stringPayload = null;
HttpRequestOptions options = findOptionsIn(method, args); HttpRequestOptions options = findOptionsIn(method, args);
if (options != null) { if (options != null) {
injector.injectMembers(options);// TODO test case injector.injectMembers(options);// TODO test case
@ -351,7 +351,7 @@ public class RestAnnotationProcessor<T> {
if (pathSuffix != null) { if (pathSuffix != null) {
builder.path(pathSuffix); builder.path(pathSuffix);
} }
stringEntity = options.buildStringEntity(); stringPayload = options.buildStringPayload();
} }
if (queryParams.size() > 0) { if (queryParams.size() > 0) {
@ -375,13 +375,13 @@ public class RestAnnotationProcessor<T> {
if (formParams.size() > 0) { if (formParams.size() > 0) {
if (headers.get(HttpHeaders.CONTENT_TYPE) != null) if (headers.get(HttpHeaders.CONTENT_TYPE) != null)
headers.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED); headers.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED);
request.setEntity(makeQueryLine(formParams, null, skips)); request.setPayload(makeQueryLine(formParams, null, skips));
} }
if (stringEntity != null) { if (stringPayload != null) {
request.setEntity(stringEntity); request.setPayload(stringPayload);
if (headers.get(HttpHeaders.CONTENT_LENGTH) != null) 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) if (headers.get(HttpHeaders.CONTENT_TYPE) != null)
headers.put(HttpHeaders.CONTENT_TYPE, "application/unknown"); headers.put(HttpHeaders.CONTENT_TYPE, "application/unknown");
} }
@ -669,7 +669,7 @@ public class RestAnnotationProcessor<T> {
return null; 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) { if (args != null) {
for (Object arg : args) { for (Object arg : args) {
if (arg instanceof Object[]) { if (arg instanceof Object[]) {
@ -737,11 +737,11 @@ public class RestAnnotationProcessor<T> {
} }
public void decorateRequest(GeneratedHttpRequest<T> request) { public void decorateRequest(GeneratedHttpRequest<T> request) {
org.jclouds.rest.MapBinder mapBinder = getMapEntityBinderOrNull(request.getJavaMethod(), org.jclouds.rest.MapBinder mapBinder = getMapPayloadBinderOrNull(request.getJavaMethod(),
request.getArgs()); request.getArgs());
Map<String, String> mapParams = buildPostParams(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 // MapPayloadBinder 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 also an PayloadBinder. If so, it can be used with or without
// parameters. // parameters.
if (mapBinder != null) { if (mapBinder != null) {
mapBinder.bindToRequest(request, mapParams); mapBinder.bindToRequest(request, mapParams);
@ -756,8 +756,8 @@ public class RestAnnotationProcessor<T> {
} }
}).entrySet()) { }).entrySet()) {
boolean shouldBreak = false; boolean shouldBreak = false;
BinderParam entityAnnotation = (BinderParam) entry.getValue().iterator().next(); BinderParam payloadAnnotation = (BinderParam) entry.getValue().iterator().next();
Binder binder = injector.getInstance(entityAnnotation.value()); Binder binder = injector.getInstance(payloadAnnotation.value());
if (request.getArgs().length != 0) { if (request.getArgs().length != 0) {
Object input; Object input;
Class<?> parameterType = request.getJavaMethod().getParameterTypes()[entry.getKey()]; Class<?> parameterType = request.getJavaMethod().getParameterTypes()[entry.getKey()];
@ -778,8 +778,8 @@ public class RestAnnotationProcessor<T> {
} else { } else {
input = request.getArgs()[entry.getKey()]; input = request.getArgs()[entry.getKey()];
if (input.getClass().isArray()) { if (input.getClass().isArray()) {
Object[] entityArray = (Object[]) input; Object[] payloadArray = (Object[]) input;
input = entityArray.length > 0 ? entityArray[0] : null; input = payloadArray.length > 0 ? payloadArray[0] : null;
} }
} }
if (input != null) { if (input != null) {
@ -789,27 +789,29 @@ public class RestAnnotationProcessor<T> {
break OUTER; break OUTER;
} }
} }
if (request.getMethod().equals("PUT") && request.getEntity() == null) { if (request.getMethod().equals("PUT") && request.getPayload() == null) {
request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH, request.getHeaders().replaceValues(HttpHeaders.CONTENT_LENGTH,
Collections.singletonList(0 + "")); 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, protected Map<Integer, Set<Annotation>> indexWithOnlyOneAnnotation(Method method,
String description, Map<Method, Map<Integer, Set<Annotation>>> toRefine) { 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>>() { .get(method), new Predicate<Set<Annotation>>() {
public boolean apply(Set<Annotation> input) { public boolean apply(Set<Annotation> input) {
return input.size() == 1; return input.size() == 1;
} }
}); });
if (indexToEntityAnnotation.size() > 1) { if (indexToPayloadAnnotation.size() > 1) {
throw new IllegalStateException(String.format( throw new IllegalStateException(String.format(
"You must not specify more than one %s annotation on: %s; found %s", description, "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) { private HttpRequestOptions findOptionsIn(Method method, Object... args) {
@ -1069,7 +1071,7 @@ public class RestAnnotationProcessor<T> {
for (Entry<Integer, Set<Annotation>> entry : indexToPathParam.entrySet()) { for (Entry<Integer, Set<Annotation>> entry : indexToPathParam.entrySet()) {
for (Annotation key : entry.getValue()) { for (Annotation key : entry.getValue()) {
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey()); Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
String paramKey = ((MapEntityParam) key).value(); String paramKey = ((MapPayloadParam) key).value();
String paramValue; String paramValue;
if (extractors != null && extractors.size() > 0) { if (extractors != null && extractors.size() > 0) {
ParamParser extractor = (ParamParser) extractors.iterator().next(); ParamParser extractor = (ParamParser) extractors.iterator().next();

View File

@ -41,12 +41,12 @@ import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.MapBinder; 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.RequestFilters;
import org.jclouds.rest.annotations.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.binders.BindMapToMatrixParams; import org.jclouds.rest.binders.BindMapToMatrixParams;
import org.jclouds.rest.binders.BindToJsonEntity; import org.jclouds.rest.binders.BindToJsonPayload;
import org.jclouds.rest.binders.BindToStringEntity; import org.jclouds.rest.binders.BindToStringPayload;
import org.jclouds.rest.internal.RestAnnotationProcessorTest.Localhost; import org.jclouds.rest.internal.RestAnnotationProcessorTest.Localhost;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -92,30 +92,30 @@ public interface IntegrationTestAsyncClient {
@PUT @PUT
@Path("objects/{id}") @Path("objects/{id}")
Future<String> upload(@PathParam("id") String id, Future<String> upload(@PathParam("id") String id,
@BinderParam(BindToStringEntity.class) String toPut); @BinderParam(BindToStringPayload.class) String toPut);
@POST @POST
@Path("objects/{id}") @Path("objects/{id}")
Future<String> post(@PathParam("id") String id, Future<String> post(@PathParam("id") String id,
@BinderParam(BindToStringEntity.class) String toPut); @BinderParam(BindToStringPayload.class) String toPut);
@POST @POST
@Path("objects/{id}") @Path("objects/{id}")
Future<String> postAsInputStream(@PathParam("id") String 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 @Override
public void bindToRequest(HttpRequest request, Object entity) { public void bindToRequest(HttpRequest request, Object payload) {
super.bindToRequest(request, entity); super.bindToRequest(request, payload);
request.setEntity(IOUtils.toInputStream(entity.toString())); request.setPayload(IOUtils.toInputStream(payload.toString()));
} }
} }
@POST @POST
@Path("objects/{id}") @Path("objects/{id}")
@MapBinder(BindToJsonEntity.class) @MapBinder(BindToJsonPayload.class)
Future<String> postJson(@PathParam("id") String id, @MapEntityParam("key") String toPut); Future<String> postJson(@PathParam("id") String id, @MapPayloadParam("key") String toPut);
@POST @POST
@Path("objects/{id}/action/{action}") @Path("objects/{id}/action/{action}")

View File

@ -27,7 +27,6 @@ import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull; import static org.testng.Assert.assertNull;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
@ -55,6 +54,7 @@ public abstract class RestClientTest<T> {
protected abstract Module createModule(); protected abstract Module createModule();
protected abstract void checkFilters(GeneratedHttpRequest<T> httpMethod); protected abstract void checkFilters(GeneratedHttpRequest<T> httpMethod);
protected abstract TypeLiteral<RestAnnotationProcessor<T>> createTypeLiteral(); protected abstract TypeLiteral<RestAnnotationProcessor<T>> createTypeLiteral();
@BeforeClass @BeforeClass
@ -63,18 +63,16 @@ public abstract class RestClientTest<T> {
injector = Guice.createInjector(createModule(), new RestModule(), new ExecutorServiceModule( injector = Guice.createInjector(createModule(), new RestModule(), new ExecutorServiceModule(
new WithinThreadExecutorService()), new JavaUrlHttpCommandExecutorServiceModule()); new WithinThreadExecutorService()), new JavaUrlHttpCommandExecutorServiceModule());
processor = injector.getInstance(Key processor = injector.getInstance(Key.get(createTypeLiteral()));
.get(createTypeLiteral()));
} }
protected void assertEntityEquals(GeneratedHttpRequest<T> httpMethod, String toMatch) protected void assertPayloadEquals(GeneratedHttpRequest<T> httpMethod, String toMatch)
throws IOException { throws IOException {
if (httpMethod.getEntity() == null) { if (httpMethod.getPayload() == null) {
assertNull(toMatch); assertNull(toMatch);
} else { } else {
String entity = (httpMethod.getEntity() instanceof String) ? httpMethod.getEntity() String payload = IOUtils.toString(httpMethod.getPayload().getContent());
.toString() : IOUtils.toString((InputStream) httpMethod.getEntity()); assertEquals(payload, toMatch);
assertEquals(entity, toMatch);
} }
} }
@ -82,8 +80,7 @@ public abstract class RestClientTest<T> {
assertEquals(HttpUtils.sortAndConcatHeadersIntoString(httpMethod.getHeaders()), toMatch); assertEquals(HttpUtils.sortAndConcatHeadersIntoString(httpMethod.getHeaders()), toMatch);
} }
protected void assertRequestLineEquals(GeneratedHttpRequest<T> httpMethod, protected void assertRequestLineEquals(GeneratedHttpRequest<T> httpMethod, String toMatch) {
String toMatch) {
assertEquals(httpMethod.getRequestLine(), toMatch); assertEquals(httpMethod.getRequestLine(), toMatch);
} }

View File

@ -88,7 +88,7 @@ import org.jclouds.rest.annotations.FormParams;
import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.HostPrefixParam; import org.jclouds.rest.annotations.HostPrefixParam;
import org.jclouds.rest.annotations.MapBinder; 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.MatrixParams;
import org.jclouds.rest.annotations.OverrideRequestFilters; import org.jclouds.rest.annotations.OverrideRequestFilters;
import org.jclouds.rest.annotations.ParamParser; 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.SkipEncoding;
import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.binders.BindMapToMatrixParams; import org.jclouds.rest.binders.BindMapToMatrixParams;
import org.jclouds.rest.binders.BindToJsonEntity; import org.jclouds.rest.binders.BindToJsonPayload;
import org.jclouds.rest.binders.BindToStringEntity; import org.jclouds.rest.binders.BindToStringPayload;
import org.jclouds.rest.config.RestModule; import org.jclouds.rest.config.RestModule;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;
import org.mortbay.jetty.HttpHeaders; import org.mortbay.jetty.HttpHeaders;
@ -206,7 +206,7 @@ public class RestAnnotationProcessorTest {
} }
@Endpoint(Localhost.class) @Endpoint(Localhost.class)
public interface TestEntityParamVarargs { public interface TestPayloadParamVarargs {
@POST @POST
public void varargs(HttpRequestOptions... options); public void varargs(HttpRequestOptions... options);
@ -215,19 +215,19 @@ public class RestAnnotationProcessorTest {
} }
public void testHttpRequestOptionsEntityParam() throws SecurityException, NoSuchMethodException { public void testHttpRequestOptionsPayloadParam() throws SecurityException, NoSuchMethodException {
Method method = TestEntityParamVarargs.class.getMethod("post", HttpRequestOptions.class); Method method = TestPayloadParamVarargs.class.getMethod("post", HttpRequestOptions.class);
verifyTestPostOptions(method); verifyTestPostOptions(method);
} }
public void testEntityParamVarargs() throws SecurityException, NoSuchMethodException { public void testPayloadParamVarargs() throws SecurityException, NoSuchMethodException {
Method method = TestEntityParamVarargs.class.getMethod("varargs", Array.newInstance( Method method = TestPayloadParamVarargs.class.getMethod("varargs", Array.newInstance(
HttpRequestOptions.class, 0).getClass()); HttpRequestOptions.class, 0).getClass());
verifyTestPostOptions(method); verifyTestPostOptions(method);
} }
private void verifyTestPostOptions(Method method) { private void verifyTestPostOptions(Method method) {
GeneratedHttpRequest<?> httpMethod = factory(TestEntityParamVarargs.class).createRequest( GeneratedHttpRequest<?> httpMethod = factory(TestPayloadParamVarargs.class).createRequest(
method, new Object[] { new HttpRequestOptions() { method, new Object[] { new HttpRequestOptions() {
public Multimap<String, String> buildMatrixParameters() { public Multimap<String, String> buildMatrixParameters() {
@ -250,7 +250,7 @@ public class RestAnnotationProcessorTest {
return LinkedHashMultimap.create(); return LinkedHashMultimap.create();
} }
public String buildStringEntity() { public String buildStringPayload() {
return "fooya"; return "fooya";
} }
@ -263,7 +263,7 @@ public class RestAnnotationProcessorTest {
.singletonList("application/unknown")); .singletonList("application/unknown"));
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList("fooya".getBytes().length + "")); .singletonList("fooya".getBytes().length + ""));
assertEquals(httpMethod.getEntity(), "fooya"); assertEquals(httpMethod.getPayload().toString(), "fooya");
} }
@Endpoint(Localhost.class) @Endpoint(Localhost.class)
@ -338,23 +338,23 @@ public class RestAnnotationProcessorTest {
@Endpoint(Localhost.class) @Endpoint(Localhost.class)
public class TestPost { public class TestPost {
@POST @POST
public void post(@BinderParam(BindToStringEntity.class) String content) { public void post(@BinderParam(BindToStringPayload.class) String content) {
} }
@POST @POST
public void postAsJson(@BinderParam(BindToJsonEntity.class) String content) { public void postAsJson(@BinderParam(BindToJsonPayload.class) String content) {
} }
@POST @POST
@Path("{foo}") @Path("{foo}")
public void postWithPath(@PathParam("foo") @MapEntityParam("fooble") String path, public void postWithPath(@PathParam("foo") @MapPayloadParam("fooble") String path,
MapBinder content) { MapBinder content) {
} }
@POST @POST
@Path("{foo}") @Path("{foo}")
@MapBinder(BindToJsonEntity.class) @MapBinder(BindToJsonPayload.class)
public void postWithMethodBinder(@PathParam("foo") @MapEntityParam("fooble") String path) { public void postWithMethodBinder(@PathParam("foo") @MapPayloadParam("fooble") String path) {
} }
} }
@ -370,7 +370,7 @@ public class RestAnnotationProcessorTest {
.singletonList("application/unknown")); .singletonList("application/unknown"));
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList("data".getBytes().length + "")); .singletonList("data".getBytes().length + ""));
assertEquals(httpMethod.getEntity(), "data"); assertEquals(httpMethod.getPayload().toString(), "data");
} }
public void testCreatePostJsonRequest() throws SecurityException, NoSuchMethodException { public void testCreatePostJsonRequest() throws SecurityException, NoSuchMethodException {
@ -385,7 +385,7 @@ public class RestAnnotationProcessorTest {
.singletonList("application/json")); .singletonList("application/json"));
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList("\"data\"".getBytes().length + "")); .singletonList("\"data\"".getBytes().length + ""));
assertEquals(httpMethod.getEntity(), "\"data\""); assertEquals(httpMethod.getPayload().toString(), "\"data\"");
} }
public void testCreatePostWithPathRequest() throws SecurityException, NoSuchMethodException { public void testCreatePostWithPathRequest() throws SecurityException, NoSuchMethodException {
@ -393,7 +393,7 @@ public class RestAnnotationProcessorTest {
GeneratedHttpRequest<?> httpMethod = factory(TestPost.class).createRequest(method, GeneratedHttpRequest<?> httpMethod = factory(TestPost.class).createRequest(method,
new Object[] { "data", new org.jclouds.rest.MapBinder() { new Object[] { "data", new org.jclouds.rest.MapBinder() {
public void bindToRequest(HttpRequest request, Map<String, String> postParams) { 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) { public void bindToRequest(HttpRequest request, Object toBind) {
@ -404,7 +404,7 @@ public class RestAnnotationProcessorTest {
assertEquals(httpMethod.getEndpoint().getPath(), "/data"); assertEquals(httpMethod.getEndpoint().getPath(), "/data");
assertEquals(httpMethod.getMethod(), HttpMethod.POST); assertEquals(httpMethod.getMethod(), HttpMethod.POST);
assertEquals(httpMethod.getHeaders().size(), 1); assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getEntity(), "data"); assertEquals(httpMethod.getPayload().toString(), "data");
} }
public void testCreatePostWithMethodBinder() throws SecurityException, NoSuchMethodException { public void testCreatePostWithMethodBinder() throws SecurityException, NoSuchMethodException {
@ -420,30 +420,30 @@ public class RestAnnotationProcessorTest {
String expected = "{\"fooble\":\"data\"}"; String expected = "{\"fooble\":\"data\"}";
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList(expected.getBytes().length + "")); .singletonList(expected.getBytes().length + ""));
assertEquals(httpMethod.getEntity(), expected); assertEquals(httpMethod.getPayload().toString(), expected);
} }
@Endpoint(Localhost.class) @Endpoint(Localhost.class)
public class TestPut { public class TestPut {
@PUT @PUT
@Path("{foo}") @Path("{foo}")
@MapBinder(BindToJsonEntity.class) @MapBinder(BindToJsonPayload.class)
public void putWithMethodBinder(@PathParam("foo") @MapEntityParam("fooble") String path) { public void putWithMethodBinder(@PathParam("foo") @MapPayloadParam("fooble") String path) {
} }
@PUT @PUT
@Path("{foo}") @Path("{foo}")
@Produces(MediaType.TEXT_PLAIN) @Produces(MediaType.TEXT_PLAIN)
public void putWithMethodBinderProduces( public void putWithMethodBinderProduces(
@PathParam("foo") @BinderParam(BindToStringEntity.class) String path) { @PathParam("foo") @BinderParam(BindToStringPayload.class) String path) {
} }
@PUT @PUT
@Path("{foo}") @Path("{foo}")
@MapBinder(BindToJsonEntity.class) @MapBinder(BindToJsonPayload.class)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public void putWithMethodBinderConsumes( 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\"}"; String expected = "{\"fooble\":\"data\"}";
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList(expected.getBytes().length + "")); .singletonList(expected.getBytes().length + ""));
assertEquals(httpMethod.getEntity(), expected); assertEquals(httpMethod.getPayload().toString(), expected);
} }
public void testCreatePutWithMethodProduces() throws SecurityException, NoSuchMethodException { public void testCreatePutWithMethodProduces() throws SecurityException, NoSuchMethodException {
@ -475,7 +475,7 @@ public class RestAnnotationProcessorTest {
.singletonList("text/plain")); .singletonList("text/plain"));
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList("data".getBytes().length + "")); .singletonList("data".getBytes().length + ""));
assertEquals(httpMethod.getEntity(), "data"); assertEquals(httpMethod.getPayload().toString(), "data");
} }
public void testCreatePutWithMethodConsumes() throws SecurityException, NoSuchMethodException { public void testCreatePutWithMethodConsumes() throws SecurityException, NoSuchMethodException {
@ -493,7 +493,7 @@ public class RestAnnotationProcessorTest {
String expected = "{\"fooble\":\"data\"}"; String expected = "{\"fooble\":\"data\"}";
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList(expected.getBytes().length + "")); .singletonList(expected.getBytes().length + ""));
assertEquals(httpMethod.getEntity(), expected); assertEquals(httpMethod.getPayload().toString(), expected);
} }
static class TestRequestFilter1 implements HttpRequestFilter { static class TestRequestFilter1 implements HttpRequestFilter {
@ -589,7 +589,7 @@ public class RestAnnotationProcessorTest {
assertRequestLineEquals(httpMethod, assertRequestLineEquals(httpMethod,
"GET http://localhost:8080/v1/ralphie/1/localhost HTTP/1.1"); "GET http://localhost:8080/v1/ralphie/1/localhost HTTP/1.1");
assertHeadersEqual(httpMethod, ""); assertHeadersEqual(httpMethod, "");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
} }
@Endpoint(Localhost.class) @Endpoint(Localhost.class)
@ -650,7 +650,7 @@ public class RestAnnotationProcessorTest {
new Object[] { "localhost" }); new Object[] { "localhost" });
assertRequestLineEquals(httpMethod, "GET http://localhost:8080/l HTTP/1.1"); assertRequestLineEquals(httpMethod, "GET http://localhost:8080/l HTTP/1.1");
assertHeadersEqual(httpMethod, ""); assertHeadersEqual(httpMethod, "");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
} }
@Test @Test
@ -661,7 +661,7 @@ public class RestAnnotationProcessorTest {
"localhost"); "localhost");
assertRequestLineEquals(httpMethod, "GET http://localhost:8080/?one=l HTTP/1.1"); assertRequestLineEquals(httpMethod, "GET http://localhost:8080/?one=l HTTP/1.1");
assertHeadersEqual(httpMethod, ""); assertHeadersEqual(httpMethod, "");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
} }
@Test @Test
@ -672,7 +672,7 @@ public class RestAnnotationProcessorTest {
new Object[] { "localhost" }); new Object[] { "localhost" });
assertRequestLineEquals(httpMethod, "GET http://localhost:8080/;one=l HTTP/1.1"); assertRequestLineEquals(httpMethod, "GET http://localhost:8080/;one=l HTTP/1.1");
assertHeadersEqual(httpMethod, ""); assertHeadersEqual(httpMethod, "");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
} }
@Test @Test
@ -684,7 +684,7 @@ public class RestAnnotationProcessorTest {
assertRequestLineEquals(httpMethod, "POST http://localhost:8080/ HTTP/1.1"); assertRequestLineEquals(httpMethod, "POST http://localhost:8080/ HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
"Content-Length: 5\nContent-Type: application/x-www-form-urlencoded\n"); "Content-Length: 5\nContent-Type: application/x-www-form-urlencoded\n");
assertEntityEquals(httpMethod, "one=l"); assertPayloadEquals(httpMethod, "one=l");
} }
@Test @Test
@ -1149,7 +1149,7 @@ public class RestAnnotationProcessorTest {
@PUT @PUT
@Path("/{id}") @Path("/{id}")
public Future<String> put(@PathParam("id") @ParamParser(FirstCharacter.class) String id, public Future<String> put(@PathParam("id") @ParamParser(FirstCharacter.class) String id,
@BinderParam(BindToStringEntity.class) String payload) { @BinderParam(BindToStringPayload.class) String payload) {
return null; return null;
} }
@ -1165,7 +1165,7 @@ public class RestAnnotationProcessorTest {
@Headers(keys = "foo", values = "--{id}--") @Headers(keys = "foo", values = "--{id}--")
@ResponseParser(ReturnTrueIf2xx.class) @ResponseParser(ReturnTrueIf2xx.class)
public Future<String> putHeader(@PathParam("id") String id, public Future<String> putHeader(@PathParam("id") String id,
@BinderParam(BindToStringEntity.class) String payload) { @BinderParam(BindToStringPayload.class) String payload) {
return null; return null;
} }
} }
@ -1221,7 +1221,7 @@ public class RestAnnotationProcessorTest {
new Object[] { "1", options }); new Object[] { "1", options });
assertRequestLineEquals(httpMethod, "GET http://localhost:8080/1?prefix=1 HTTP/1.1"); assertRequestLineEquals(httpMethod, "GET http://localhost:8080/1?prefix=1 HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: localhost\n"); assertHeadersEqual(httpMethod, "Host: localhost\n");
assertEntityEquals(httpMethod, null); assertPayloadEquals(httpMethod, null);
} }
public void testCreateGetQuery() throws SecurityException, NoSuchMethodException { public void testCreateGetQuery() throws SecurityException, NoSuchMethodException {
@ -1247,16 +1247,16 @@ public class RestAnnotationProcessorTest {
} }
@Endpoint(Localhost.class) @Endpoint(Localhost.class)
public class EntityOptions extends BaseHttpRequestOptions { public class PayloadOptions extends BaseHttpRequestOptions {
@Override @Override
public String buildStringEntity() { public String buildStringPayload() {
return "foo"; return "foo";
} }
} }
public void testCreateGetOptionsThatProducesEntity() throws SecurityException, public void testCreateGetOptionsThatProducesPayload() throws SecurityException,
NoSuchMethodException { NoSuchMethodException {
EntityOptions options = new EntityOptions(); PayloadOptions options = new PayloadOptions();
Method method = TestRequest.class.getMethod("putOptions", String.class, Method method = TestRequest.class.getMethod("putOptions", String.class,
HttpRequestOptions.class); HttpRequestOptions.class);
GeneratedHttpRequest<?> httpMethod = factory(TestRequest.class).createRequest(method, GeneratedHttpRequest<?> httpMethod = factory(TestRequest.class).createRequest(method,
@ -1267,7 +1267,7 @@ public class RestAnnotationProcessorTest {
assertEquals(httpMethod.getHeaders().size(), 3); assertEquals(httpMethod.getHeaders().size(), 3);
assertEquals(httpMethod.getHeaders().get(HttpHeaders.HOST), Collections assertEquals(httpMethod.getHeaders().get(HttpHeaders.HOST), Collections
.singletonList("localhost")); .singletonList("localhost"));
assertEquals(httpMethod.getEntity(), "foo"); assertEquals(httpMethod.getPayload().toString(), "foo");
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections
.singletonList("application/unknown")); .singletonList("application/unknown"));
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
@ -1307,7 +1307,7 @@ public class RestAnnotationProcessorTest {
.singletonList("application/unknown")); .singletonList("application/unknown"));
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList("data".getBytes().length + "")); .singletonList("data".getBytes().length + ""));
assertEquals(httpMethod.getEntity(), "data"); assertEquals(httpMethod.getPayload().toString(), "data");
} }
public void testCreatePutHeader() throws SecurityException, NoSuchMethodException { public void testCreatePutHeader() throws SecurityException, NoSuchMethodException {
@ -1323,7 +1323,7 @@ public class RestAnnotationProcessorTest {
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList("data".getBytes().length + "")); .singletonList("data".getBytes().length + ""));
assertEquals(httpMethod.getHeaders().get("foo"), Collections.singletonList("--1--")); assertEquals(httpMethod.getHeaders().get("foo"), Collections.singletonList("--1--"));
assertEquals(httpMethod.getEntity(), "data"); assertEquals(httpMethod.getPayload().toString(), "data");
} }
@Endpoint(Localhost.class) @Endpoint(Localhost.class)
@ -1480,28 +1480,28 @@ public class RestAnnotationProcessorTest {
} }
@Endpoint(Localhost.class) @Endpoint(Localhost.class)
public interface TestEntity { public interface TestPayload {
@PUT @PUT
public void put(@BinderParam(BindToStringEntity.class) String content); public void put(@BinderParam(BindToStringPayload.class) String content);
@PUT @PUT
@Path("{foo}") @Path("{foo}")
public Future<Void> putWithPath(@PathParam("foo") String path, public Future<Void> putWithPath(@PathParam("foo") String path,
@BinderParam(BindToStringEntity.class) String content); @BinderParam(BindToStringPayload.class) String content);
@PUT @PUT
public void twoEntities(@BinderParam(BindToStringEntity.class) String entity1, public void twoEntities(@BinderParam(BindToStringPayload.class) String payload1,
@BinderParam(BindToStringEntity.class) String entity2); @BinderParam(BindToStringPayload.class) String payload2);
} }
@Test @Test
public void testPut() throws SecurityException, NoSuchMethodException { public void testPut() throws SecurityException, NoSuchMethodException {
RestAnnotationProcessor<TestEntity> processor = factory(TestEntity.class); RestAnnotationProcessor<TestPayload> processor = factory(TestPayload.class);
Method method = TestEntity.class.getMethod("put", String.class); Method method = TestPayload.class.getMethod("put", String.class);
GeneratedHttpRequest<TestEntity> request = new GeneratedHttpRequest<TestEntity>("GET", URI GeneratedHttpRequest<TestPayload> request = new GeneratedHttpRequest<TestPayload>("GET", URI
.create("http://localhost"), processor, TestEntity.class, method, "test"); .create("http://localhost"), processor, TestPayload.class, method, "test");
processor.decorateRequest(request); processor.decorateRequest(request);
assertEquals(request.getEntity(), "test"); assertEquals(request.getPayload().toString(), "test");
assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections
.singletonList("application/unknown")); .singletonList("application/unknown"));
assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
@ -1513,12 +1513,12 @@ public class RestAnnotationProcessorTest {
@Test @Test
public void putWithPath() throws SecurityException, NoSuchMethodException { public void putWithPath() throws SecurityException, NoSuchMethodException {
RestAnnotationProcessor<TestEntity> processor = factory(TestEntity.class); RestAnnotationProcessor<TestPayload> processor = factory(TestPayload.class);
Method method = TestEntity.class.getMethod("putWithPath", String.class, String.class); Method method = TestPayload.class.getMethod("putWithPath", String.class, String.class);
GeneratedHttpRequest<TestEntity> request = new GeneratedHttpRequest<TestEntity>("GET", URI GeneratedHttpRequest<TestPayload> request = new GeneratedHttpRequest<TestPayload>("GET", URI
.create("http://localhost"), processor, TestEntity.class, method, "rabble", "test"); .create("http://localhost"), processor, TestPayload.class, method, "rabble", "test");
processor.decorateRequest(request); processor.decorateRequest(request);
assertEquals(request.getEntity(), "test"); assertEquals(request.getPayload().toString(), "test");
assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections
.singletonList("application/unknown")); .singletonList("application/unknown"));
assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections assertEquals(request.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
@ -1566,7 +1566,7 @@ public class RestAnnotationProcessorTest {
UnsupportedEncodingException { UnsupportedEncodingException {
Method oneForm = TestFormReplace.class.getMethod("twoForm", String.class); Method oneForm = TestFormReplace.class.getMethod("twoForm", String.class);
String form = factory(TestFormReplace.class).createRequest(oneForm, new Object[] { "robot" }) String form = factory(TestFormReplace.class).createRequest(oneForm, new Object[] { "robot" })
.getEntity().toString(); .getPayload().toString().toString();
assertEquals(form, "slash=/robot&hyphen=-robot"); assertEquals(form, "slash=/robot&hyphen=-robot");
} }
@ -1584,7 +1584,7 @@ public class RestAnnotationProcessorTest {
UnsupportedEncodingException { UnsupportedEncodingException {
Method oneForm = TestClassForm.class.getMethod("oneForm", String.class); Method oneForm = TestClassForm.class.getMethod("oneForm", String.class);
String form = factory(TestClassForm.class).createRequest(oneForm, new Object[] { "robot" }) String form = factory(TestClassForm.class).createRequest(oneForm, new Object[] { "robot" })
.getEntity().toString(); .getPayload().toString().toString();
assertEquals(form, "x-amz-copy-source=/robot"); assertEquals(form, "x-amz-copy-source=/robot");
} }
@ -1593,7 +1593,7 @@ public class RestAnnotationProcessorTest {
UnsupportedEncodingException { UnsupportedEncodingException {
Method oneForm = TestFormReplace.class.getMethod("oneForm", String.class); Method oneForm = TestFormReplace.class.getMethod("oneForm", String.class);
String form = factory(TestFormReplace.class).createRequest(oneForm, new Object[] { "robot" }) String form = factory(TestFormReplace.class).createRequest(oneForm, new Object[] { "robot" })
.getEntity().toString(); .getPayload().toString().toString();
assertEquals(form, "x-amz-copy-source=/robot"); assertEquals(form, "x-amz-copy-source=/robot");
} }
@ -1602,7 +1602,7 @@ public class RestAnnotationProcessorTest {
UnsupportedEncodingException { UnsupportedEncodingException {
Method twoForms = TestFormReplace.class.getMethod("twoForms", String.class, String.class); Method twoForms = TestFormReplace.class.getMethod("twoForms", String.class, String.class);
String form = factory(TestFormReplace.class).createRequest(twoForms, 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"); assertEquals(form, "x-amz-copy-source=/robot/eggs");
} }
@ -1612,7 +1612,7 @@ public class RestAnnotationProcessorTest {
Method twoFormsOutOfOrder = TestFormReplace.class.getMethod("twoFormsOutOfOrder", Method twoFormsOutOfOrder = TestFormReplace.class.getMethod("twoFormsOutOfOrder",
String.class, String.class); String.class, String.class);
String form = factory(TestFormReplace.class).createRequest(twoFormsOutOfOrder, 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"); 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 { throws IOException {
if (httpMethod.getEntity() == null) { if (httpMethod.getPayload() == null) {
assertNull(toMatch); assertNull(toMatch);
} else { } else {
String entity = (httpMethod.getEntity() instanceof String) ? httpMethod.getEntity() String payload = IOUtils.toString(httpMethod.getPayload().getContent());
.toString() : IOUtils.toString((InputStream) httpMethod.getEntity()); assertEquals(payload, toMatch);
assertEquals(entity, toMatch);
} }
} }

View File

@ -69,7 +69,7 @@ public class StoreTweetsController extends HttpServlet {
Blob to = map.newBlob(); Blob to = map.newBlob();
to.getMetadata().setContentType(MediaType.TEXT_PLAIN); to.getMetadata().setContentType(MediaType.TEXT_PLAIN);
to.getMetadata().setName(from.getId() + ""); to.getMetadata().setName(from.getId() + "");
to.setData(from.getText()); to.setPayload(from.getText());
to.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, to.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME,
from.getUser().getScreenName()); from.getUser().getScreenName());
return to; return to;

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