From 306bb0ebdee85635162cce8706f30cb36df3aa97 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Fri, 11 Jun 2010 19:02:19 -0700 Subject: [PATCH] Issue 191: started cookbook support; refactored multipart form code --- .../atmosonline/saas/domain/AtmosObject.java | 2 +- .../saas/domain/MutableContentMetadata.java | 2 +- .../org/jclouds/aws/s3/domain/S3Object.java | 2 +- .../azure/storage/blob/domain/AzureBlob.java | 2 +- .../blobstore/TransientAsyncBlobStore.java | 2 +- .../binders/BindBlobToMultipartForm.java | 4 +- .../blobstore/domain/internal/BlobImpl.java | 2 +- .../org/jclouds/chef/ChefAsyncClient.java | 21 ++++- .../java/org/jclouds/chef/ChefClient.java | 6 ++ .../chef/filters/SignedHeaderAuth.java | 4 +- .../org/jclouds/chef/ChefClientLiveTest.java | 28 ++++++ .../java/org/jclouds/http/HttpRequest.java | 4 +- .../java/org/jclouds/http/MultipartForm.java | 90 ++++++++++++++----- .../main/java/org/jclouds/http/Payload.java | 12 +-- .../internal/BasePayloadEnclosingImpl.java | 4 +- .../http/payloads/ByteArrayPayload.java | 2 +- .../jclouds/http/payloads/FilePayload.java | 4 +- .../http/payloads/InputStreamPayload.java | 6 +- .../jclouds/http/payloads/StringPayload.java | 2 +- .../internal/RestAnnotationProcessor.java | 4 +- .../org/jclouds/http/MultipartFormTest.java | 16 ++-- .../java/org/jclouds/rest/RestClientTest.java | 2 +- .../internal/RestAnnotationProcessorTest.java | 2 +- .../AsyncGaeHttpCommandExecutorService.java | 2 +- .../gae/GaeHttpCommandExecutorService.java | 2 +- .../mezeo/pcs2/binders/BindDataToPayload.java | 2 +- .../binders/BindCFObjectToPayloadTest.java | 4 +- 27 files changed, 170 insertions(+), 63 deletions(-) diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/domain/AtmosObject.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/domain/AtmosObject.java index 8a19383814..9928c6a18b 100644 --- a/atmos/src/main/java/org/jclouds/atmosonline/saas/domain/AtmosObject.java +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/domain/AtmosObject.java @@ -25,7 +25,7 @@ import com.google.inject.internal.Nullable; /** * Amazon Atmos is designed to store objects. Objects are stored in buckets and consist of a - * {@link ObjectMetadataAtmosObject#getContent() value}, a {@link ObjectMetadata#getKey key}, + * {@link ObjectMetadataAtmosObject#getInput() value}, a {@link ObjectMetadata#getKey key}, * {@link ObjectMetadata#getUserMetadata() metadata}, and an access control policy. * * @author Adrian Cole diff --git a/atmos/src/main/java/org/jclouds/atmosonline/saas/domain/MutableContentMetadata.java b/atmos/src/main/java/org/jclouds/atmosonline/saas/domain/MutableContentMetadata.java index cf42d85d5b..948f293dce 100644 --- a/atmos/src/main/java/org/jclouds/atmosonline/saas/domain/MutableContentMetadata.java +++ b/atmos/src/main/java/org/jclouds/atmosonline/saas/domain/MutableContentMetadata.java @@ -46,7 +46,7 @@ public class MutableContentMetadata { * Chunking is only used when org.jclouds.http.GetOptions is called with options like tail, * range, or startAt. * - * @return the length in bytes that can be be obtained from {@link #getContent()} + * @return the length in bytes that can be be obtained from {@link #getInput()} * @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH * @see GetObjectOptions */ diff --git a/aws/core/src/main/java/org/jclouds/aws/s3/domain/S3Object.java b/aws/core/src/main/java/org/jclouds/aws/s3/domain/S3Object.java index 43e19e1b49..ae94c3c368 100644 --- a/aws/core/src/main/java/org/jclouds/aws/s3/domain/S3Object.java +++ b/aws/core/src/main/java/org/jclouds/aws/s3/domain/S3Object.java @@ -25,7 +25,7 @@ import com.google.inject.internal.Nullable; /** * Amazon S3 is designed to store objects. Objects are stored in buckets and consist of a - * {@link ObjectMetadataS3Object#getContent() value}, a {@link ObjectMetadata#getKey key}, + * {@link ObjectMetadataS3Object#getInput() value}, a {@link ObjectMetadata#getKey key}, * {@link ObjectMetadata#getUserMetadata() metadata}, and an access control policy. * * @author Adrian Cole diff --git a/azure/src/main/java/org/jclouds/azure/storage/blob/domain/AzureBlob.java b/azure/src/main/java/org/jclouds/azure/storage/blob/domain/AzureBlob.java index 9b7f02cdb1..b9c5661610 100644 --- a/azure/src/main/java/org/jclouds/azure/storage/blob/domain/AzureBlob.java +++ b/azure/src/main/java/org/jclouds/azure/storage/blob/domain/AzureBlob.java @@ -27,7 +27,7 @@ import com.google.common.collect.Multimap; /** * Amazon S3 is designed to store objects. Objects are stored in buckets and consist of a - * {@link ObjectPropertiesBlob#getContent() value}, a {@link ObjectProperties#getKey key}, + * {@link ObjectPropertiesBlob#getInput() value}, a {@link ObjectProperties#getKey key}, * {@link ObjectProperties#getUserProperties() metadata}, and an access control policy. * * @author Adrian Cole diff --git a/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java b/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java index 1d842d6021..68ceae04cb 100755 --- a/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java @@ -577,7 +577,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore { if (options.getRanges() != null && options.getRanges().size() > 0) { byte[] data; try { - data = ByteStreams.toByteArray(returnVal.getPayload().getContent()); + data = ByteStreams.toByteArray(returnVal.getPayload().getInput()); } catch (IOException e) { return immediateFailedFuture(new RuntimeException(e)); } diff --git a/blobstore/src/main/java/org/jclouds/blobstore/binders/BindBlobToMultipartForm.java b/blobstore/src/main/java/org/jclouds/blobstore/binders/BindBlobToMultipartForm.java index 923c86f36e..e32580a3a9 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/binders/BindBlobToMultipartForm.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/binders/BindBlobToMultipartForm.java @@ -41,9 +41,9 @@ public class BindBlobToMultipartForm implements Binder { .getMetadata().getContentType()); MultipartForm form = new MultipartForm(BOUNDARY, part); - request.setPayload(form.getData()); + request.setPayload(form.getInput()); request.getHeaders().put(HttpHeaders.CONTENT_TYPE, "multipart/form-data; boundary=" + BOUNDARY); - request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, form.getSize() + ""); + request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, form.calculateSize() + ""); } } diff --git a/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/BlobImpl.java b/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/BlobImpl.java index 1af7ffb746..8f12bc8929 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/BlobImpl.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/domain/internal/BlobImpl.java @@ -33,7 +33,7 @@ import com.google.common.collect.Multimap; /** * Value type for an HTTP Blob service. Blobs are stored in {@link StorageMetadata containers} and consist - * of a {@link org.jclouds.blobstore.domain.Value#getContent() value}, a {@link Blob#getKey key and + * of a {@link org.jclouds.blobstore.domain.Value#getInput() value}, a {@link Blob#getKey key and * * @link Blob.Metadata#getUserMetadata() metadata} * diff --git a/chef/src/main/java/org/jclouds/chef/ChefAsyncClient.java b/chef/src/main/java/org/jclouds/chef/ChefAsyncClient.java index ed56488758..dcd1deb797 100644 --- a/chef/src/main/java/org/jclouds/chef/ChefAsyncClient.java +++ b/chef/src/main/java/org/jclouds/chef/ChefAsyncClient.java @@ -23,10 +23,12 @@ */ package org.jclouds.chef; +import java.io.File; import java.util.Set; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; +import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.HEAD; import javax.ws.rs.POST; @@ -43,6 +45,7 @@ import org.jclouds.chef.functions.ParseKeySetFromJson; import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.PartParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; @@ -70,7 +73,23 @@ public interface ChefAsyncClient { ListenableFuture listCookbooks(); /** - * @see ChefClient#createClientanization + * @see ChefClient#createCookbook(String,File) + */ + @POST + @Path("cookbooks") + ListenableFuture createCookbook(@FormParam("name") String name, + @PartParam(name = "file", contentType = MediaType.APPLICATION_OCTET_STREAM) File content); + + /** + * @see ChefClient#createCookbook(String,byte[]) + */ + @POST + @Path("cookbooks") + ListenableFuture createCookbook(@FormParam("name") String name, + @PartParam(name = "file", contentType = MediaType.APPLICATION_OCTET_STREAM) byte[] content); + + /** + * @see ChefClient#createClient */ @POST @Path("clients") diff --git a/chef/src/main/java/org/jclouds/chef/ChefClient.java b/chef/src/main/java/org/jclouds/chef/ChefClient.java index 1e285af99e..bcfdd8ec51 100644 --- a/chef/src/main/java/org/jclouds/chef/ChefClient.java +++ b/chef/src/main/java/org/jclouds/chef/ChefClient.java @@ -41,6 +41,8 @@ */ package org.jclouds.chef; +import java.io.File; +import java.io.InputStream; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -60,6 +62,10 @@ import org.jclouds.rest.AuthorizationException; public interface ChefClient { String listCookbooks(); + String createCookbook(String name, File content); + + String createCookbook(String name, byte[] content); + /** * creates a new client * diff --git a/chef/src/main/java/org/jclouds/chef/filters/SignedHeaderAuth.java b/chef/src/main/java/org/jclouds/chef/filters/SignedHeaderAuth.java index 0e98d7b988..a7227dab64 100644 --- a/chef/src/main/java/org/jclouds/chef/filters/SignedHeaderAuth.java +++ b/chef/src/main/java/org/jclouds/chef/filters/SignedHeaderAuth.java @@ -152,9 +152,9 @@ public class SignedHeaderAuth implements HttpRequestFilter { if (payload == null) return emptyStringHash; checkArgument(payload != null, "payload was null"); - checkArgument(payload.isRepeatable(), "payload must be repeatable"); + checkArgument(payload.isRepeatable(), "payload must be repeatable: " + payload); try { - return encryptionService.sha1Base64(Utils.toStringAndClose(payload.getContent())); + return encryptionService.sha1Base64(Utils.toStringAndClose(payload.getInput())); } catch (Exception e) { Throwables.propagateIfPossible(e); throw new HttpException("error creating sigature for payload: " + payload, e); diff --git a/chef/src/test/java/org/jclouds/chef/ChefClientLiveTest.java b/chef/src/test/java/org/jclouds/chef/ChefClientLiveTest.java index 2a4641c9c6..ea14d7e97f 100644 --- a/chef/src/test/java/org/jclouds/chef/ChefClientLiveTest.java +++ b/chef/src/test/java/org/jclouds/chef/ChefClientLiveTest.java @@ -26,8 +26,10 @@ package org.jclouds.chef; import static com.google.common.base.Preconditions.checkNotNull; import static org.testng.Assert.assertNotNull; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.net.URI; import java.util.Set; @@ -38,6 +40,7 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.google.common.base.Charsets; +import com.google.common.io.ByteStreams; import com.google.common.io.Files; /** @@ -108,6 +111,31 @@ public class ChefClientLiveTest { } @Test(dependsOnMethods = "testGenerateKeyForClient") + public void testCreateCookbooks() throws Exception { + InputStream in = null; + try { + in = URI + .create( + "https://s3.amazonaws.com/opscode-community/cookbook_versions/tarballs/194/original/java.tar.gz") + .toURL().openStream(); + + byte[] content = ByteStreams.toByteArray(in); + + System.err.println(clientConnection.getApi().createCookbook("java-bytearray", content)); + + File file = File.createTempFile("foo", "bar"); + Files.write(content, file); + file.deleteOnExit(); + + System.err.println(clientConnection.getApi().createCookbook("java-file", file)); + + } finally { + if (in != null) + in.close(); + } + } + + @Test(dependsOnMethods = "testCreateCookbooks") public void testListCookbooks() throws Exception { System.err.println(clientConnection.getApi().listCookbooks()); } diff --git a/core/src/main/java/org/jclouds/http/HttpRequest.java b/core/src/main/java/org/jclouds/http/HttpRequest.java index aed8bb769f..3e368359f4 100644 --- a/core/src/main/java/org/jclouds/http/HttpRequest.java +++ b/core/src/main/java/org/jclouds/http/HttpRequest.java @@ -159,8 +159,8 @@ public class HttpRequest extends HttpMessage { } private void closeContentIfPresent() { - if (getPayload() != null && getPayload().getContent() != null) { - Closeables.closeQuietly(getPayload().getContent()); + if (getPayload() != null && getPayload().getInput() != null) { + Closeables.closeQuietly(getPayload().getInput()); } } diff --git a/core/src/main/java/org/jclouds/http/MultipartForm.java b/core/src/main/java/org/jclouds/http/MultipartForm.java index 2987e87e43..1455f347f8 100644 --- a/core/src/main/java/org/jclouds/http/MultipartForm.java +++ b/core/src/main/java/org/jclouds/http/MultipartForm.java @@ -19,6 +19,7 @@ package org.jclouds.http; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; import java.io.IOException; import java.io.InputStream; @@ -30,59 +31,70 @@ import javax.annotation.Nullable; import javax.ws.rs.core.HttpHeaders; import org.jclouds.http.payloads.FilePayload; -import org.jclouds.util.InputStreamChain; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; +import com.google.common.io.ByteStreams; +import com.google.common.io.Closeables; +import com.google.common.io.InputSupplier; /** * * @author Adrian Cole */ -public class MultipartForm { +public class MultipartForm implements Payload { private static final String rn = "\r\n"; private static final String dd = "--"; - private final InputStreamChain chain; + private final InputSupplier chain; private long size; + private boolean isRepeatable; + private boolean written; public MultipartForm(String boundary, Part... parts) { this(boundary, Lists.newArrayList(parts)); } + @SuppressWarnings("unchecked") public MultipartForm(String boundary, Iterable parts) { String boundaryrn = boundary + rn; - chain = new InputStreamChain(); + isRepeatable = true; + InputSupplier chain = ByteStreams.join(); for (Part part : parts) { - addHeaders(boundaryrn, part); - addData(part); + if (!part.isRepeatable()) + isRepeatable = false; + size += part.calculateSize(); + chain = ByteStreams.join(chain, addLengthAndReturnHeaders(boundaryrn, part), part, + addLengthAndReturnRn()); } - addFooter(boundary); + chain = ByteStreams.join(chain, addLengthAndReturnFooter(boundary)); + this.chain = chain; } - private void addData(Part part) { - chain.addInputStream(part.getContent()); - chain.addAsInputStream(rn); - size += part.calculateSize() + rn.length(); + private InputSupplier addLengthAndReturnRn() { + size += rn.length(); + return ByteStreams.newInputStreamSupplier(rn.getBytes()); } - private void addHeaders(String boundaryrn, Part part) { + private InputSupplier addLengthAndReturnHeaders(String boundaryrn, + Part part) { StringBuilder builder = new StringBuilder(dd).append(boundaryrn); for (Entry entry : part.getHeaders().entries()) { String header = String.format("%s: %s%s", entry.getKey(), entry.getValue(), rn); builder.append(header); } builder.append(rn); - chain.addAsInputStream(builder.toString()); size += builder.length(); + return ByteStreams.newInputStreamSupplier(builder.toString().getBytes()); } - private void addFooter(String boundary) { + private InputSupplier addLengthAndReturnFooter(String boundary) { String end = dd + boundary + dd + rn; - chain.addAsInputStream(end); size += end.length(); + return ByteStreams.newInputStreamSupplier(end.getBytes()); } public MultipartForm(Part... parts) { @@ -147,13 +159,13 @@ public class MultipartForm { } @Override - public InputStream getContent() { - return delegate.getContent(); + public InputStream getInput() { + return delegate.getInput(); } @Override public Object getRawContent() { - return delegate.getContent(); + return delegate.getInput(); } @Override @@ -198,11 +210,47 @@ public class MultipartForm { } } - public long getSize() { + @Override + public Long calculateSize() { return size; } - public InputStream getData() { - return chain; + @Override + public InputStream getInput() { + try { + return chain.getInput(); + } catch (IOException e) { + Throwables.propagate(e); + return null; + } + } + + @Override + public Object getRawContent() { + return getInput(); + } + + @Override + public boolean isRepeatable() { + return isRepeatable; + } + + @Override + public void writeTo(OutputStream outstream) throws IOException { + checkState(!written || !isRepeatable, + "InputStreams can only be writted to an outputstream once"); + written = true; + InputStream in = getInput(); + try { + ByteStreams.copy(getInput(), outstream); + } finally { + Closeables.closeQuietly(in); + } + } + + @Override + public String toString() { + return "MultipartForm [chain=" + chain + ", isRepeatable=" + isRepeatable + ", size=" + size + + ", written=" + written + "]"; } } diff --git a/core/src/main/java/org/jclouds/http/Payload.java b/core/src/main/java/org/jclouds/http/Payload.java index 51fc10265e..dddb18e813 100644 --- a/core/src/main/java/org/jclouds/http/Payload.java +++ b/core/src/main/java/org/jclouds/http/Payload.java @@ -22,21 +22,23 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import com.google.common.io.InputSupplier; + /** * @author Adrian Cole */ -public interface Payload { +public interface Payload extends InputSupplier { /** *  Creates a new InputStream object of the payload. */ - InputStream getContent(); - + InputStream getInput(); + /** - * Payload in its original form. + * Payload in its original form. */ Object getRawContent(); - + /** * Tells if the payload is capable of producing its data more than once. */ diff --git a/core/src/main/java/org/jclouds/http/internal/BasePayloadEnclosingImpl.java b/core/src/main/java/org/jclouds/http/internal/BasePayloadEnclosingImpl.java index 5641c22449..f63ac99b0e 100644 --- a/core/src/main/java/org/jclouds/http/internal/BasePayloadEnclosingImpl.java +++ b/core/src/main/java/org/jclouds/http/internal/BasePayloadEnclosingImpl.java @@ -57,7 +57,7 @@ public abstract class BasePayloadEnclosingImpl implements PayloadEnclosing { checkState(payload != null, "payload"); if (payload instanceof InputStreamPayload) { MD5InputStreamResult result = encryptionService - .generateMD5Result(((InputStreamPayload) payload).getContent()); + .generateMD5Result(((InputStreamPayload) payload).getInput()); setContentMD5(result.md5); setContentLength(result.length); setPayload(result.data); @@ -73,7 +73,7 @@ public abstract class BasePayloadEnclosingImpl implements PayloadEnclosing { */ @Override public InputStream getContent() { - return payload != null ? payload.getContent() : null; + return payload != null ? payload.getInput() : null; } /** diff --git a/core/src/main/java/org/jclouds/http/payloads/ByteArrayPayload.java b/core/src/main/java/org/jclouds/http/payloads/ByteArrayPayload.java index 27e8dccf90..7f6a58fa6a 100644 --- a/core/src/main/java/org/jclouds/http/payloads/ByteArrayPayload.java +++ b/core/src/main/java/org/jclouds/http/payloads/ByteArrayPayload.java @@ -49,7 +49,7 @@ public class ByteArrayPayload implements Payload { * {@inheritDoc} */ @Override - public InputStream getContent() { + public InputStream getInput() { return new ByteArrayInputStream(content); } diff --git a/core/src/main/java/org/jclouds/http/payloads/FilePayload.java b/core/src/main/java/org/jclouds/http/payloads/FilePayload.java index 1665f3e82a..e7747ffdc2 100644 --- a/core/src/main/java/org/jclouds/http/payloads/FilePayload.java +++ b/core/src/main/java/org/jclouds/http/payloads/FilePayload.java @@ -52,7 +52,7 @@ public class FilePayload implements Payload { * {@inheritDoc} */ @Override - public InputStream getContent() { + public InputStream getInput() { try { return new FileInputStream(content); } catch (FileNotFoundException e) { @@ -73,7 +73,7 @@ public class FilePayload implements Payload { */ @Override public void writeTo(OutputStream outstream) throws IOException { - InputStream in = getContent(); + InputStream in = getInput(); try { Files.copy(content, outstream); } finally { diff --git a/core/src/main/java/org/jclouds/http/payloads/InputStreamPayload.java b/core/src/main/java/org/jclouds/http/payloads/InputStreamPayload.java index 73b50c059f..3459e15378 100644 --- a/core/src/main/java/org/jclouds/http/payloads/InputStreamPayload.java +++ b/core/src/main/java/org/jclouds/http/payloads/InputStreamPayload.java @@ -49,7 +49,7 @@ public class InputStreamPayload implements Payload { * {@inheritDoc} */ @Override - public InputStream getContent() { + public InputStream getInput() { return content; } @@ -68,9 +68,9 @@ public class InputStreamPayload implements Payload { public void writeTo(OutputStream outstream) throws IOException { checkState(!written, "InputStreams can only be writted to an outputstream once"); written = true; - InputStream in = getContent(); + InputStream in = getInput(); try { - ByteStreams.copy(getContent(), outstream); + ByteStreams.copy(getInput(), outstream); } finally { Closeables.closeQuietly(in); } diff --git a/core/src/main/java/org/jclouds/http/payloads/StringPayload.java b/core/src/main/java/org/jclouds/http/payloads/StringPayload.java index 11a8c28524..05bed4c428 100644 --- a/core/src/main/java/org/jclouds/http/payloads/StringPayload.java +++ b/core/src/main/java/org/jclouds/http/payloads/StringPayload.java @@ -47,7 +47,7 @@ public class StringPayload implements Payload { * {@inheritDoc} */ @Override - public InputStream getContent() { + public InputStream getInput() { return Utils.toInputStream(content); } diff --git a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java index cb5cab49df..856fd28514 100755 --- a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java +++ b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java @@ -426,11 +426,11 @@ public class RestAnnotationProcessor { } MultipartForm form = new MultipartForm(BOUNDARY, parts); - request.setPayload(form.getData()); + request.setPayload(form); request.getHeaders().put(HttpHeaders.CONTENT_TYPE, "multipart/form-data; boundary=" + BOUNDARY); - request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, form.getSize() + ""); + request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, form.calculateSize() + ""); } else if (formParams.size() > 0) { if (headers.get(HttpHeaders.CONTENT_TYPE) != null) diff --git a/core/src/test/java/org/jclouds/http/MultipartFormTest.java b/core/src/test/java/org/jclouds/http/MultipartFormTest.java index 92690eda28..6c26e9f319 100644 --- a/core/src/test/java/org/jclouds/http/MultipartFormTest.java +++ b/core/src/test/java/org/jclouds/http/MultipartFormTest.java @@ -55,8 +55,8 @@ public class MultipartFormTest { MultipartForm multipartForm = new MultipartForm(boundary, newPart("hello")); - assertEquals(Utils.toStringAndClose(multipartForm.getData()), expects); - assertEquals(multipartForm.getSize(), 199); + assertEquals(Utils.toStringAndClose(multipartForm.getInput()), expects); + assertEquals(multipartForm.calculateSize(), new Long(199)); } public static class MockFilePayload extends FilePayload { @@ -82,8 +82,8 @@ public class MultipartFormTest { } @Override - public InputStream getContent() { - return realPayload.getContent(); + public InputStream getInput() { + return realPayload.getInput(); } @Override @@ -125,8 +125,12 @@ public class MultipartFormTest { MultipartForm multipartForm = new MultipartForm(boundary, newPart("hello"), newPart("goodbye")); - assertEquals(Utils.toStringAndClose(multipartForm.getData()), expects); - assertEquals(multipartForm.getSize(), 352); + assertEquals(Utils.toStringAndClose(multipartForm.getInput()), expects); + + // test repeatable + assert multipartForm.isRepeatable(); + assertEquals(Utils.toStringAndClose(multipartForm.getInput()), expects); + assertEquals(multipartForm.calculateSize(), new Long(352)); } } diff --git a/core/src/test/java/org/jclouds/rest/RestClientTest.java b/core/src/test/java/org/jclouds/rest/RestClientTest.java index 136389fdd2..22af382c50 100644 --- a/core/src/test/java/org/jclouds/rest/RestClientTest.java +++ b/core/src/test/java/org/jclouds/rest/RestClientTest.java @@ -77,7 +77,7 @@ public abstract class RestClientTest { if (httpMethod.getPayload() == null) { assertNull(toMatch); } else { - String payload = Utils.toStringAndClose(httpMethod.getPayload().getContent()); + String payload = Utils.toStringAndClose(httpMethod.getPayload().getInput()); assertEquals(payload, toMatch); } } diff --git a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java index 8e8a396691..1867d09ae7 100755 --- a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java +++ b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java @@ -2013,7 +2013,7 @@ public class RestAnnotationProcessorTest { if (httpMethod.getPayload() == null) { assertNull(toMatch); } else { - String payload = Utils.toStringAndClose(httpMethod.getPayload().getContent()); + String payload = Utils.toStringAndClose(httpMethod.getPayload().getInput()); assertEquals(payload, toMatch); } } diff --git a/extensions/gae/src/main/java/org/jclouds/gae/AsyncGaeHttpCommandExecutorService.java b/extensions/gae/src/main/java/org/jclouds/gae/AsyncGaeHttpCommandExecutorService.java index fc57dfbf3d..f73b7af71d 100644 --- a/extensions/gae/src/main/java/org/jclouds/gae/AsyncGaeHttpCommandExecutorService.java +++ b/extensions/gae/src/main/java/org/jclouds/gae/AsyncGaeHttpCommandExecutorService.java @@ -120,7 +120,7 @@ public class AsyncGaeHttpCommandExecutorService implements HttpCommandExecutorSe String string = ((StringPayload) content).getRawContent(); request.setPayload(string.getBytes()); } else if (content instanceof InputStreamPayload || content instanceof FilePayload) { - InputStream i = content.getContent(); + InputStream i = content.getInput(); try { try { request.setPayload(ByteStreams.toByteArray(i)); diff --git a/extensions/gae/src/main/java/org/jclouds/gae/GaeHttpCommandExecutorService.java b/extensions/gae/src/main/java/org/jclouds/gae/GaeHttpCommandExecutorService.java index abb01ffbba..7c8788905c 100644 --- a/extensions/gae/src/main/java/org/jclouds/gae/GaeHttpCommandExecutorService.java +++ b/extensions/gae/src/main/java/org/jclouds/gae/GaeHttpCommandExecutorService.java @@ -90,7 +90,7 @@ public class GaeHttpCommandExecutorService extends BaseHttpCommandExecutorServic String string = ((StringPayload) content).getRawContent(); request.setPayload(string.getBytes()); } else if (content instanceof InputStreamPayload || content instanceof FilePayload) { - InputStream i = content.getContent(); + InputStream i = content.getInput(); try { request.setPayload(ByteStreams.toByteArray(i)); } finally { diff --git a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/binders/BindDataToPayload.java b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/binders/BindDataToPayload.java index 4a21ca99a1..1b7d1b4f66 100644 --- a/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/binders/BindDataToPayload.java +++ b/mezeo/pcs2/core/src/main/java/org/jclouds/mezeo/pcs2/binders/BindDataToPayload.java @@ -30,7 +30,7 @@ public class BindDataToPayload implements Binder { public void bindToRequest(HttpRequest request, Object payload) { PCSFile object = (PCSFile) payload; - request.setPayload(checkNotNull(object.getPayload().getContent(), "object.getContent()")); + request.setPayload(checkNotNull(object.getPayload().getInput(), "object.getContent()")); request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, object.getContentLength() + ""); } } diff --git a/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/binders/BindCFObjectToPayloadTest.java b/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/binders/BindCFObjectToPayloadTest.java index ce32dfea39..f8e6c484d2 100644 --- a/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/binders/BindCFObjectToPayloadTest.java +++ b/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/binders/BindCFObjectToPayloadTest.java @@ -79,7 +79,7 @@ public class BindCFObjectToPayloadTest { HttpRequest request = new HttpRequest("GET", URI.create("http://localhost:8001")); binder.bindToRequest(request, testBlob()); - assertEquals(Utils.toStringAndClose(request.getPayload().getContent()), "hello"); + assertEquals(Utils.toStringAndClose(request.getPayload().getInput()), "hello"); assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH), 5 + ""); assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE), MediaType.TEXT_PLAIN); } @@ -93,7 +93,7 @@ public class BindCFObjectToPayloadTest { HttpRequest request = new HttpRequest("GET", URI.create("http://localhost:8001")); binder.bindToRequest(request, blob); - assertEquals(Utils.toStringAndClose(request.getPayload().getContent()), "hello"); + assertEquals(Utils.toStringAndClose(request.getPayload().getInput()), "hello"); assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH), 5 + ""); assertEquals(request.getFirstHeaderOrNull(HttpHeaders.ETAG), "5d41402abc4b2a76b9719d911017c592");