View Javadoc

1   /*
2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java,v 1.4 2004/05/17 21:46:03 olegk Exp $
3    * $Revision: 159637 $
4    * $Date: 2005-03-31 16:05:48 -0500 (Thu, 31 Mar 2005) $
5    *
6    * ====================================================================
7    *
8    *  Copyright 2004 The Apache Software Foundation
9    *
10   *  Licensed under the Apache License, Version 2.0 (the "License");
11   *  you may not use this file except in compliance with the License.
12   *  You may obtain a copy of the License at
13   *
14   *      http://www.apache.org/licenses/LICENSE-2.0
15   *
16   *  Unless required by applicable law or agreed to in writing, software
17   *  distributed under the License is distributed on an "AS IS" BASIS,
18   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   *  See the License for the specific language governing permissions and
20   *  limitations under the License.
21   * ====================================================================
22   *
23   * This software consists of voluntary contributions made by many
24   * individuals on behalf of the Apache Software Foundation.  For more
25   * information on the Apache Software Foundation, please see
26   * <http://www.apache.org/>.
27   *
28   * [Additional notices, if required by prior licensing conditions]
29   *
30   */
31  package org.apache.commons.httpclient.methods;
32  
33  import java.io.ByteArrayOutputStream;
34  import java.io.IOException;
35  import java.io.InputStream;
36  import java.io.OutputStream;
37  
38  import org.apache.commons.logging.Log;
39  import org.apache.commons.logging.LogFactory;
40  
41  /***
42   * A RequestEntity that contains an InputStream.
43   * 
44   * @since 3.0
45   */
46  public class InputStreamRequestEntity implements RequestEntity {
47  
48      /***
49       * The content length will be calculated automatically. This implies
50       * buffering of the content.
51       */
52      public static final int CONTENT_LENGTH_AUTO = -2;
53      
54      private static final Log LOG = LogFactory.getLog(InputStreamRequestEntity.class);
55      
56      private long contentLength;
57      
58      private InputStream content;
59  
60      /*** The buffered request body, if any. */
61      private byte[] buffer = null;
62      
63      /*** The content type */
64      private String contentType;
65  
66      /***
67       * Creates a new InputStreamRequestEntity with the given content and a content type of
68       * {@link #CONTENT_LENGTH_AUTO}.
69       * @param content The content to set.
70       */
71      public InputStreamRequestEntity(InputStream content) {
72          this(content, null);
73      }
74      
75      /***
76       * Creates a new InputStreamRequestEntity with the given content, content type, and a 
77       * content length of {@link #CONTENT_LENGTH_AUTO}.
78       * @param content The content to set.
79       * @param contentType The type of the content, or <code>null</code>.
80       */
81      public InputStreamRequestEntity(InputStream content, String contentType) {
82          this(content, CONTENT_LENGTH_AUTO, contentType);
83      }
84  
85      /***
86       * Creates a new InputStreamRequestEntity with the given content and content length.
87       * @param content The content to set.
88       * @param contentLength The content size in bytes or any of 
89       *  {@link EntityEnclosingMethod#CONTENT_LENGTH_AUTO CONTENT_LENGTH_AUTO},
90       *  {@link EntityEnclosingMethod#CONTENT_LENGTH_CHUNKED CONTENT_LENGTH_CHUNKED}. If the number 
91       *  of bytes or <code>CONTENT_LENGTH_CHUNKED</code> is specified the content will not be 
92       *  buffered when {@link #getContentLength()} is called.
93       */
94      public InputStreamRequestEntity(InputStream content, long contentLength) {
95          this(content, contentLength, null);
96      }
97      
98      /***
99       * Creates a new InputStreamRequestEntity with the given content, content length, and 
100      * content type.
101      * @param content The content to set.
102      * @param contentLength The content size in bytes or any of 
103      *  {@link EntityEnclosingMethod#CONTENT_LENGTH_AUTO CONTENT_LENGTH_AUTO},
104      *  {@link EntityEnclosingMethod#CONTENT_LENGTH_CHUNKED CONTENT_LENGTH_CHUNKED}. If the number 
105      *  of bytes or <code>CONTENT_LENGTH_CHUNKED</code> is specified the content will not be 
106      *  buffered when {@link #getContentLength()} is called.
107      * @param contentType The type of the content, or <code>null</code>.
108      */
109     public InputStreamRequestEntity(InputStream content, long contentLength, String contentType) {
110         if (content == null) {
111             throw new IllegalArgumentException("The content cannot be null");
112         }
113         this.content = content;
114         this.contentLength = contentLength;
115         this.contentType = contentType;
116     }
117 
118     /* (non-Javadoc)
119      * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType()
120      */
121     public String getContentType() {
122         return contentType;
123     }
124     
125     /***
126      * Buffers request body input stream.
127      */
128     private void bufferContent() {
129 
130         if (this.buffer != null) {
131             // Already been buffered
132             return;
133         }
134         if (this.content != null) {
135             try {
136                 ByteArrayOutputStream tmp = new ByteArrayOutputStream();
137                 byte[] data = new byte[4096];
138                 int l = 0;
139                 while ((l = this.content.read(data)) >= 0) {
140                     tmp.write(data, 0, l);
141                 }
142                 this.buffer = tmp.toByteArray();
143                 this.content = null;
144                 this.contentLength = buffer.length;
145             } catch (IOException e) {
146                 LOG.error(e.getMessage(), e);
147                 this.buffer = null;
148                 this.content = null;
149                 this.contentLength = 0;
150             }
151         }
152     }
153     
154     /***
155      * Tests if this method is repeatable.  Only <code>true</code> if the content has been
156      * buffered.
157      * 
158      * @see #getContentLength()
159      */
160     public boolean isRepeatable() {
161         return buffer != null;
162     }
163 
164     /* (non-Javadoc)
165      * @see org.apache.commons.httpclient.RequestEntity#writeRequest(java.io.OutputStream)
166      */
167     public void writeRequest(OutputStream out) throws IOException {
168         
169         if (content != null) {
170             byte[] tmp = new byte[4096];
171             int total = 0;
172             int i = 0;
173             while ((i = content.read(tmp)) >= 0) {
174                 out.write(tmp, 0, i);
175                 total += i;
176             }        
177         } else if (buffer != null) {
178             out.write(buffer);
179         } else {
180             throw new IllegalStateException("Content must be set before entity is written");
181         }
182     }
183 
184     /***
185      * Gets the content length.  If the content length has not been set, the content will be
186      * buffered to determine the actual content length.
187      */
188     public long getContentLength() {
189         if (contentLength == CONTENT_LENGTH_AUTO && buffer == null) {
190             bufferContent();
191         }
192         return contentLength;
193     }
194 
195     /***
196      * @return Returns the content.
197      */
198     public InputStream getContent() {
199         return content;
200     }
201 
202 }