You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2013/06/21 14:28:59 UTC
svn commit: r1495409 - in /httpcomponents/httpclient/trunk/httpmime/src:
main/java/org/apache/http/entity/mime/ test/java/org/apache/http/entity/mime/
Author: olegk
Date: Fri Jun 21 12:28:58 2013
New Revision: 1495409
URL: http://svn.apache.org/r1495409
Log:
Post HTTPCLIENT-1372 cleanups; all multipart entity generation logic moved to MultipartEntityBuilder
Added:
httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java (with props)
Removed:
httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpMultipartFactory.java
Modified:
httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/AbstractMultipartForm.java
httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpBrowserCompatibleMultipart.java
httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpMultipart.java
httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpRFC6532Multipart.java
httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpStrictMultipart.java
httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MIME.java
httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartEntity.java
httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartEntityBuilder.java
httpcomponents/httpclient/trunk/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartEntityBuilder.java
httpcomponents/httpclient/trunk/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartForm.java
httpcomponents/httpclient/trunk/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartFormHttpEntity.java
Modified: httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/AbstractMultipartForm.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/AbstractMultipartForm.java?rev=1495409&r1=1495408&r2=1495409&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/AbstractMultipartForm.java (original)
+++ httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/AbstractMultipartForm.java Fri Jun 21 12:28:58 2013
@@ -33,7 +33,6 @@ import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
-import java.util.ArrayList;
import java.util.List;
import org.apache.http.entity.mime.content.ContentBody;
@@ -94,11 +93,9 @@ abstract class AbstractMultipartForm {
private static final ByteArrayBuffer CR_LF = encode(MIME.DEFAULT_CHARSET, "\r\n");
private static final ByteArrayBuffer TWO_DASHES = encode(MIME.DEFAULT_CHARSET, "--");
-
private final String subType;
protected final Charset charset;
private final String boundary;
- private final List<FormBodyPart> parts;
/**
* Creates an instance with the specified settings.
@@ -115,7 +112,6 @@ abstract class AbstractMultipartForm {
this.subType = subType;
this.charset = charset != null ? charset : MIME.DEFAULT_CHARSET;
this.boundary = boundary;
- this.parts = new ArrayList<FormBodyPart>();
}
public AbstractMultipartForm(final String subType, final String boundary) {
@@ -130,27 +126,18 @@ abstract class AbstractMultipartForm {
return this.charset;
}
- public List<FormBodyPart> getBodyParts() {
- return this.parts;
- }
-
- public void addBodyPart(final FormBodyPart part) {
- if (part == null) {
- return;
- }
- this.parts.add(part);
- }
+ public abstract List<FormBodyPart> getBodyParts();
public String getBoundary() {
return this.boundary;
}
- private void doWriteTo(
+ void doWriteTo(
final OutputStream out,
final boolean writeContent) throws IOException {
final ByteArrayBuffer boundary = encode(this.charset, getBoundary());
- for (final FormBodyPart part: this.parts) {
+ for (final FormBodyPart part: getBodyParts()) {
writeBytes(TWO_DASHES, out);
writeBytes(boundary, out);
writeBytes(CR_LF, out);
@@ -201,7 +188,7 @@ abstract class AbstractMultipartForm {
*/
public long getTotalLength() {
long contentLen = 0;
- for (final FormBodyPart part: this.parts) {
+ for (final FormBodyPart part: getBodyParts()) {
final ContentBody body = part.getBody();
final long len = body.getContentLength();
if (len >= 0) {
Modified: httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpBrowserCompatibleMultipart.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpBrowserCompatibleMultipart.java?rev=1495409&r1=1495408&r2=1495409&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpBrowserCompatibleMultipart.java (original)
+++ httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpBrowserCompatibleMultipart.java Fri Jun 21 12:28:58 2013
@@ -30,6 +30,7 @@ package org.apache.http.entity.mime;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
+import java.util.List;
/**
* HttpBrowserCompatibleMultipart represents a collection of MIME multipart encoded
@@ -39,22 +40,20 @@ import java.nio.charset.Charset;
*/
class HttpBrowserCompatibleMultipart extends AbstractMultipartForm {
- /**
- * Creates an instance with the specified settings.
- *
- * @param subType mime subtype - must not be {@code null}
- * @param charset the character set to use. May be {@code null},
- * in which case {@link MIME#DEFAULT_CHARSET} - i.e. US-ASCII - is used.
- * @param boundary to use - must not be {@code null}
- * @throws IllegalArgumentException if charset is null or boundary is null
- */
+ private final List<FormBodyPart> parts;
+
public HttpBrowserCompatibleMultipart(
- final String subType, final Charset charset, final String boundary) {
+ final String subType,
+ final Charset charset,
+ final String boundary,
+ final List<FormBodyPart> parts) {
super(subType, charset, boundary);
+ this.parts = parts;
}
- public HttpBrowserCompatibleMultipart(final String subType, final String boundary) {
- this(subType, null, boundary);
+ @Override
+ public List<FormBodyPart> getBodyParts() {
+ return this.parts;
}
/**
Modified: httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpMultipart.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpMultipart.java?rev=1495409&r1=1495408&r2=1495409&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpMultipart.java (original)
+++ httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpMultipart.java Fri Jun 21 12:28:58 2013
@@ -30,6 +30,8 @@ package org.apache.http.entity.mime;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
/**
* HttpMultipart represents a collection of MIME multipart encoded content bodies. This class is
@@ -44,6 +46,7 @@ import java.nio.charset.Charset;
public class HttpMultipart extends AbstractMultipartForm {
private final HttpMultipartMode mode;
+ private final List<FormBodyPart> parts;
/**
* Creates an instance with the specified settings.
@@ -60,6 +63,7 @@ public class HttpMultipart extends Abstr
final HttpMultipartMode mode) {
super(subType, charset, boundary);
this.mode = mode;
+ this.parts = new ArrayList<FormBodyPart>();
}
/**
@@ -107,4 +111,16 @@ public class HttpMultipart extends Abstr
}
}
+ @Override
+ public List<FormBodyPart> getBodyParts() {
+ return this.parts;
+ }
+
+ public void addBodyPart(final FormBodyPart part) {
+ if (part == null) {
+ return;
+ }
+ this.parts.add(part);
+ }
+
}
Modified: httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpRFC6532Multipart.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpRFC6532Multipart.java?rev=1495409&r1=1495408&r2=1495409&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpRFC6532Multipart.java (original)
+++ httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpRFC6532Multipart.java Fri Jun 21 12:28:58 2013
@@ -30,6 +30,7 @@ package org.apache.http.entity.mime;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
+import java.util.List;
/**
* HttpRFC6532Multipart represents a collection of MIME multipart encoded content bodies,
@@ -40,26 +41,22 @@ import java.nio.charset.Charset;
*/
class HttpRFC6532Multipart extends AbstractMultipartForm {
- /**
- * Creates an instance with the specified settings.
- *
- * @param subType mime subtype - must not be {@code null}
- * @param charset the character set to use. May be {@code null},
- * in which case {@link MIME#DEFAULT_CHARSET} - i.e. US-ASCII - is used.
- * @param boundary to use - must not be {@code null}
- * @throws IllegalArgumentException if charset is null or boundary is null
- */
- public HttpRFC6532Multipart(final String subType, final Charset charset, final String boundary) {
+ private final List<FormBodyPart> parts;
+
+ public HttpRFC6532Multipart(
+ final String subType,
+ final Charset charset,
+ final String boundary,
+ final List<FormBodyPart> parts) {
super(subType, charset, boundary);
+ this.parts = parts;
}
- public HttpRFC6532Multipart(final String subType, final String boundary) {
- this(subType, null, boundary);
+ @Override
+ public List<FormBodyPart> getBodyParts() {
+ return this.parts;
}
- /**
- * Write the multipart header fields; depends on the style.
- */
@Override
protected void formatMultipartHeader(
final FormBodyPart part,
Modified: httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpStrictMultipart.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpStrictMultipart.java?rev=1495409&r1=1495408&r2=1495409&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpStrictMultipart.java (original)
+++ httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/HttpStrictMultipart.java Fri Jun 21 12:28:58 2013
@@ -30,6 +30,7 @@ package org.apache.http.entity.mime;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
+import java.util.List;
/**
* HttpStrictMultipart represents a collection of MIME multipart encoded content bodies,
@@ -40,26 +41,22 @@ import java.nio.charset.Charset;
*/
class HttpStrictMultipart extends AbstractMultipartForm {
- /**
- * Creates an instance with the specified settings.
- *
- * @param subType mime subtype - must not be {@code null}
- * @param charset the character set to use. May be {@code null},
- * in which case {@link MIME#DEFAULT_CHARSET} - i.e. US-ASCII - is used.
- * @param boundary to use - must not be {@code null}
- * @throws IllegalArgumentException if charset is null or boundary is null
- */
- public HttpStrictMultipart(final String subType, final Charset charset, final String boundary) {
+ private final List<FormBodyPart> parts;
+
+ public HttpStrictMultipart(
+ final String subType,
+ final Charset charset,
+ final String boundary,
+ final List<FormBodyPart> parts) {
super(subType, charset, boundary);
+ this.parts = parts;
}
- public HttpStrictMultipart(final String subType, final String boundary) {
- this(subType, null, boundary);
+ @Override
+ public List<FormBodyPart> getBodyParts() {
+ return this.parts;
}
- /**
- * Write the multipart header fields; depends on the style.
- */
@Override
protected void formatMultipartHeader(
final FormBodyPart part,
Modified: httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MIME.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MIME.java?rev=1495409&r1=1495408&r2=1495409&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MIME.java (original)
+++ httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MIME.java Fri Jun 21 12:28:58 2013
@@ -27,6 +27,8 @@
package org.apache.http.entity.mime;
+import org.apache.http.Consts;
+
import java.nio.charset.Charset;
/**
@@ -43,9 +45,9 @@ public final class MIME {
public static final String ENC_BINARY = "binary";
/** The default character set to be used, i.e. "US-ASCII" */
- public static final Charset DEFAULT_CHARSET = Charset.forName("US-ASCII");
+ public static final Charset DEFAULT_CHARSET = Consts.ASCII;
/** UTF-8 is used for RFC6532 */
- public static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
+ public static final Charset UTF8_CHARSET = Consts.UTF_8;
}
Modified: httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartEntity.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartEntity.java?rev=1495409&r1=1495408&r2=1495409&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartEntity.java (original)
+++ httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartEntity.java Fri Jun 21 12:28:58 2013
@@ -36,14 +36,15 @@ import java.util.Random;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.entity.mime.content.ContentBody;
-import org.apache.http.message.BasicHeader;
-import org.apache.http.protocol.HTTP;
/**
* Multipart/form coded HTTP entity consisting of multiple body parts.
*
* @since 4.0
+ *
+ * @deprecated 4.3 Use {@link MultipartEntityBuilder}.
*/
+@Deprecated
public class MultipartEntity implements HttpEntity {
/**
@@ -53,12 +54,8 @@ public class MultipartEntity implements
"-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
.toCharArray();
- private final AbstractMultipartForm multipart;
- private final Header contentType;
-
- // @GuardedBy("dirty") // we always read dirty before accessing length
- private long length;
- private volatile boolean dirty; // used to decide whether to recalculate length
+ private final MultipartEntityBuilder builder;
+ private volatile MultipartFormEntity entity;
/**
* Creates an instance using the specified parameters
@@ -71,30 +68,14 @@ public class MultipartEntity implements
final String boundary,
final Charset charset) {
super();
- final String b = boundary != null ? boundary : generateBoundary();
- this.multipart = HttpMultipartFactory.getInstance("form-data", charset, b, mode != null ? mode : HttpMultipartMode.STRICT);
- this.contentType = new BasicHeader(HTTP.CONTENT_TYPE, generateContentType(b, charset));
- this.dirty = true;
+ this.builder = new MultipartEntityBuilder()
+ .setMode(mode)
+ .setCharset(charset)
+ .setBoundary(boundary);
+ this.entity = null;
}
/**
- * Creates an instance using the specified parameters
- * @param multipart the part encoder to use, may not be {@code null}
- * @param boundary the boundary string, may be {@code null}, in which case {@link #generateBoundary()} is invoked to create the string
- * @param charset the character set to use, may be {@code null}, in which case {@link MIME#DEFAULT_CHARSET} - i.e. US-ASCII - is used.
- */
- public MultipartEntity(
- final AbstractMultipartForm multipart,
- final String boundary,
- final Charset charset) {
- super();
- final String b = boundary != null ? boundary : generateBoundary();
- this.multipart = multipart;
- this.contentType = new BasicHeader(HTTP.CONTENT_TYPE, generateContentType(b, charset));
- this.dirty = true;
- }
-
- /**
* Creates an instance using the specified {@link HttpMultipartMode} mode.
* Boundary and charset are set to {@code null}.
* @param mode the desired mode
@@ -133,16 +114,16 @@ public class MultipartEntity implements
return buffer.toString();
}
- /**
- * @since 4.3
- */
- protected AbstractMultipartForm getMultipart() {
- return multipart;
+ private MultipartFormEntity getEntity() {
+ if (this.entity == null) {
+ this.entity = this.builder.buildEntity();
+ }
+ return this.entity;
}
public void addPart(final FormBodyPart bodyPart) {
- this.multipart.addBodyPart(bodyPart);
- this.dirty = true;
+ this.builder.addPart(bodyPart);
+ this.entity = null;
}
public void addPart(final String name, final ContentBody contentBody) {
@@ -150,37 +131,27 @@ public class MultipartEntity implements
}
public boolean isRepeatable() {
- for (final FormBodyPart part: this.multipart.getBodyParts()) {
- final ContentBody body = part.getBody();
- if (body.getContentLength() < 0) {
- return false;
- }
- }
- return true;
+ return getEntity().isRepeatable();
}
public boolean isChunked() {
- return !isRepeatable();
+ return getEntity().isChunked();
}
public boolean isStreaming() {
- return !isRepeatable();
+ return getEntity().isStreaming();
}
public long getContentLength() {
- if (this.dirty) {
- this.length = this.multipart.getTotalLength();
- this.dirty = false;
- }
- return this.length;
+ return getEntity().getContentLength();
}
public Header getContentType() {
- return this.contentType;
+ return getEntity().getContentType();
}
public Header getContentEncoding() {
- return null;
+ return getEntity().getContentEncoding();
}
public void consumeContent()
@@ -197,7 +168,7 @@ public class MultipartEntity implements
}
public void writeTo(final OutputStream outstream) throws IOException {
- this.multipart.writeTo(outstream);
+ getEntity().writeTo(outstream);
}
}
Modified: httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartEntityBuilder.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartEntityBuilder.java?rev=1495409&r1=1495408&r2=1495409&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartEntityBuilder.java (original)
+++ httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartEntityBuilder.java Fri Jun 21 12:28:58 2013
@@ -31,20 +31,36 @@ import java.io.File;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import java.util.Random;
+import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.content.ByteArrayBody;
+import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.InputStreamBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.util.Args;
/**
+ * Builder for multipart {@link HttpEntity}s.
+ *
* @since 4.3
*/
public class MultipartEntityBuilder {
+ /**
+ * The pool of ASCII chars to be used for generating a multipart boundary.
+ */
+ private final static char[] MULTIPART_CHARS =
+ "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ .toCharArray();
+
+ private final static String DEFAULT_SUBTYPE = "form-data";
+
+ private String subType = DEFAULT_SUBTYPE;
private HttpMultipartMode mode = HttpMultipartMode.STRICT;
private String boundary = null;
private Charset charset = null;
@@ -58,6 +74,11 @@ public class MultipartEntityBuilder {
super();
}
+ public MultipartEntityBuilder setMode(final HttpMultipartMode mode) {
+ this.mode = mode;
+ return this;
+ }
+
public MultipartEntityBuilder setLaxMode() {
this.mode = HttpMultipartMode.BROWSER_COMPATIBLE;
return this;
@@ -78,17 +99,28 @@ public class MultipartEntityBuilder {
return this;
}
- public MultipartEntityBuilder addTextBody(
- final String name, final String text, final ContentType contentType) {
- Args.notNull(name, "Name");
- Args.notNull(text, "Text");
+ MultipartEntityBuilder addPart(final FormBodyPart bodyPart) {
+ if (bodyPart == null) {
+ return this;
+ }
if (this.bodyParts == null) {
this.bodyParts = new ArrayList<FormBodyPart>();
}
- this.bodyParts.add(new FormBodyPart(name, new StringBody(text, contentType)));
+ this.bodyParts.add(bodyPart);
return this;
}
+ public MultipartEntityBuilder addPart(final String name, final ContentBody contentBody) {
+ Args.notNull(name, "Name");
+ Args.notNull(contentBody, "Content body");
+ return addPart(new FormBodyPart(name, contentBody));
+ }
+
+ public MultipartEntityBuilder addTextBody(
+ final String name, final String text, final ContentType contentType) {
+ return addPart(name, new StringBody(text, contentType));
+ }
+
public MultipartEntityBuilder addTextBody(
final String name, final String text) {
return addTextBody(name, text, ContentType.DEFAULT_TEXT);
@@ -96,11 +128,7 @@ public class MultipartEntityBuilder {
public MultipartEntityBuilder addBinaryBody(
final String name, final byte[] b, final ContentType contentType, final String filename) {
- if (this.bodyParts == null) {
- this.bodyParts = new ArrayList<FormBodyPart>();
- }
- this.bodyParts.add(new FormBodyPart(name, new ByteArrayBody(b, contentType, filename)));
- return this;
+ return addPart(name, new ByteArrayBody(b, contentType, filename));
}
public MultipartEntityBuilder addBinaryBody(
@@ -110,12 +138,7 @@ public class MultipartEntityBuilder {
public MultipartEntityBuilder addBinaryBody(
final String name, final File file, final ContentType contentType, final String filename) {
- if (this.bodyParts == null) {
- this.bodyParts = new ArrayList<FormBodyPart>();
- }
- this.bodyParts.add(
- new FormBodyPart(name, new FileBody(file, contentType, filename)));
- return this;
+ return addPart(name, new FileBody(file, contentType, filename));
}
public MultipartEntityBuilder addBinaryBody(
@@ -126,28 +149,59 @@ public class MultipartEntityBuilder {
public MultipartEntityBuilder addBinaryBody(
final String name, final InputStream stream, final ContentType contentType,
final String filename) {
- if (this.bodyParts == null) {
- this.bodyParts = new ArrayList<FormBodyPart>();
- }
- this.bodyParts.add(
- new FormBodyPart(name, new InputStreamBody(stream, contentType, filename)));
- return this;
+ return addPart(name, new InputStreamBody(stream, contentType, filename));
}
public MultipartEntityBuilder addBinaryBody(final String name, final InputStream stream) {
return addBinaryBody(name, stream, ContentType.DEFAULT_BINARY, null);
}
- public MultipartEntity build() {
- final MultipartEntity e = new MultipartEntity(
- this.mode,
- this.boundary, this.charset);
- if (this.bodyParts != null) {
- for (final FormBodyPart bp: this.bodyParts) {
- e.addPart(bp);
- }
+ private String generateContentType(
+ final String boundary,
+ final Charset charset) {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append("multipart/form-data; boundary=");
+ buffer.append(boundary);
+ if (charset != null) {
+ buffer.append("; charset=");
+ buffer.append(charset.name());
}
- return e;
+ return buffer.toString();
+ }
+
+ private String generateBoundary() {
+ final StringBuilder buffer = new StringBuilder();
+ final Random rand = new Random();
+ final int count = rand.nextInt(11) + 30; // a random size from 30 to 40
+ for (int i = 0; i < count; i++) {
+ buffer.append(MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)]);
+ }
+ return buffer.toString();
+ }
+
+ MultipartFormEntity buildEntity() {
+ final String st = subType != null ? subType : DEFAULT_SUBTYPE;
+ final Charset cs = charset;
+ final String b = boundary != null ? boundary : generateBoundary();
+ final List<FormBodyPart> bps = bodyParts != null ? new ArrayList<FormBodyPart>(bodyParts) :
+ Collections.<FormBodyPart>emptyList();
+ final HttpMultipartMode m = mode != null ? mode : HttpMultipartMode.STRICT;
+ final AbstractMultipartForm form;
+ switch (m) {
+ case BROWSER_COMPATIBLE:
+ form = new HttpBrowserCompatibleMultipart(st, cs, b, bps);
+ break;
+ case RFC6532:
+ form = new HttpRFC6532Multipart(st, cs, b, bps);
+ break;
+ default:
+ form = new HttpStrictMultipart(st, cs, b, bps);
+ }
+ return new MultipartFormEntity(form, generateContentType(b, cs), form.getTotalLength());
+ }
+
+ public HttpEntity build() {
+ return buildEntity();
}
}
Added: httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java?rev=1495409&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java (added)
+++ httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java Fri Jun 21 12:28:58 2013
@@ -0,0 +1,100 @@
+/*
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.entity.mime;
+
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.message.BasicHeader;
+import org.apache.http.protocol.HTTP;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+class MultipartFormEntity implements HttpEntity {
+
+ private final AbstractMultipartForm multipart;
+ private final Header contentType;
+ private final long contentLength;
+
+ MultipartFormEntity(
+ final AbstractMultipartForm multipart,
+ final String contentType,
+ final long contentLength) {
+ super();
+ this.multipart = multipart;
+ this.contentType = new BasicHeader(HTTP.CONTENT_TYPE, contentType);
+ this.contentLength = contentLength;
+ }
+
+ AbstractMultipartForm getMultipart() {
+ return this.multipart;
+ }
+
+ public boolean isRepeatable() {
+ return this.contentLength != -1;
+ }
+
+ public boolean isChunked() {
+ return !isRepeatable();
+ }
+
+ public boolean isStreaming() {
+ return !isRepeatable();
+ }
+
+ public long getContentLength() {
+ return this.contentLength;
+ }
+
+ public Header getContentType() {
+ return this.contentType;
+ }
+
+ public Header getContentEncoding() {
+ return null;
+ }
+
+ public void consumeContent()
+ throws IOException, UnsupportedOperationException{
+ if (isStreaming()) {
+ throw new UnsupportedOperationException(
+ "Streaming entity does not implement #consumeContent()");
+ }
+ }
+
+ public InputStream getContent() throws IOException {
+ throw new UnsupportedOperationException(
+ "Multipart form entity does not implement #getContent()");
+ }
+
+ public void writeTo(final OutputStream outstream) throws IOException {
+ this.multipart.writeTo(outstream);
+ }
+
+}
Propchange: httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: httpcomponents/httpclient/trunk/httpmime/src/main/java/org/apache/http/entity/mime/MultipartFormEntity.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: httpcomponents/httpclient/trunk/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartEntityBuilder.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartEntityBuilder.java?rev=1495409&r1=1495408&r2=1495409&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartEntityBuilder.java (original)
+++ httpcomponents/httpclient/trunk/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartEntityBuilder.java Fri Jun 21 12:28:58 2013
@@ -39,33 +39,33 @@ public class TestMultipartEntityBuilder
@Test
public void testBasics() throws Exception {
- final MultipartEntity entity = MultipartEntityBuilder.create().build();
+ final MultipartFormEntity entity = MultipartEntityBuilder.create().buildEntity();
Assert.assertNotNull(entity);
- Assert.assertEquals("org.apache.http.entity.mime.HttpStrictMultipart", entity.getMultipart().getClass().getName());
+ Assert.assertTrue(entity.getMultipart() instanceof HttpStrictMultipart);
Assert.assertEquals(0, entity.getMultipart().getBodyParts().size());
}
@Test
public void testMultipartOptions() throws Exception {
- final MultipartEntity entity = MultipartEntityBuilder.create()
+ final MultipartFormEntity entity = MultipartEntityBuilder.create()
.setBoundary("blah-blah")
.setCharset(Consts.UTF_8)
.setLaxMode()
- .build();
+ .buildEntity();
Assert.assertNotNull(entity);
- Assert.assertEquals("org.apache.http.entity.mime.HttpBrowserCompatibleMultipart", entity.getMultipart().getClass().getName());
+ Assert.assertTrue(entity.getMultipart() instanceof HttpBrowserCompatibleMultipart);
Assert.assertEquals("blah-blah", entity.getMultipart().getBoundary());
Assert.assertEquals(Consts.UTF_8, entity.getMultipart().getCharset());
}
@Test
public void testAddBodyParts() throws Exception {
- final MultipartEntity entity = MultipartEntityBuilder.create()
+ final MultipartFormEntity entity = MultipartEntityBuilder.create()
.addTextBody("p1", "stuff")
.addBinaryBody("p2", new File("stuff"))
.addBinaryBody("p3", new byte[] {})
.addBinaryBody("p4", new ByteArrayInputStream(new byte[] {}))
- .build();
+ .buildEntity();
Assert.assertNotNull(entity);
final List<FormBodyPart> bodyParts = entity.getMultipart().getBodyParts();
Assert.assertNotNull(bodyParts);
Modified: httpcomponents/httpclient/trunk/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartForm.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartForm.java?rev=1495409&r1=1495408&r2=1495409&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartForm.java (original)
+++ httpcomponents/httpclient/trunk/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartForm.java Fri Jun 21 12:28:58 2013
@@ -33,20 +33,30 @@ import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.Writer;
import java.nio.charset.Charset;
+import java.util.Arrays;
import org.apache.http.Consts;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.InputStreamBody;
import org.apache.http.entity.mime.content.StringBody;
+import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
public class TestMultipartForm {
+ private File tmpfile;
+
+ @After
+ public void cleanup() {
+ if (tmpfile != null) {
+ tmpfile.delete();
+ }
+ }
+
@Test
public void testMultipartFormStringParts() throws Exception {
- final AbstractMultipartForm multipart = new HttpStrictMultipart("form-data", "foo");
final FormBodyPart p1 = new FormBodyPart(
"field1",
new StringBody("this stuff", ContentType.DEFAULT_TEXT));
@@ -57,10 +67,8 @@ public class TestMultipartForm {
final FormBodyPart p3 = new FormBodyPart(
"field3",
new StringBody("all kind of stuff", ContentType.DEFAULT_TEXT));
-
- multipart.addBodyPart(p1);
- multipart.addBodyPart(p2);
- multipart.addBodyPart(p3);
+ final HttpStrictMultipart multipart = new HttpStrictMultipart("form-data", null, "foo",
+ Arrays.asList(p1, p2, p3));
final ByteArrayOutputStream out = new ByteArrayOutputStream();
multipart.writeTo(out);
@@ -93,8 +101,7 @@ public class TestMultipartForm {
@Test
public void testMultipartFormBinaryParts() throws Exception {
- final File tmpfile = File.createTempFile("tmp", ".bin");
- tmpfile.deleteOnExit();
+ tmpfile = File.createTempFile("tmp", ".bin");
final Writer writer = new FileWriter(tmpfile);
try {
writer.append("some random whatever");
@@ -102,16 +109,14 @@ public class TestMultipartForm {
writer.close();
}
- final AbstractMultipartForm multipart = new HttpStrictMultipart("form-data", "foo");
final FormBodyPart p1 = new FormBodyPart(
"field1",
new FileBody(tmpfile));
final FormBodyPart p2 = new FormBodyPart(
"field2",
new InputStreamBody(new FileInputStream(tmpfile), "file.tmp"));
-
- multipart.addBodyPart(p1);
- multipart.addBodyPart(p2);
+ final HttpStrictMultipart multipart = new HttpStrictMultipart("form-data", null, "foo",
+ Arrays.asList(p1, p2));
final ByteArrayOutputStream out = new ByteArrayOutputStream();
multipart.writeTo(out);
@@ -136,14 +141,11 @@ public class TestMultipartForm {
final String s = out.toString("US-ASCII");
Assert.assertEquals(expected, s);
Assert.assertEquals(-1, multipart.getTotalLength());
-
- tmpfile.delete();
}
@Test
- public void testMultipartFormBrowserCompatible() throws Exception {
- final File tmpfile = File.createTempFile("tmp", ".bin");
- tmpfile.deleteOnExit();
+ public void testMultipartFormStrict() throws Exception {
+ tmpfile = File.createTempFile("tmp", ".bin");
final Writer writer = new FileWriter(tmpfile);
try {
writer.append("some random whatever");
@@ -151,8 +153,6 @@ public class TestMultipartForm {
writer.close();
}
- // Strict is no accident here, despite the test name - otherwise Transfer-Encoding is not produced.
- final AbstractMultipartForm multipart = new HttpStrictMultipart("form-data", null, "foo");
final FormBodyPart p1 = new FormBodyPart(
"field1",
new FileBody(tmpfile));
@@ -162,10 +162,8 @@ public class TestMultipartForm {
final FormBodyPart p3 = new FormBodyPart(
"field3",
new InputStreamBody(new FileInputStream(tmpfile), "file.tmp"));
-
- multipart.addBodyPart(p1);
- multipart.addBodyPart(p2);
- multipart.addBodyPart(p3);
+ final HttpStrictMultipart multipart = new HttpStrictMultipart("form-data", null, "foo",
+ Arrays.asList(p1, p2, p3));
final ByteArrayOutputStream out = new ByteArrayOutputStream();
multipart.writeTo(out);
@@ -197,14 +195,11 @@ public class TestMultipartForm {
final String s = out.toString("US-ASCII");
Assert.assertEquals(expected, s);
Assert.assertEquals(-1, multipart.getTotalLength());
-
- tmpfile.delete();
}
@Test
public void testMultipartFormRFC6532() throws Exception {
- final File tmpfile = File.createTempFile("tmp", ".bin");
- tmpfile.deleteOnExit();
+ tmpfile = File.createTempFile("tmp", ".bin");
final Writer writer = new FileWriter(tmpfile);
try {
writer.append("some random whatever");
@@ -212,8 +207,6 @@ public class TestMultipartForm {
writer.close();
}
- // Strict is no accident here, despite the test name - otherwise Transfer-Encoding is not produced.
- final AbstractMultipartForm multipart = new HttpRFC6532Multipart("form-data", null, "foo");
final FormBodyPart p1 = new FormBodyPart(
"field1\u0414",
new FileBody(tmpfile));
@@ -223,10 +216,8 @@ public class TestMultipartForm {
final FormBodyPart p3 = new FormBodyPart(
"field3",
new InputStreamBody(new FileInputStream(tmpfile), "file.tmp"));
-
- multipart.addBodyPart(p1);
- multipart.addBodyPart(p2);
- multipart.addBodyPart(p3);
+ final HttpRFC6532Multipart multipart = new HttpRFC6532Multipart("form-data", null, "foo",
+ Arrays.asList(p1, p2, p3));
final ByteArrayOutputStream out = new ByteArrayOutputStream();
multipart.writeTo(out);
@@ -258,8 +249,6 @@ public class TestMultipartForm {
final String s = out.toString("UTF-8");
Assert.assertEquals(expected, s);
Assert.assertEquals(-1, multipart.getTotalLength());
-
- tmpfile.delete();
}
private static final int SWISS_GERMAN_HELLO [] = {
@@ -286,8 +275,7 @@ public class TestMultipartForm {
final String s1 = constructString(SWISS_GERMAN_HELLO);
final String s2 = constructString(RUSSIAN_HELLO);
- final File tmpfile = File.createTempFile("tmp", ".bin");
- tmpfile.deleteOnExit();
+ tmpfile = File.createTempFile("tmp", ".bin");
final Writer writer = new FileWriter(tmpfile);
try {
writer.append("some random whatever");
@@ -295,16 +283,15 @@ public class TestMultipartForm {
writer.close();
}
- final AbstractMultipartForm multipart = new HttpBrowserCompatibleMultipart("form-data", Charset.forName("UTF-8"), "foo");
final FormBodyPart p1 = new FormBodyPart(
"field1",
new InputStreamBody(new FileInputStream(tmpfile), s1 + ".tmp"));
final FormBodyPart p2 = new FormBodyPart(
"field2",
new InputStreamBody(new FileInputStream(tmpfile), s2 + ".tmp"));
-
- multipart.addBodyPart(p1);
- multipart.addBodyPart(p2);
+ final HttpBrowserCompatibleMultipart multipart = new HttpBrowserCompatibleMultipart(
+ "form-data", Consts.UTF_8, "foo",
+ Arrays.asList(p1, p2));
final ByteArrayOutputStream out = new ByteArrayOutputStream();
multipart.writeTo(out);
@@ -327,8 +314,6 @@ public class TestMultipartForm {
final String s = out.toString("UTF-8");
Assert.assertEquals(expected, s);
Assert.assertEquals(-1, multipart.getTotalLength());
-
- tmpfile.delete();
}
@Test
@@ -336,16 +321,14 @@ public class TestMultipartForm {
final String s1 = constructString(SWISS_GERMAN_HELLO);
final String s2 = constructString(RUSSIAN_HELLO);
- final AbstractMultipartForm multipart = new HttpStrictMultipart("form-data", "foo");
final FormBodyPart p1 = new FormBodyPart(
"field1",
new StringBody(s1, ContentType.create("text/plain", Charset.forName("ISO-8859-1"))));
final FormBodyPart p2 = new FormBodyPart(
"field2",
new StringBody(s2, ContentType.create("text/plain", Charset.forName("KOI8-R"))));
-
- multipart.addBodyPart(p1);
- multipart.addBodyPart(p2);
+ final HttpStrictMultipart multipart = new HttpStrictMultipart("form-data", null, "foo",
+ Arrays.asList(p1, p2));
final ByteArrayOutputStream out1 = new ByteArrayOutputStream();
multipart.writeTo(out1);
Modified: httpcomponents/httpclient/trunk/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartFormHttpEntity.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartFormHttpEntity.java?rev=1495409&r1=1495408&r2=1495409&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartFormHttpEntity.java (original)
+++ httpcomponents/httpclient/trunk/httpmime/src/test/java/org/apache/http/entity/mime/TestMultipartFormHttpEntity.java Fri Jun 21 12:28:58 2013
@@ -29,14 +29,13 @@ package org.apache.http.entity.mime;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.nio.charset.Charset;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
+import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.content.InputStreamBody;
-import org.apache.http.entity.mime.content.StringBody;
import org.junit.Assert;
import org.junit.Test;
@@ -44,10 +43,11 @@ public class TestMultipartFormHttpEntity
@Test
public void testExplictContractorParams() throws Exception {
- final MultipartEntity entity = new MultipartEntity(
- HttpMultipartMode.BROWSER_COMPATIBLE,
- "whatever",
- Charset.forName("UTF-8"));
+ final HttpEntity entity = MultipartEntityBuilder.create()
+ .setLaxMode()
+ .setBoundary("whatever")
+ .setCharset(MIME.UTF8_CHARSET)
+ .build();
Assert.assertNull(entity.getContentEncoding());
Assert.assertNotNull(entity.getContentType());
@@ -68,7 +68,7 @@ public class TestMultipartFormHttpEntity
@Test
public void testImplictContractorParams() throws Exception {
- final MultipartEntity entity = new MultipartEntity();
+ final HttpEntity entity = MultipartEntityBuilder.create().build();
Assert.assertNull(entity.getContentEncoding());
Assert.assertNotNull(entity.getContentType());
final Header header = entity.getContentType();
@@ -93,9 +93,10 @@ public class TestMultipartFormHttpEntity
@Test
public void testRepeatable() throws Exception {
- final MultipartEntity entity = new MultipartEntity();
- entity.addPart("p1", new StringBody("blah blah", ContentType.DEFAULT_TEXT));
- entity.addPart("p2", new StringBody("yada yada", ContentType.DEFAULT_TEXT));
+ final HttpEntity entity = MultipartEntityBuilder.create()
+ .addTextBody("p1", "blah blah", ContentType.DEFAULT_TEXT)
+ .addTextBody("p2", "yada yada", ContentType.DEFAULT_TEXT)
+ .build();
Assert.assertTrue(entity.isRepeatable());
Assert.assertFalse(entity.isChunked());
Assert.assertFalse(entity.isStreaming());
@@ -124,11 +125,12 @@ public class TestMultipartFormHttpEntity
@Test
public void testNonRepeatable() throws Exception {
- final MultipartEntity entity = new MultipartEntity();
- entity.addPart("p1", new InputStreamBody(
- new ByteArrayInputStream("blah blah".getBytes()), ContentType.DEFAULT_BINARY));
- entity.addPart("p2", new InputStreamBody(
- new ByteArrayInputStream("yada yada".getBytes()), ContentType.DEFAULT_BINARY));
+ final HttpEntity entity = MultipartEntityBuilder.create()
+ .addPart("p1", new InputStreamBody(
+ new ByteArrayInputStream("blah blah".getBytes()), ContentType.DEFAULT_BINARY))
+ .addPart("p2", new InputStreamBody(
+ new ByteArrayInputStream("yada yada".getBytes()), ContentType.DEFAULT_BINARY))
+ .build();
Assert.assertFalse(entity.isRepeatable());
Assert.assertTrue(entity.isChunked());
Assert.assertTrue(entity.isStreaming());