1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package org.apache.commons.httpclient.methods;
33
34 import java.io.ByteArrayOutputStream;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.io.OutputStream;
38
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41
42 /***
43 * A RequestEntity that contains an InputStream.
44 *
45 * @since 3.0
46 */
47 public class InputStreamRequestEntity implements RequestEntity {
48
49 /***
50 * The content length will be calculated automatically. This implies
51 * buffering of the content.
52 */
53 public static final int CONTENT_LENGTH_AUTO = -2;
54
55 private static final Log LOG = LogFactory.getLog(InputStreamRequestEntity.class);
56
57 private long contentLength;
58
59 private InputStream content;
60
61 /*** The buffered request body, if any. */
62 private byte[] buffer = null;
63
64 /*** The content type */
65 private String contentType;
66
67 /***
68 * Creates a new InputStreamRequestEntity with the given content and a content type of
69 * {@link #CONTENT_LENGTH_AUTO}.
70 * @param content The content to set.
71 */
72 public InputStreamRequestEntity(InputStream content) {
73 this(content, null);
74 }
75
76 /***
77 * Creates a new InputStreamRequestEntity with the given content, content type, and a
78 * content length of {@link #CONTENT_LENGTH_AUTO}.
79 * @param content The content to set.
80 * @param contentType The type of the content, or <code>null</code>.
81 */
82 public InputStreamRequestEntity(InputStream content, String contentType) {
83 this(content, CONTENT_LENGTH_AUTO, contentType);
84 }
85
86 /***
87 * Creates a new InputStreamRequestEntity with the given content and content length.
88 * @param content The content to set.
89 * @param contentLength The content size in bytes or a negative number if not known.
90 * If {@link #CONTENT_LENGTH_AUTO} is given the content will be buffered in order to
91 * determine its size when {@link #getContentLength()} is called.
92 */
93 public InputStreamRequestEntity(InputStream content, long contentLength) {
94 this(content, contentLength, null);
95 }
96
97 /***
98 * Creates a new InputStreamRequestEntity with the given content, content length, and
99 * content type.
100 * @param content The content to set.
101 * @param contentLength The content size in bytes or a negative number if not known.
102 * If {@link #CONTENT_LENGTH_AUTO} is given the content will be buffered in order to
103 * determine its size when {@link #getContentLength()} is called.
104 * @param contentType The type of the content, or <code>null</code>.
105 */
106 public InputStreamRequestEntity(InputStream content, long contentLength, String contentType) {
107 if (content == null) {
108 throw new IllegalArgumentException("The content cannot be null");
109 }
110 this.content = content;
111 this.contentLength = contentLength;
112 this.contentType = contentType;
113 }
114
115
116
117
118 public String getContentType() {
119 return contentType;
120 }
121
122 /***
123 * Buffers request body input stream.
124 */
125 private void bufferContent() {
126
127 if (this.buffer != null) {
128
129 return;
130 }
131 if (this.content != null) {
132 try {
133 ByteArrayOutputStream tmp = new ByteArrayOutputStream();
134 byte[] data = new byte[4096];
135 int l = 0;
136 while ((l = this.content.read(data)) >= 0) {
137 tmp.write(data, 0, l);
138 }
139 this.buffer = tmp.toByteArray();
140 this.content = null;
141 this.contentLength = buffer.length;
142 } catch (IOException e) {
143 LOG.error(e.getMessage(), e);
144 this.buffer = null;
145 this.content = null;
146 this.contentLength = 0;
147 }
148 }
149 }
150
151 /***
152 * Tests if this method is repeatable. Only <code>true</code> if the content has been
153 * buffered.
154 *
155 * @see #getContentLength()
156 */
157 public boolean isRepeatable() {
158 return buffer != null;
159 }
160
161
162
163
164 public void writeRequest(OutputStream out) throws IOException {
165
166 if (content != null) {
167 byte[] tmp = new byte[4096];
168 int total = 0;
169 int i = 0;
170 while ((i = content.read(tmp)) >= 0) {
171 out.write(tmp, 0, i);
172 total += i;
173 }
174 } else if (buffer != null) {
175 out.write(buffer);
176 } else {
177 throw new IllegalStateException("Content must be set before entity is written");
178 }
179 }
180
181 /***
182 * Gets the content length. If the content length has not been set, the content will be
183 * buffered to determine the actual content length.
184 */
185 public long getContentLength() {
186 if (contentLength == CONTENT_LENGTH_AUTO && buffer == null) {
187 bufferContent();
188 }
189 return contentLength;
190 }
191
192 /***
193 * @return Returns the content.
194 */
195 public InputStream getContent() {
196 return content;
197 }
198
199 }