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.hc.core5.http.io.entity;
29
30 import java.io.IOException;
31 import java.io.InputStream;
32
33 import org.apache.hc.core5.annotation.Contract;
34 import org.apache.hc.core5.annotation.ThreadingBehavior;
35 import org.apache.hc.core5.http.ContentType;
36 import org.apache.hc.core5.io.Closer;
37 import org.apache.hc.core5.util.Args;
38
39 /**
40 * A generic streamed, non-repeatable entity that obtains its content from an {@link InputStream}.
41 * <p>
42 * This class contains {@link ThreadingBehavior#IMMUTABLE_CONDITIONAL immutable attributes} but subclasses may contain
43 * additional immutable or mutable attributes.
44 * </p>
45 *
46 * @see ThreadingBehavior#IMMUTABLE_CONDITIONAL
47 * @since 4.0
48 */
49 @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
50 public class BasicHttpEntity extends AbstractHttpEntity {
51
52 private final InputStream content;
53 private final long length;
54
55 /**
56 * Constructs a new instance with the given attributes kept as immutable.
57 *
58 * @param content The message body contents as an InputStream.
59 * @param contentLength The value for the {@code Content-Length} header for the size of the message body, in bytes.
60 * @param contentType The content-type, may be null.
61 * @param contentEncoding The content encoding string, may be null.
62 * @param chunked Whether this entity should be chunked.
63 */
64 public BasicHttpEntity(
65 final InputStream content, final long contentLength, final ContentType contentType, final String contentEncoding,
66 final boolean chunked) {
67 super(contentType, contentEncoding, chunked);
68 this.content = Args.notNull(content, "Content stream");
69 this.length = contentLength;
70 }
71
72 /**
73 * Constructs a new instance with the given attributes kept as immutable.
74 * <p>
75 * The new instance:
76 * </p>
77 * <ul>
78 * <li>is not chunked.</li>
79 * </ul>
80 *
81 * @param content The message body contents as an InputStream.
82 * @param contentLength The value for the {@code Content-Length} header for the size of the message body, in bytes.
83 * @param contentType The content-type, may be null.
84 * @param contentEncoding The content encoding string, may be null.
85 */
86 public BasicHttpEntity(
87 final InputStream content, final long contentLength, final ContentType contentType, final String contentEncoding) {
88 this(content, contentLength, contentType, contentEncoding, false);
89 }
90
91 /**
92 * Constructs a new instance with the given attributes kept as immutable.
93 * <p>
94 * The new instance:
95 * </p>
96 * <ul>
97 * <li>is not chunked.</li>
98 * <li>does not define a content encoding.</li>
99 * </ul>
100 *
101 * @param content The message body contents as an InputStream.
102 * @param contentLength The value for the {@code Content-Length} header for the size of the message body, in bytes.
103 * @param contentType The content-type, may be null.
104 */
105 public BasicHttpEntity(final InputStream content, final long contentLength, final ContentType contentType) {
106 this(content, contentLength, contentType, null);
107 }
108
109 /**
110 * Constructs a new instance with the given attributes kept as immutable.
111 * <p>
112 * The new instance:
113 * </p>
114 * <ul>
115 * <li>is not chunked.</li>
116 * <li>does not define a length.</li>
117 * </ul>
118 *
119 * @param content The message body contents as an InputStream.
120 * @param contentType The content-type, may be null.
121 * @param contentEncoding The content encoding string, may be null.
122 */
123 public BasicHttpEntity(final InputStream content, final ContentType contentType, final String contentEncoding) {
124 this(content, -1, contentType, contentEncoding);
125 }
126
127 /**
128 * Constructs a new instance with the given attributes kept as immutable.
129 * <p>
130 * The new instance:
131 * </p>
132 * <ul>
133 * <li>is not chunked.</li>
134 * <li>does not define a length.</li>
135 * <li>does not define a content encoding.</li>
136 * </ul>
137 *
138 * @param content The message body contents as an InputStream.
139 * @param contentType The content-type, may be null.
140 */
141 public BasicHttpEntity(final InputStream content, final ContentType contentType) {
142 this(content, -1, contentType, null);
143 }
144
145 /**
146 * Constructs a new instance with the given attributes kept as immutable.
147 * <p>
148 * The new instance:
149 * </p>
150 * <ul>
151 * <li>does not define a length.</li>
152 * <li>does not define a content encoding.</li>
153 * </ul>
154 *
155 * @param content The message body contents as an InputStream.
156 * @param contentType The content-type, may be null.
157 * @param chunked Whether this entity should be chunked.
158 */
159 public BasicHttpEntity(final InputStream content, final ContentType contentType, final boolean chunked) {
160 this(content, -1, contentType, null, chunked);
161 }
162
163 @Override
164 public final long getContentLength() {
165 return this.length;
166 }
167
168 @Override
169 public final InputStream getContent() throws IllegalStateException {
170 return this.content;
171 }
172
173 /**
174 * {@inheritDoc}
175 * <p>
176 * This implementation always returns {@code false}.
177 * </p>
178 */
179 @Override
180 public final boolean isRepeatable() {
181 return false;
182 }
183
184 /**
185 * {@inheritDoc}
186 * <p>
187 * This implementation always returns {@code true}.
188 * </p>
189 */
190 @Override
191 public final boolean isStreaming() {
192 return true;
193 }
194
195 @Override
196 public final void close() throws IOException {
197 Closer.close(content);
198 }
199
200 }