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