diff --git a/module-httpmime/pom.xml b/module-httpmime/pom.xml
new file mode 100644
index 000000000..bc420ff03
--- /dev/null
+++ b/module-httpmime/pom.xml
@@ -0,0 +1,147 @@
+
+
+
+
+ 4.0.0
+
+ org.apache.httpcomponents
+ httpcomponents-client
+ 4.0-alpha3-SNAPSHOT
+
+ httpclient-mime
+ HttpClient (MIME entities)
+ 2000
+
+ HttpComponents HttpClient - MIME coded entities
+
+ http://hc.apache.org/httpcomponents-client
+ jar
+
+
+
+ Apache License
+ ../LICENSE.txt
+ repo
+
+
+
+
+ scm:svn:http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-httpmime
+ scm:svn:http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-httpmime
+ http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-httpmime
+
+
+
+
+ org.apache.httpcomponents
+ httpclient
+ ${pom.version}
+
+
+ org.apache.james
+ apache-mime4j
+ 0.3
+
+
+ junit
+ junit
+ 3.8.1
+ test
+
+
+
+
+ 1.5
+ 1.5
+ true
+ true
+
+
+
+
+
+ src/main/resources
+ false
+
+ META-INF/*
+
+
+
+ src/main/resources
+ true
+
+ **/*.properties
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ ${maven.compile.target}
+ ${maven.compile.optimize}
+ ${maven.compile.deprecation}
+
+
+
+ maven-surefire-plugin
+
+
+ **/TestAll.java
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-project-info-reports-plugin
+
+
+
+ dependencies
+ issue-tracking
+ scm
+
+
+
+
+
+
+
+
+
diff --git a/module-httpmime/src/main/java/org/apache/http/client/mime/HttpMultipart.java b/module-httpmime/src/main/java/org/apache/http/client/mime/HttpMultipart.java
new file mode 100644
index 000000000..a8b448530
--- /dev/null
+++ b/module-httpmime/src/main/java/org/apache/http/client/mime/HttpMultipart.java
@@ -0,0 +1,88 @@
+/*
+ * $HeadURL:$
+ * $Revision:$
+ * $Date:$
+ *
+ * ====================================================================
+ * 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
+ * .
+ *
+ */
+
+package org.apache.http.client.mime;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.util.List;
+
+import org.apache.james.mime4j.field.ContentTypeField;
+import org.apache.james.mime4j.field.Field;
+import org.apache.james.mime4j.message.BodyPart;
+import org.apache.james.mime4j.message.Entity;
+import org.apache.james.mime4j.message.Multipart;
+import org.apache.james.mime4j.util.CharsetUtil;
+
+/**
+ * Extension of the mime4j standard class needed to work around
+ * some formatting issues in the {@link Multipart#writeTo(OutputStream)}
+ * method until they have been addressed downstream.
+ */
+public class HttpMultipart extends Multipart {
+
+ @Override
+ public void writeTo(OutputStream out) throws IOException {
+ Entity e = getParent();
+ ContentTypeField cField = (ContentTypeField) e.getHeader().getField(
+ Field.CONTENT_TYPE);
+ String boundary = cField.getBoundary();
+ String charset = cField.getCharset();
+
+ List> bodyParts = getBodyParts();
+
+ BufferedWriter writer = new BufferedWriter(
+ new OutputStreamWriter(out, CharsetUtil.getCharset(charset)),
+ 8192);
+
+ writer.write(getPreamble());
+ writer.write("\r\n");
+
+ for (int i = 0; i < bodyParts.size(); i++) {
+ writer.write("--");
+ writer.write(boundary);
+ writer.write("\r\n");
+ writer.flush();
+ ((BodyPart) bodyParts.get(i)).writeTo(out);
+ writer.write("\r\n");
+ }
+
+ writer.write("--");
+ writer.write(boundary);
+ writer.write("--\r\n");
+ writer.write(getEpilogue());
+ writer.write("\r\n");
+ writer.flush();
+ }
+
+}
diff --git a/module-httpmime/src/main/java/org/apache/http/client/mime/StringPart.java b/module-httpmime/src/main/java/org/apache/http/client/mime/StringPart.java
new file mode 100644
index 000000000..62f970abd
--- /dev/null
+++ b/module-httpmime/src/main/java/org/apache/http/client/mime/StringPart.java
@@ -0,0 +1,45 @@
+package org.apache.http.client.mime;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.http.protocol.HTTP;
+import org.apache.james.mime4j.message.AbstractBody;
+import org.apache.james.mime4j.message.TextBody;
+
+public class StringPart extends AbstractBody implements TextBody {
+
+ private final String text;
+ private final String charset;
+
+ public StringPart(final String text, String charset) {
+ super();
+ if (text == null) {
+ throw new IllegalArgumentException("Text may not be null");
+ }
+ if (charset == null) {
+ charset = HTTP.UTF_8;
+ }
+ this.text = text;
+ this.charset = charset;
+ }
+
+ public StringPart(final String text) {
+ this(text, null);
+ }
+
+ public Reader getReader() throws IOException {
+ return new StringReader(this.text);
+ }
+
+ public void writeTo(final OutputStream out) throws IOException {
+ if (out == null) {
+ throw new IllegalArgumentException("Output stream may not be null");
+ }
+ IOUtils.copy(getReader(), out, this.charset);
+ }
+
+}
diff --git a/module-httpmime/src/test/java/org/apache/http/client/mime/TestAll.java b/module-httpmime/src/test/java/org/apache/http/client/mime/TestAll.java
new file mode 100644
index 000000000..142075dd2
--- /dev/null
+++ b/module-httpmime/src/test/java/org/apache/http/client/mime/TestAll.java
@@ -0,0 +1,54 @@
+/*
+ * $HeadURL:$
+ * $Revision:$
+ * $Date:$
+ * ====================================================================
+ * 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
+ * .
+ *
+ */
+
+package org.apache.http.client.mime;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class TestAll extends TestCase {
+
+ public TestAll(String testName) {
+ super(testName);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTest(TestMultipartForm.suite());
+ return suite;
+ }
+
+ public static void main(String args[]) {
+ String[] testCaseName = { TestAll.class.getName() };
+ junit.textui.TestRunner.main(testCaseName);
+ }
+
+}
diff --git a/module-httpmime/src/test/java/org/apache/http/client/mime/TestMultipartForm.java b/module-httpmime/src/test/java/org/apache/http/client/mime/TestMultipartForm.java
new file mode 100644
index 000000000..ad62352c6
--- /dev/null
+++ b/module-httpmime/src/test/java/org/apache/http/client/mime/TestMultipartForm.java
@@ -0,0 +1,118 @@
+/*
+ * $HeadURL:$
+ * $Revision:$
+ * $Date:$
+ *
+ * ====================================================================
+ * 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
+ * .
+ *
+ */
+
+package org.apache.http.client.mime;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.james.mime4j.field.Field;
+import org.apache.james.mime4j.message.BodyPart;
+import org.apache.james.mime4j.message.Header;
+import org.apache.james.mime4j.message.Message;
+import org.apache.james.mime4j.message.Multipart;
+
+public class TestMultipartForm extends TestCase {
+
+ // ------------------------------------------------------------ Constructor
+ public TestMultipartForm(final String testName) throws IOException {
+ super(testName);
+ }
+
+ // ------------------------------------------------------------------- Main
+ public static void main(String args[]) {
+ String[] testCaseName = { TestMultipartForm.class.getName() };
+ junit.textui.TestRunner.main(testCaseName);
+ }
+
+ // ------------------------------------------------------- TestCase Methods
+
+ public static Test suite() {
+ return new TestSuite(TestMultipartForm.class);
+ }
+
+ public void testMultipartFormContent() throws Exception {
+ Message message = new Message();
+ Header header = new Header();
+ header.addField(
+ Field.parse("Content-Type: multipart/form-data; boundary=foo"));
+ message.setHeader(header);
+
+ Multipart multipart = new HttpMultipart();
+ multipart.setParent(message);
+ BodyPart p1 = new BodyPart();
+ Header h1 = new Header();
+ h1.addField(Field.parse("Content-Type: text/plain"));
+ p1.setHeader(h1);
+ p1.setBody(new StringPart("this stuff"));
+ BodyPart p2 = new BodyPart();
+ Header h2 = new Header();
+ h2.addField(Field.parse("Content-Type: text/plain"));
+ p2.setHeader(h2);
+ p2.setBody(new StringPart("that stuff"));
+ BodyPart p3 = new BodyPart();
+ Header h3 = new Header();
+ h3.addField(Field.parse("Content-Type: text/plain"));
+ p3.setHeader(h3);
+ p3.setBody(new StringPart("all kind of stuff"));
+
+ multipart.addBodyPart(p1);
+ multipart.addBodyPart(p2);
+ multipart.addBodyPart(p3);
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ multipart.writeTo(out);
+ out.close();
+
+ String expected = "\r\n" +
+ "--foo\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" +
+ "this stuff\r\n" +
+ "--foo\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" +
+ "that stuff\r\n" +
+ "--foo\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" +
+ "all kind of stuff\r\n" +
+ "--foo--\r\n" +
+ "\r\n";
+ String s = out.toString("US-ASCII");
+ assertEquals(expected, s);
+ }
+
+}