1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.entity.mime;
29
30 import java.io.ByteArrayOutputStream;
31 import java.io.IOException;
32 import java.io.OutputStream;
33 import java.nio.ByteBuffer;
34 import java.nio.CharBuffer;
35 import java.nio.charset.Charset;
36 import java.util.List;
37
38 import org.apache.http.entity.mime.content.ContentBody;
39 import org.apache.http.util.Args;
40 import org.apache.http.util.ByteArrayBuffer;
41
42
43
44
45
46
47
48
49 abstract class AbstractMultipartForm {
50
51 private static ByteArrayBuffer encode(
52 final Charset charset, final String string) {
53 final ByteBuffer encoded = charset.encode(CharBuffer.wrap(string));
54 final ByteArrayBuffer bab = new ByteArrayBuffer(encoded.remaining());
55 bab.append(encoded.array(), encoded.position(), encoded.remaining());
56 return bab;
57 }
58
59 private static void writeBytes(
60 final ByteArrayBuffer b, final OutputStream out) throws IOException {
61 out.write(b.buffer(), 0, b.length());
62 }
63
64 private static void writeBytes(
65 final String s, final Charset charset, final OutputStream out) throws IOException {
66 final ByteArrayBuffer b = encode(charset, s);
67 writeBytes(b, out);
68 }
69
70 private static void writeBytes(
71 final String s, final OutputStream out) throws IOException {
72 final ByteArrayBuffer b = encode(MIME.DEFAULT_CHARSET, s);
73 writeBytes(b, out);
74 }
75
76 protected static void writeField(
77 final MinimalField field, final OutputStream out) throws IOException {
78 writeBytes(field.getName(), out);
79 writeBytes(FIELD_SEP, out);
80 writeBytes(field.getBody(), out);
81 writeBytes(CR_LF, out);
82 }
83
84 protected static void writeField(
85 final MinimalField field, final Charset charset, final OutputStream out) throws IOException {
86 writeBytes(field.getName(), charset, out);
87 writeBytes(FIELD_SEP, out);
88 writeBytes(field.getBody(), charset, out);
89 writeBytes(CR_LF, out);
90 }
91
92 private static final ByteArrayBuffer FIELD_SEP = encode(MIME.DEFAULT_CHARSET, ": ");
93 private static final ByteArrayBuffer CR_LF = encode(MIME.DEFAULT_CHARSET, "\r\n");
94 private static final ByteArrayBuffer TWO_DASHES = encode(MIME.DEFAULT_CHARSET, "--");
95
96 final Charset charset;
97 final String boundary;
98
99
100
101
102
103
104
105
106 public AbstractMultipartForm(final Charset charset, final String boundary) {
107 super();
108 Args.notNull(boundary, "Multipart boundary");
109 this.charset = charset != null ? charset : MIME.DEFAULT_CHARSET;
110 this.boundary = boundary;
111 }
112
113 public AbstractMultipartForm(final String boundary) {
114 this(null, boundary);
115 }
116
117 public abstract List<FormBodyPart> getBodyParts();
118
119 void doWriteTo(
120 final OutputStream out,
121 final boolean writeContent) throws IOException {
122
123 final ByteArrayBuffer boundaryEncoded = encode(this.charset, this.boundary);
124 for (final FormBodyPart part: getBodyParts()) {
125 writeBytes(TWO_DASHES, out);
126 writeBytes(boundaryEncoded, out);
127 writeBytes(CR_LF, out);
128
129 formatMultipartHeader(part, out);
130
131 writeBytes(CR_LF, out);
132
133 if (writeContent) {
134 part.getBody().writeTo(out);
135 }
136 writeBytes(CR_LF, out);
137 }
138 writeBytes(TWO_DASHES, out);
139 writeBytes(boundaryEncoded, out);
140 writeBytes(TWO_DASHES, out);
141 writeBytes(CR_LF, out);
142 }
143
144
145
146
147 protected abstract void formatMultipartHeader(
148 final FormBodyPart part,
149 final OutputStream out) throws IOException;
150
151
152
153
154
155
156 public void writeTo(final OutputStream out) throws IOException {
157 doWriteTo(out, true);
158 }
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 public long getTotalLength() {
175 long contentLen = 0;
176 for (final FormBodyPart part: getBodyParts()) {
177 final ContentBody body = part.getBody();
178 final long len = body.getContentLength();
179 if (len >= 0) {
180 contentLen += len;
181 } else {
182 return -1;
183 }
184 }
185 final ByteArrayOutputStream out = new ByteArrayOutputStream();
186 try {
187 doWriteTo(out, false);
188 final byte[] extra = out.toByteArray();
189 return contentLen + extra.length;
190 } catch (final IOException ex) {
191
192 return -1;
193 }
194 }
195
196 }