1a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath/*
2a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/Part.java,v 1.16 2005/01/14 21:16:40 olegk Exp $
3a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * $Revision: 480424 $
4a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
5a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *
6a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * ====================================================================
7a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *
8a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *  Licensed to the Apache Software Foundation (ASF) under one or more
9a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *  contributor license agreements.  See the NOTICE file distributed with
10a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *  this work for additional information regarding copyright ownership.
11a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *  The ASF licenses this file to You under the Apache License, Version 2.0
12a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *  (the "License"); you may not use this file except in compliance with
13a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *  the License.  You may obtain a copy of the License at
14a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *
15a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *      http://www.apache.org/licenses/LICENSE-2.0
16a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *
17a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *  Unless required by applicable law or agreed to in writing, software
18a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *  distributed under the License is distributed on an "AS IS" BASIS,
19a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *  See the License for the specific language governing permissions and
21a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *  limitations under the License.
22a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * ====================================================================
23a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *
24a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * This software consists of voluntary contributions made by many
25a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * individuals on behalf of the Apache Software Foundation.  For more
26a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * information on the Apache Software Foundation, please see
27a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * <http://www.apache.org/>.
28a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *
29a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */
30a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
31a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathpackage com.android.internal.http.multipart;
32a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
33a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport java.io.ByteArrayOutputStream;
34a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport java.io.IOException;
35a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport java.io.OutputStream;
36a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
37a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport org.apache.http.util.EncodingUtils;
38a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport org.apache.commons.logging.Log;
39a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathimport org.apache.commons.logging.LogFactory;
40a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
41a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath/**
42a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * Abstract class for one Part of a multipart post object.
43a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *
44a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * @author <a href="mailto:mattalbright@yahoo.com">Matthew Albright</a>
45a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
46a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * @author <a href="mailto:adrian@ephox.com">Adrian Sutton</a>
47a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
48a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
49a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath *
50a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath * @since 2.0
51a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath */
52a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamathpublic abstract class Part {
53a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
54a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /** Log object for this class. */
55a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    private static final Log LOG = LogFactory.getLog(Part.class);
56a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
57a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
58a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * The boundary
59a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @deprecated use {@link org.apache.http.client.methods.multipart#MULTIPART_BOUNDARY}
60a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
61a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final String BOUNDARY = "----------------314159265358979323846";
62a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
63a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
64a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * The boundary as a byte array.
65a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @deprecated
66a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
67a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final byte[] BOUNDARY_BYTES = EncodingUtils.getAsciiBytes(BOUNDARY);
68a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
69a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
70a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * The default boundary to be used if {@link #setPartBoundary(byte[])} has not
71a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * been called.
72a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
73a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    private static final byte[] DEFAULT_BOUNDARY_BYTES = BOUNDARY_BYTES;
74a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
75a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /** Carriage return/linefeed */
76a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final String CRLF = "\r\n";
77a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
78a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /** Carriage return/linefeed as a byte array */
79a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final byte[] CRLF_BYTES = EncodingUtils.getAsciiBytes(CRLF);
80a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
81a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /** Content dispostion characters */
82a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final String QUOTE = "\"";
83a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
84a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /** Content dispostion as a byte array */
85a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final byte[] QUOTE_BYTES =
86a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath      EncodingUtils.getAsciiBytes(QUOTE);
87a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
88a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /** Extra characters */
89a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final String EXTRA = "--";
90a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
91a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /** Extra characters as a byte array */
92a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final byte[] EXTRA_BYTES =
93a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath      EncodingUtils.getAsciiBytes(EXTRA);
94a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
95a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /** Content dispostion characters */
96a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final String CONTENT_DISPOSITION = "Content-Disposition: form-data; name=";
97a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
98a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /** Content dispostion as a byte array */
99a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final byte[] CONTENT_DISPOSITION_BYTES =
100a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath      EncodingUtils.getAsciiBytes(CONTENT_DISPOSITION);
101a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
102a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /** Content type header */
103a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final String CONTENT_TYPE = "Content-Type: ";
104a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
105a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /** Content type header as a byte array */
106a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final byte[] CONTENT_TYPE_BYTES =
107a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath      EncodingUtils.getAsciiBytes(CONTENT_TYPE);
108a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
109a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /** Content charset */
110a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final String CHARSET = "; charset=";
111a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
112a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /** Content charset as a byte array */
113a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final byte[] CHARSET_BYTES =
114a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath      EncodingUtils.getAsciiBytes(CHARSET);
115a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
116a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /** Content type header */
117a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding: ";
118a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
119a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /** Content type header as a byte array */
120a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected static final byte[] CONTENT_TRANSFER_ENCODING_BYTES =
121a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath      EncodingUtils.getAsciiBytes(CONTENT_TRANSFER_ENCODING);
122a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
123a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
124a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Return the boundary string.
125a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @return the boundary string
126a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @deprecated uses a constant string. Rather use {@link #getPartBoundary}
127a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
128a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    public static String getBoundary() {
129a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        return BOUNDARY;
130a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
131a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
132a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
133a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * The ASCII bytes to use as the multipart boundary.
134a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
135a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    private byte[] boundaryBytes;
136a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
137a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
138a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Return the name of this part.
139a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @return The name.
140a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
141a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    public abstract String getName();
142a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
143a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
144a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Returns the content type of this part.
145a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @return the content type, or <code>null</code> to exclude the content type header
146a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
147a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    public abstract String getContentType();
148a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
149a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
150a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Return the character encoding of this part.
151a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @return the character encoding, or <code>null</code> to exclude the character
152a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * encoding header
153a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
154a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    public abstract String getCharSet();
155a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
156a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
157a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Return the transfer encoding of this part.
158a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @return the transfer encoding, or <code>null</code> to exclude the transfer encoding header
159a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
160a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    public abstract String getTransferEncoding();
161a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
162a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
163a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Gets the part boundary to be used.
164a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @return the part boundary as an array of bytes.
165a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
166a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @since 3.0
167a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
168a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected byte[] getPartBoundary() {
169a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        if (boundaryBytes == null) {
170a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            // custom boundary bytes have not been set, use the default.
171a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            return DEFAULT_BOUNDARY_BYTES;
172a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        } else {
173a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            return boundaryBytes;
174a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        }
175a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
176a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
177a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
178a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Sets the part boundary.  Only meant to be used by
179a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * {@link Part#sendParts(OutputStream, Part[], byte[])}
180a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * and {@link Part#getLengthOfParts(Part[], byte[])}
181a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param boundaryBytes An array of ASCII bytes.
182a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @since 3.0
183a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
184a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    void setPartBoundary(byte[] boundaryBytes) {
185a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        this.boundaryBytes = boundaryBytes;
186a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
187a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
188a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
189a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Tests if this part can be sent more than once.
190a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @return <code>true</code> if {@link #sendData(OutputStream)} can be successfully called
191a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * more than once.
192a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @since 3.0
193a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
194a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    public boolean isRepeatable() {
195a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        return true;
196a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
197a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
198a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
199a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Write the start to the specified output stream
200a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param out The output stream
201a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @throws IOException If an IO problem occurs.
202a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
203a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected void sendStart(OutputStream out) throws IOException {
204a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        LOG.trace("enter sendStart(OutputStream out)");
205a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        out.write(EXTRA_BYTES);
206a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        out.write(getPartBoundary());
207a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        out.write(CRLF_BYTES);
208a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
209a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
210a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
211a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Write the content disposition header to the specified output stream
212a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
213a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param out The output stream
214a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @throws IOException If an IO problem occurs.
215a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
216a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected void sendDispositionHeader(OutputStream out) throws IOException {
217a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        LOG.trace("enter sendDispositionHeader(OutputStream out)");
218a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        out.write(CONTENT_DISPOSITION_BYTES);
219a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        out.write(QUOTE_BYTES);
220a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        out.write(EncodingUtils.getAsciiBytes(getName()));
221a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        out.write(QUOTE_BYTES);
222a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
223a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
224a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
225a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Write the content type header to the specified output stream
226a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param out The output stream
227a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @throws IOException If an IO problem occurs.
228a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
229a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     protected void sendContentTypeHeader(OutputStream out) throws IOException {
230a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        LOG.trace("enter sendContentTypeHeader(OutputStream out)");
231a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        String contentType = getContentType();
232a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        if (contentType != null) {
233a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            out.write(CRLF_BYTES);
234a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            out.write(CONTENT_TYPE_BYTES);
235a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            out.write(EncodingUtils.getAsciiBytes(contentType));
236a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            String charSet = getCharSet();
237a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            if (charSet != null) {
238a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath                out.write(CHARSET_BYTES);
239a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath                out.write(EncodingUtils.getAsciiBytes(charSet));
240a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            }
241a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        }
242a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
243a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
244a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
245a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Write the content transfer encoding header to the specified
246a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * output stream
247a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
248a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param out The output stream
249a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @throws IOException If an IO problem occurs.
250a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
251a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     protected void sendTransferEncodingHeader(OutputStream out) throws IOException {
252a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        LOG.trace("enter sendTransferEncodingHeader(OutputStream out)");
253a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        String transferEncoding = getTransferEncoding();
254a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        if (transferEncoding != null) {
255a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            out.write(CRLF_BYTES);
256a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            out.write(CONTENT_TRANSFER_ENCODING_BYTES);
257a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            out.write(EncodingUtils.getAsciiBytes(transferEncoding));
258a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        }
259a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
260a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
261a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
262a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Write the end of the header to the output stream
263a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param out The output stream
264a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @throws IOException If an IO problem occurs.
265a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
266a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected void sendEndOfHeader(OutputStream out) throws IOException {
267a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        LOG.trace("enter sendEndOfHeader(OutputStream out)");
268a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        out.write(CRLF_BYTES);
269a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        out.write(CRLF_BYTES);
270a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
271a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
272a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
273a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Write the data to the specified output stream
274a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param out The output stream
275a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @throws IOException If an IO problem occurs.
276a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
277a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected abstract void sendData(OutputStream out) throws IOException;
278a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
279a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
280a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Return the length of the main content
281a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
282a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @return long The length.
283a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @throws IOException If an IO problem occurs
284a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
285a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected abstract long lengthOfData() throws IOException;
286a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
287a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
288a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Write the end data to the output stream.
289a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param out The output stream
290a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @throws IOException If an IO problem occurs.
291a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
292a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    protected void sendEnd(OutputStream out) throws IOException {
293a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        LOG.trace("enter sendEnd(OutputStream out)");
294a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        out.write(CRLF_BYTES);
295a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
296a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
297a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
298a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Write all the data to the output stream.
299a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * If you override this method make sure to override
300a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * #length() as well
301a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
302a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param out The output stream
303a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @throws IOException If an IO problem occurs.
304a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
305a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    public void send(OutputStream out) throws IOException {
306a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        LOG.trace("enter send(OutputStream out)");
307a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        sendStart(out);
308a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        sendDispositionHeader(out);
309a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        sendContentTypeHeader(out);
310a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        sendTransferEncodingHeader(out);
311a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        sendEndOfHeader(out);
312a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        sendData(out);
313a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        sendEnd(out);
314a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
315a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
316a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
317a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
318a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Return the full length of all the data.
319a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * If you override this method make sure to override
320a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * #send(OutputStream) as well
321a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
322a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @return long The length.
323a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @throws IOException If an IO problem occurs
324a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
325a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    public long length() throws IOException {
326a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        LOG.trace("enter length()");
327a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        if (lengthOfData() < 0) {
328a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            return -1;
329a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        }
330a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        ByteArrayOutputStream overhead = new ByteArrayOutputStream();
331a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        sendStart(overhead);
332a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        sendDispositionHeader(overhead);
333a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        sendContentTypeHeader(overhead);
334a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        sendTransferEncodingHeader(overhead);
335a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        sendEndOfHeader(overhead);
336a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        sendEnd(overhead);
337a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        return overhead.size() + lengthOfData();
338a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
339a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
340a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
341a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Return a string representation of this object.
342a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @return A string representation of this object.
343a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @see java.lang.Object#toString()
344a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
345a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    @Override
346a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    public String toString() {
347a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        return this.getName();
348a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
349a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
350a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
351a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Write all parts and the last boundary to the specified output stream.
352a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
353a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param out The stream to write to.
354a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param parts The parts to write.
355a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
356a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @throws IOException If an I/O error occurs while writing the parts.
357a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
358a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    public static void sendParts(OutputStream out, final Part[] parts)
359a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        throws IOException {
360a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        sendParts(out, parts, DEFAULT_BOUNDARY_BYTES);
361a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
362a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
363a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
364a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Write all parts and the last boundary to the specified output stream.
365a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
366a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param out The stream to write to.
367a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param parts The parts to write.
368a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param partBoundary The ASCII bytes to use as the part boundary.
369a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
370a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @throws IOException If an I/O error occurs while writing the parts.
371a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
372a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @since 3.0
373a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
374a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    public static void sendParts(OutputStream out, Part[] parts, byte[] partBoundary)
375a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        throws IOException {
376a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
377a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        if (parts == null) {
378a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            throw new IllegalArgumentException("Parts may not be null");
379a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        }
380a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        if (partBoundary == null || partBoundary.length == 0) {
381a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            throw new IllegalArgumentException("partBoundary may not be empty");
382a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        }
383a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        for (int i = 0; i < parts.length; i++) {
384a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            // set the part boundary before the part is sent
385a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            parts[i].setPartBoundary(partBoundary);
386a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            parts[i].send(out);
387a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        }
388a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        out.write(EXTRA_BYTES);
389a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        out.write(partBoundary);
390a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        out.write(EXTRA_BYTES);
391a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        out.write(CRLF_BYTES);
392a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
393a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
394a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
395a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Return the total sum of all parts and that of the last boundary
396a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
397a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param parts The parts.
398a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @return The total length
399a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
400a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @throws IOException If an I/O error occurs while writing the parts.
401a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
402a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    public static long getLengthOfParts(Part[] parts)
403a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    throws IOException {
404a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        return getLengthOfParts(parts, DEFAULT_BOUNDARY_BYTES);
405a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
406a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath
407a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    /**
408a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * Gets the length of the multipart message including the given parts.
409a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
410a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param parts The parts.
411a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @param partBoundary The ASCII bytes to use as the part boundary.
412a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @return The total length
413a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
414a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @throws IOException If an I/O error occurs while writing the parts.
415a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     *
416a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     * @since 3.0
417a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath     */
418a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    public static long getLengthOfParts(Part[] parts, byte[] partBoundary) throws IOException {
419a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        LOG.trace("getLengthOfParts(Parts[])");
420a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        if (parts == null) {
421a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            throw new IllegalArgumentException("Parts may not be null");
422a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        }
423a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        long total = 0;
424a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        for (int i = 0; i < parts.length; i++) {
425a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            // set the part boundary before we calculate the part's length
426a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            parts[i].setPartBoundary(partBoundary);
427a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            long l = parts[i].length();
428a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            if (l < 0) {
429a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath                return -1;
430a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            }
431a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath            total += l;
432a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        }
433a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        total += EXTRA_BYTES.length;
434a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        total += partBoundary.length;
435a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        total += EXTRA_BYTES.length;
436a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        total += CRLF_BYTES.length;
437a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath        return total;
438a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath    }
439a8b46a3d3b6ed1488df10740653829283572903bNarayan Kamath}
440