1 /*
2 * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/Part.java,v 1.10.2.1 2003/10/10 04:16:02 mbecke Exp $
3 * $Revision: 1.10.2.1 $
4 * $Date: 2003/10/10 04:16:02 $
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 The name.
157 */
158 public abstract String getName();
159
160 /***
161 * Returns the content type of this part.
162 * @return the content type, or <code>null</code> to exclude the content type header
163 */
164 public abstract String getContentType();
165
166 /***
167 * Return the character encoding of this part.
168 * @return the character encoding, or <code>null</code> to exclude the character
169 * encoding header
170 */
171 public abstract String getCharSet();
172
173 /***
174 * Return the transfer encoding of this part.
175 * @return the transfer encoding, or <code>null</code> to exclude the transfer encoding header
176 */
177 public abstract String getTransferEncoding();
178
179 /***
180 * Write the start to the specified output stream
181 * @param out The output stream
182 * @throws IOException If an IO problem occurs.
183 */
184 protected void sendStart(OutputStream out) throws IOException {
185 LOG.trace("enter sendStart(OutputStream out)");
186 out.write(EXTRA_BYTES);
187 out.write(BOUNDARY_BYTES);
188 out.write(CRLF_BYTES);
189 }
190
191 /***
192 * Write the content disposition header to the specified output stream
193 *
194 * @param out The output stream
195 * @throws IOException If an IO problem occurs.
196 */
197 protected void sendDispositionHeader(OutputStream out) throws IOException {
198 LOG.trace("enter sendDispositionHeader(OutputStream out)");
199 out.write(CONTENT_DISPOSITION_BYTES);
200 out.write(QUOTE_BYTES);
201 out.write(HttpConstants.getAsciiBytes(getName()));
202 out.write(QUOTE_BYTES);
203 }
204
205 /***
206 * Write the content type header to the specified output stream
207 * @param out The output stream
208 * @throws IOException If an IO problem occurs.
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 protected void sendTransferEncodingHeader(OutputStream out) throws IOException {
233 LOG.trace("enter sendTransferEncodingHeader(OutputStream out)");
234 String transferEncoding = getTransferEncoding();
235 if (transferEncoding != null) {
236 out.write(CRLF_BYTES);
237 out.write(CONTENT_TRANSFER_ENCODING_BYTES);
238 out.write(HttpConstants.getAsciiBytes(transferEncoding));
239 }
240 }
241
242 /***
243 * Write the end of the header to the output stream
244 * @param out The output stream
245 * @throws IOException If an IO problem occurs.
246 */
247 protected void sendEndOfHeader(OutputStream out) throws IOException {
248 LOG.trace("enter sendEndOfHeader(OutputStream out)");
249 out.write(CRLF_BYTES);
250 out.write(CRLF_BYTES);
251 }
252
253 /***
254 * Write the data to the specified output stream
255 * @param out The output stream
256 * @throws IOException If an IO problem occurs.
257 */
258 protected abstract void sendData(OutputStream out) throws IOException;
259
260 /***
261 * Return the length of the main content
262 *
263 * @return long The length.
264 * @throws IOException If an IO problem occurs
265 */
266 protected abstract long lengthOfData() throws IOException;
267
268 /***
269 * Write the end data to the output stream.
270 * @param out The output stream
271 * @throws IOException If an IO problem occurs.
272 */
273 protected void sendEnd(OutputStream out) throws IOException {
274 LOG.trace("enter sendEnd(OutputStream out)");
275 out.write(CRLF_BYTES);
276 }
277
278 /***
279 * Write all the data to the output stream.
280 * If you override this method make sure to override
281 * #length() as well
282 *
283 * @param out The output stream
284 * @throws IOException If an IO problem occurs.
285 */
286 public void send(OutputStream out) throws IOException {
287 LOG.trace("enter send(OutputStream out)");
288 sendStart(out);
289 sendDispositionHeader(out);
290 sendContentTypeHeader(out);
291 sendTransferEncodingHeader(out);
292 sendEndOfHeader(out);
293 sendData(out);
294 sendEnd(out);
295 }
296
297
298 /***
299 * Return the full length of all the data.
300 * If you override this method make sure to override
301 * #send(OutputStream) as well
302 *
303 * @return long The length.
304 * @throws IOException If an IO problem occurs
305 */
306 public long length() throws IOException {
307 LOG.trace("enter length()");
308 ByteArrayOutputStream overhead = new ByteArrayOutputStream();
309 sendStart(overhead);
310 sendDispositionHeader(overhead);
311 sendContentTypeHeader(overhead);
312 sendTransferEncodingHeader(overhead);
313 sendEndOfHeader(overhead);
314 sendEnd(overhead);
315 return overhead.size() + lengthOfData();
316 }
317
318 /***
319 * Return a string representation of this object.
320 * @return A string representation of this object.
321 * @see java.lang.Object#toString()
322 */
323 public String toString() {
324 return this.getName();
325 }
326
327 /***
328 * Write all parts and the last boundary to the specified output stream
329 *
330 * @param out The output stream
331 * @param parts The array of parts to be sent
332 *
333 * @throws IOException If an IO problem occurs.
334 */
335 public static void sendParts(OutputStream out, final Part[] parts)
336 throws IOException {
337 LOG.trace("enter sendParts(OutputStream out, Parts[])");
338 if (parts == null) {
339 throw new IllegalArgumentException("Parts may not be null");
340 }
341 for (int i = 0; i < parts.length; i++) {
342 parts[i].send(out);
343 }
344 out.write(EXTRA_BYTES);
345 out.write(BOUNDARY_BYTES);
346 out.write(EXTRA_BYTES);
347 out.write(CRLF_BYTES);
348 }
349
350 /***
351 * Return the total sum of all parts and that of the last boundary
352 *
353 * @param parts The array of parts
354 *
355 * @return the total length
356 *
357 * @throws IOException If an IO problem occurs.
358 */
359 public static long getLengthOfParts(final Part[] parts)
360 throws IOException {
361 LOG.trace("getLengthOfParts(Parts[])");
362 if (parts == null) {
363 throw new IllegalArgumentException("Parts may not be null");
364 }
365 long total = 0;
366 for (int i = 0; i < parts.length; i++) {
367 total += parts[i].length();
368 }
369 total += EXTRA_BYTES.length;
370 total += BOUNDARY_BYTES.length;
371 total += EXTRA_BYTES.length;
372 total += CRLF_BYTES.length;
373 return total;
374 }
375 }
This page was automatically generated by Maven