1 /*
2 * ====================================================================
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 * ====================================================================
20 *
21 * This software consists of voluntary contributions made by many
22 * individuals on behalf of the Apache Software Foundation. For more
23 * information on the Apache Software Foundation, please see
24 * <http://www.apache.org/>.
25 *
26 */
27
28 package org.apache.http.entity;
29
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.OutputStream;
33
34 import org.apache.http.annotation.NotThreadSafe;
35
36 /**
37 * A streamed, non-repeatable entity that obtains its content from
38 * an {@link InputStream}.
39 *
40 * @since 4.0
41 */
42 @NotThreadSafe
43 public class InputStreamEntity extends AbstractHttpEntity {
44
45 private final static int BUFFER_SIZE = 2048;
46
47 private final InputStream content;
48 private final long length;
49
50 public InputStreamEntity(final InputStream instream, long length) {
51 this(instream, length, null);
52 }
53
54 /**
55 * @since 4.2
56 */
57 public InputStreamEntity(final InputStream instream, long length, final ContentType contentType) {
58 super();
59 if (instream == null) {
60 throw new IllegalArgumentException("Source input stream may not be null");
61 }
62 this.content = instream;
63 this.length = length;
64 if (contentType != null) {
65 setContentType(contentType.toString());
66 }
67 }
68
69 public boolean isRepeatable() {
70 return false;
71 }
72
73 public long getContentLength() {
74 return this.length;
75 }
76
77 public InputStream getContent() throws IOException {
78 return this.content;
79 }
80
81 public void writeTo(final OutputStream outstream) throws IOException {
82 if (outstream == null) {
83 throw new IllegalArgumentException("Output stream may not be null");
84 }
85 InputStream instream = this.content;
86 try {
87 byte[] buffer = new byte[BUFFER_SIZE];
88 int l;
89 if (this.length < 0) {
90 // consume until EOF
91 while ((l = instream.read(buffer)) != -1) {
92 outstream.write(buffer, 0, l);
93 }
94 } else {
95 // consume no more than length
96 long remaining = this.length;
97 while (remaining > 0) {
98 l = instream.read(buffer, 0, (int)Math.min(BUFFER_SIZE, remaining));
99 if (l == -1) {
100 break;
101 }
102 outstream.write(buffer, 0, l);
103 remaining -= l;
104 }
105 }
106 } finally {
107 instream.close();
108 }
109 }
110
111 public boolean isStreaming() {
112 return true;
113 }
114
115 /**
116 * @deprecated (4.1) Either use {@link #getContent()} and call {@link java.io.InputStream#close()} on that;
117 * otherwise call {@link #writeTo(OutputStream)} which is required to free the resources.
118 */
119 @Deprecated
120 @Override
121 public void consumeContent() throws IOException {
122 // If the input stream is from a connection, closing it will read to
123 // the end of the content. Otherwise, we don't care what it does.
124 this.content.close();
125 }
126
127 }