1 /*
2 * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/Part.java,v 1.10 2003/04/04 02:37:03 mbecke Exp $
3 * $Revision: 1.10 $
4 * $Date: 2003/04/04 02:37:03 $
5 *
6 * ====================================================================
7 *
8 * The Apache Software License, Version 1.1
9 *
10 * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
11 * reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in
22 * the documentation and/or other materials provided with the
23 * distribution.
24 *
25 * 3. The end-user documentation included with the redistribution, if
26 * any, must include the following acknowlegement:
27 * "This product includes software developed by the
28 * Apache Software Foundation (http://www.apache.org/)."
29 * Alternately, this acknowlegement may appear in the software itself,
30 * if and wherever such third-party acknowlegements normally appear.
31 *
32 * 4. The names "The Jakarta Project", "Commons", and "Apache Software
33 * Foundation" must not be used to endorse or promote products derived
34 * from this software without prior written permission. For written
35 * permission, please contact apache@apache.org.
36 *
37 * 5. Products derived from this software may not be called "Apache"
38 * nor may "Apache" appear in their names without prior written
39 * permission of the Apache Group.
40 *
41 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * SUCH DAMAGE.
53 * ====================================================================
54 *
55 * This software consists of voluntary contributions made by many
56 * individuals on behalf of the Apache Software Foundation. For more
57 * information on the Apache Software Foundation, please see
58 * <http://www.apache.org/>.
59 *
60 * [Additional notices, if required by prior licensing conditions]
61 *
62 */
63
64 package org.apache.commons.httpclient.methods.multipart;
65
66 import java.io.ByteArrayOutputStream;
67 import java.io.IOException;
68 import java.io.OutputStream;
69
70 import org.apache.commons.httpclient.HttpConstants;
71 import org.apache.commons.logging.Log;
72 import org.apache.commons.logging.LogFactory;
73
74 /***
75 * Abstract class for one Part of a multipart post object.
76 *
77 * @author <a href="mailto:mattalbright@yahoo.com">Matthew Albright</a>
78 * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
79 * @author <a href="mailto:adrian@ephox.com">Adrian Sutton</a>
80 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
81 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
82 *
83 * @since 2.0
84 */
85 public abstract class Part {
86
87 /*** Log object for this class. */
88 private static final Log LOG = LogFactory.getLog(Part.class);
89
90 //TODO: Make this configurable
91
92 /*** The boundary */
93 protected static final String BOUNDARY = "----------------314159265358979323846";
94
95 /*** The boundary as a byte array */
96 protected static final byte[] BOUNDARY_BYTES = HttpConstants.getAsciiBytes(BOUNDARY);
97
98 /*** Carriage return/linefeed */
99 protected static final String CRLF = "\r\n";
100
101 /*** Carriage return/linefeed as a byte array */
102 protected static final byte[] CRLF_BYTES = HttpConstants.getAsciiBytes(CRLF);
103
104 /*** Content dispostion characters */
105 protected static final String QUOTE = "\"";
106
107 /*** Content dispostion as a byte array */
108 protected static final byte[] QUOTE_BYTES =
109 HttpConstants.getAsciiBytes(QUOTE);
110
111 /*** Extra characters */
112 protected static final String EXTRA = "--";
113
114 /*** Extra characters as a byte array */
115 protected static final byte[] EXTRA_BYTES =
116 HttpConstants.getAsciiBytes(EXTRA);
117
118 /*** Content dispostion characters */
119 protected static final String CONTENT_DISPOSITION = "Content-Disposition: form-data; name=";
120
121 /*** Content dispostion as a byte array */
122 protected static final byte[] CONTENT_DISPOSITION_BYTES =
123 HttpConstants.getAsciiBytes(CONTENT_DISPOSITION);
124
125 /*** Content type header */
126 protected static final String CONTENT_TYPE = "Content-Type: ";
127
128 /*** Content type header as a byte array */
129 protected static final byte[] CONTENT_TYPE_BYTES =
130 HttpConstants.getAsciiBytes(CONTENT_TYPE);
131
132 /*** Content charset */
133 protected static final String CHARSET = "; charset=";
134
135 /*** Content charset as a byte array */
136 protected static final byte[] CHARSET_BYTES =
137 HttpConstants.getAsciiBytes(CHARSET);
138
139 /*** Content type header */
140 protected static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding: ";
141
142 /*** Content type header as a byte array */
143 protected static final byte[] CONTENT_TRANSFER_ENCODING_BYTES =
144 HttpConstants.getAsciiBytes(CONTENT_TRANSFER_ENCODING);
145
146 /***
147 * Return the boundary string.
148 * @return the boundary string
149 */
150 public static String getBoundary() {
151 return BOUNDARY;
152 }
153
154 /***
155 * Return the name of this part.
156 * @return String The name.
157 */
158 public abstract String getName();
159
160 /***
161 * Return the content type of this part.
162 * @return String The name.
163 */
164 public abstract String getContentType();
165
166 /***
167 * Return the character encoding of this part.
168 * @return String The name.
169 */
170 public abstract String getCharSet();
171
172 /***
173 * Return the transfer encoding of this part.
174 * @return String The name.
175 */
176 public abstract String getTransferEncoding();
177
178 /***
179 * Write the start to the specified output stream
180 * @param out The output stream
181 * @throws IOException If an IO problem occurs.
182 */
183 protected void sendStart(OutputStream out) throws IOException {
184 LOG.trace("enter sendStart(OutputStream out)");
185 out.write(EXTRA_BYTES);
186 out.write(BOUNDARY_BYTES);
187 out.write(CRLF_BYTES);
188 }
189
190 /***
191 * Write the content disposition header to the specified output stream
192 *
193 * @param out The output stream
194 * @throws IOException If an IO problem occurs.
195 */
196 protected void sendDispositionHeader(OutputStream out) throws IOException {
197 LOG.trace("enter sendDispositionHeader(OutputStream out)");
198 out.write(CONTENT_DISPOSITION_BYTES);
199 out.write(QUOTE_BYTES);
200 out.write(HttpConstants.getAsciiBytes(getName()));
201 out.write(QUOTE_BYTES);
202 }
203
204 /***
205 * Write the content type header to the specified output stream
206 * @param out The output stream
207 * @throws IOException If an IO problem occurs.
208 */
209
210 protected void sendContentTypeHeader(OutputStream out) throws IOException {
211 LOG.trace("enter sendContentTypeHeader(OutputStream out)");
212 String contentType = getContentType();
213 if (contentType != null) {
214 out.write(CRLF_BYTES);
215 out.write(CONTENT_TYPE_BYTES);
216 out.write(HttpConstants.getAsciiBytes(contentType));
217 String charSet = getCharSet();
218 if (charSet != null) {
219 out.write(CHARSET_BYTES);
220 out.write(HttpConstants.getAsciiBytes(charSet));
221 }
222 }
223 }
224
225 /***
226 * Write the content transfer encoding header to the specified
227 * output stream
228 *
229 * @param out The output stream
230 * @throws IOException If an IO problem occurs.
231 */
232
233 protected void sendTransferEncodingHeader(OutputStream out) throws IOException {
234 LOG.trace("enter sendTransferEncodingHeader(OutputStream out)");
235 String transferEncoding = getTransferEncoding();
236 if (transferEncoding != null) {
237 out.write(CRLF_BYTES);
238 out.write(CONTENT_TRANSFER_ENCODING_BYTES);
239 out.write(HttpConstants.getAsciiBytes(transferEncoding));
240 }
241 }
242
243 /***
244 * Write the end of the header to the output stream
245 * @param out The output stream
246 * @throws IOException If an IO problem occurs.
247 */
248 protected void sendEndOfHeader(OutputStream out) throws IOException {
249 LOG.trace("enter sendEndOfHeader(OutputStream out)");
250 out.write(CRLF_BYTES);
251 out.write(CRLF_BYTES);
252 }
253
254 /***
255 * Write the data to the specified output stream
256 * @param out The output stream
257 * @throws IOException If an IO problem occurs.
258 */
259 protected abstract void sendData(OutputStream out) throws IOException;
260
261 /***
262 * Return the length of the main content
263 *
264 * @return long The length.
265 * @throws IOException If an IO problem occurs
266 */
267 protected abstract long lengthOfData() throws IOException;
268
269 /***
270 * Write the end data to the output stream.
271 * @param out The output stream
272 * @throws IOException If an IO problem occurs.
273 */
274 protected void sendEnd(OutputStream out) throws IOException {
275 LOG.trace("enter sendEnd(OutputStream out)");
276 out.write(CRLF_BYTES);
277 }
278
279 /***
280 * Write all the data to the output stream.
281 * If you override this method make sure to override
282 * #length() as well
283 *
284 * @param out The output stream
285 * @throws IOException If an IO problem occurs.
286 */
287 public void send(OutputStream out) throws IOException {
288 LOG.trace("enter send(OutputStream out)");
289 sendStart(out);
290 sendDispositionHeader(out);
291 sendContentTypeHeader(out);
292 sendTransferEncodingHeader(out);
293 sendEndOfHeader(out);
294 sendData(out);
295 sendEnd(out);
296 }
297
298
299 /***
300 * Return the full length of all the data.
301 * If you override this method make sure to override
302 * #send(OutputStream) as well
303 *
304 * @return long The length.
305 * @throws IOException If an IO problem occurs
306 */
307 public long length() throws IOException {
308 LOG.trace("enter length()");
309 ByteArrayOutputStream overhead = new ByteArrayOutputStream();
310 sendStart(overhead);
311 sendDispositionHeader(overhead);
312 sendContentTypeHeader(overhead);
313 sendTransferEncodingHeader(overhead);
314 sendEndOfHeader(overhead);
315 sendEnd(overhead);
316 return overhead.size() + lengthOfData();
317 }
318
319 /***
320 * Return a string representation of this object.
321 * @return A string representation of this object.
322 * @see java.lang.Object#toString()
323 */
324 public String toString() {
325 return this.getName();
326 }
327
328
329 /***
330 * Write all parts and the last boundary to the specified output stream
331 *
332 * @param out The output stream
333 * @param parts The array of parts to be sent
334 *
335 * @throws IOException If an IO problem occurs.
336 */
337 public static void sendParts(OutputStream out, final Part[] parts)
338 throws IOException {
339 LOG.trace("enter sendParts(OutputStream out, Parts[])");
340 if (parts == null) {
341 throw new IllegalArgumentException("Parts may not be null");
342 }
343 for (int i = 0; i < parts.length; i++) {
344 parts[i].send(out);
345 }
346 out.write(EXTRA_BYTES);
347 out.write(BOUNDARY_BYTES);
348 out.write(EXTRA_BYTES);
349 out.write(CRLF_BYTES);
350 }
351
352 /***
353 * Return the total sum of all parts and that of the last boundary
354 *
355 * @param parts The array of parts
356 *
357 * @return the total length
358 *
359 * @throws IOException If an IO problem occurs.
360 */
361 public static long getLengthOfParts(final Part[] parts)
362 throws IOException {
363 LOG.trace("getLengthOfParts(Parts[])");
364 if (parts == null) {
365 throw new IllegalArgumentException("Parts may not be null");
366 }
367 long total = 0;
368 for (int i = 0; i < parts.length; i++) {
369 total += parts[i].length();
370 }
371 total += EXTRA_BYTES.length;
372 total += BOUNDARY_BYTES.length;
373 total += EXTRA_BYTES.length;
374 total += CRLF_BYTES.length;
375 return total;
376 }
377 }
This page was automatically generated by Maven