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: 224452 $
4    * $Date: 2005-07-23 06:33:39 -0400 (Sat, 23 Jul 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 a negative number if not known.
89       *  If {@link #CONTENT_LENGTH_AUTO} is given the content will be buffered in order to 
90       *  determine its size when {@link #getContentLength()} is called.
91       */
92      public InputStreamRequestEntity(InputStream content, long contentLength) {
93          this(content, contentLength, null);
94      }
95      
96      /***
97       * Creates a new InputStreamRequestEntity with the given content, content length, and 
98       * content type.
99       * @param content The content to set.
100      * @param contentLength The content size in bytes or a negative number if not known.
101      *  If {@link #CONTENT_LENGTH_AUTO} is given the content will be buffered in order to 
102      *  determine its size when {@link #getContentLength()} is called.
103      * @param contentType The type of the content, or <code>null</code>.
104      */
105     public InputStreamRequestEntity(InputStream content, long contentLength, String contentType) {
106         if (content == null) {
107             throw new IllegalArgumentException("The content cannot be null");
108         }
109         this.content = content;
110         this.contentLength = contentLength;
111         this.contentType = contentType;
112     }
113 
114     /* (non-Javadoc)
115      * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType()
116      */
117     public String getContentType() {
118         return contentType;
119     }
120     
121     /***
122      * Buffers request body input stream.
123      */
124     private void bufferContent() {
125 
126         if (this.buffer != null) {
127             // Already been buffered
128             return;
129         }
130         if (this.content != null) {
131             try {
132                 ByteArrayOutputStream tmp = new ByteArrayOutputStream();
133                 byte[] data = new byte[4096];
134                 int l = 0;
135                 while ((l = this.content.read(data)) >= 0) {
136                     tmp.write(data, 0, l);
137                 }
138                 this.buffer = tmp.toByteArray();
139                 this.content = null;
140                 this.contentLength = buffer.length;
141             } catch (IOException e) {
142                 LOG.error(e.getMessage(), e);
143                 this.buffer = null;
144                 this.content = null;
145                 this.contentLength = 0;
146             }
147         }
148     }
149     
150     /***
151      * Tests if this method is repeatable.  Only <code>true</code> if the content has been
152      * buffered.
153      * 
154      * @see #getContentLength()
155      */
156     public boolean isRepeatable() {
157         return buffer != null;
158     }
159 
160     /* (non-Javadoc)
161      * @see org.apache.commons.httpclient.RequestEntity#writeRequest(java.io.OutputStream)
162      */
163     public void writeRequest(OutputStream out) throws IOException {
164         
165         if (content != null) {
166             byte[] tmp = new byte[4096];
167             int total = 0;
168             int i = 0;
169             while ((i = content.read(tmp)) >= 0) {
170                 out.write(tmp, 0, i);
171                 total += i;
172             }        
173         } else if (buffer != null) {
174             out.write(buffer);
175         } else {
176             throw new IllegalStateException("Content must be set before entity is written");
177         }
178     }
179 
180     /***
181      * Gets the content length.  If the content length has not been set, the content will be
182      * buffered to determine the actual content length.
183      */
184     public long getContentLength() {
185         if (contentLength == CONTENT_LENGTH_AUTO && buffer == null) {
186             bufferContent();
187         }
188         return contentLength;
189     }
190 
191     /***
192      * @return Returns the content.
193      */
194     public InputStream getContent() {
195         return content;
196     }
197 
198 }