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.client5.http.entity;
29
30 import java.io.File;
31 import java.io.InputStream;
32 import java.io.Serializable;
33 import java.util.Arrays;
34 import java.util.List;
35
36 import org.apache.hc.core5.http.ContentType;
37 import org.apache.hc.core5.http.HttpEntity;
38 import org.apache.hc.core5.http.NameValuePair;
39 import org.apache.hc.core5.http.io.entity.AbstractHttpEntity;
40 import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
41 import org.apache.hc.core5.http.io.entity.FileEntity;
42 import org.apache.hc.core5.http.io.entity.InputStreamEntity;
43 import org.apache.hc.core5.http.io.entity.SerializableEntity;
44 import org.apache.hc.core5.http.io.entity.StringEntity;
45
46 /**
47 * Builder for {@link HttpEntity} instances.
48 * <p>
49 * Several setter methods of this builder are mutually exclusive. In case of multiple invocations
50 * of the following methods only the last one will have effect:
51 * </p>
52 * <ul>
53 * <li>{@link #setText(String)}</li>
54 * <li>{@link #setBinary(byte[])}</li>
55 * <li>{@link #setStream(java.io.InputStream)}</li>
56 * <li>{@link #setSerializable(java.io.Serializable)}</li>
57 * <li>{@link #setParameters(java.util.List)}</li>
58 * <li>{@link #setParameters(NameValuePair...)}</li>
59 * <li>{@link #setFile(java.io.File)}</li>
60 * </ul>
61 *
62 * @since 4.3
63 */
64 public class EntityBuilder {
65
66 private String text;
67 private byte[] binary;
68 private InputStream stream;
69 private List<NameValuePair> parameters;
70 private Serializable serializable;
71 private File file;
72 private ContentType contentType;
73 private String contentEncoding;
74 private boolean chunked;
75 private boolean gzipCompressed;
76
77 EntityBuilder() {
78 super();
79 }
80
81 public static EntityBuilder create() {
82 return new EntityBuilder();
83 }
84
85 private void clearContent() {
86 this.text = null;
87 this.binary = null;
88 this.stream = null;
89 this.parameters = null;
90 this.serializable = null;
91 this.file = null;
92 }
93
94 /**
95 * Returns entity content as a string if set using {@link #setText(String)} method.
96 */
97 public String getText() {
98 return text;
99 }
100
101 /**
102 * Sets entity content as a string. This method is mutually exclusive with
103 * {@link #setBinary(byte[])},
104 * {@link #setStream(java.io.InputStream)} ,
105 * {@link #setSerializable(java.io.Serializable)} ,
106 * {@link #setParameters(java.util.List)},
107 * {@link #setParameters(NameValuePair...)}
108 * {@link #setFile(java.io.File)} methods.
109 */
110 public EntityBuilder setText(final String text) {
111 clearContent();
112 this.text = text;
113 return this;
114 }
115
116 /**
117 * Returns entity content as a byte array if set using
118 * {@link #setBinary(byte[])} method.
119 */
120 public byte[] getBinary() {
121 return binary;
122 }
123
124 /**
125 * Sets entity content as a byte array. This method is mutually exclusive with
126 * {@link #setText(String)},
127 * {@link #setStream(java.io.InputStream)} ,
128 * {@link #setSerializable(java.io.Serializable)} ,
129 * {@link #setParameters(java.util.List)},
130 * {@link #setParameters(NameValuePair...)}
131 * {@link #setFile(java.io.File)} methods.
132 */
133 public EntityBuilder setBinary(final byte[] binary) {
134 clearContent();
135 this.binary = binary;
136 return this;
137 }
138
139 /**
140 * Returns entity content as a {@link InputStream} if set using
141 * {@link #setStream(java.io.InputStream)} method.
142 */
143 public InputStream getStream() {
144 return stream;
145 }
146
147 /**
148 * Sets entity content as a {@link InputStream}. This method is mutually exclusive with
149 * {@link #setText(String)},
150 * {@link #setBinary(byte[])},
151 * {@link #setSerializable(java.io.Serializable)} ,
152 * {@link #setParameters(java.util.List)},
153 * {@link #setParameters(NameValuePair...)}
154 * {@link #setFile(java.io.File)} methods.
155 */
156 public EntityBuilder setStream(final InputStream stream) {
157 clearContent();
158 this.stream = stream;
159 return this;
160 }
161
162 /**
163 * Returns entity content as a parameter list if set using
164 * {@link #setParameters(java.util.List)} or
165 * {@link #setParameters(NameValuePair...)} methods.
166 */
167 public List<NameValuePair> getParameters() {
168 return parameters;
169 }
170
171 /**
172 * Sets entity content as a parameter list. This method is mutually exclusive with
173 * {@link #setText(String)},
174 * {@link #setBinary(byte[])},
175 * {@link #setStream(java.io.InputStream)} ,
176 * {@link #setSerializable(java.io.Serializable)} ,
177 * {@link #setFile(java.io.File)} methods.
178 */
179 public EntityBuilder setParameters(final List<NameValuePair> parameters) {
180 clearContent();
181 this.parameters = parameters;
182 return this;
183 }
184
185 /**
186 * Sets entity content as a parameter list. This method is mutually exclusive with
187 * {@link #setText(String)},
188 * {@link #setBinary(byte[])},
189 * {@link #setStream(java.io.InputStream)} ,
190 * {@link #setSerializable(java.io.Serializable)} ,
191 * {@link #setFile(java.io.File)} methods.
192 */
193 public EntityBuilder setParameters(final NameValuePair... parameters) {
194 return setParameters(Arrays.asList(parameters));
195 }
196
197 /**
198 * Returns entity content as a {@link Serializable} if set using
199 * {@link #setSerializable(java.io.Serializable)} method.
200 */
201 public Serializable getSerializable() {
202 return serializable;
203 }
204
205 /**
206 * Sets entity content as a {@link Serializable}. This method is mutually exclusive with
207 * {@link #setText(String)},
208 * {@link #setBinary(byte[])},
209 * {@link #setStream(java.io.InputStream)} ,
210 * {@link #setParameters(java.util.List)},
211 * {@link #setParameters(NameValuePair...)}
212 * {@link #setFile(java.io.File)} methods.
213 */
214 public EntityBuilder setSerializable(final Serializable serializable) {
215 clearContent();
216 this.serializable = serializable;
217 return this;
218 }
219
220 /**
221 * Returns entity content as a {@link File} if set using
222 * {@link #setFile(java.io.File)} method.
223 */
224 public File getFile() {
225 return file;
226 }
227
228 /**
229 * Sets entity content as a {@link File}. This method is mutually exclusive with
230 * {@link #setText(String)},
231 * {@link #setBinary(byte[])},
232 * {@link #setStream(java.io.InputStream)} ,
233 * {@link #setParameters(java.util.List)},
234 * {@link #setParameters(NameValuePair...)}
235 * {@link #setSerializable(java.io.Serializable)} methods.
236 */
237 public EntityBuilder setFile(final File file) {
238 clearContent();
239 this.file = file;
240 return this;
241 }
242
243 /**
244 * Returns {@link ContentType} of the entity, if set.
245 */
246 public ContentType getContentType() {
247 return contentType;
248 }
249
250 /**
251 * Sets {@link ContentType} of the entity.
252 */
253 public EntityBuilder setContentType(final ContentType contentType) {
254 this.contentType = contentType;
255 return this;
256 }
257
258 /**
259 * Returns content encoding of the entity, if set.
260 */
261 public String getContentEncoding() {
262 return contentEncoding;
263 }
264
265 /**
266 * Sets content encoding of the entity.
267 */
268 public EntityBuilder setContentEncoding(final String contentEncoding) {
269 this.contentEncoding = contentEncoding;
270 return this;
271 }
272
273 /**
274 * Returns {@code true} if entity is to be chunk coded, {@code false} otherwise.
275 */
276 public boolean isChunked() {
277 return chunked;
278 }
279
280 /**
281 * Makes entity chunk coded.
282 */
283 public EntityBuilder chunked() {
284 this.chunked = true;
285 return this;
286 }
287
288 /**
289 * Returns {@code true} if entity is to be GZIP compressed, {@code false} otherwise.
290 */
291 public boolean isGzipCompressed() {
292 return gzipCompressed;
293 }
294
295 /**
296 * Makes entity GZIP compressed.
297 */
298 public EntityBuilder gzipCompressed() {
299 this.gzipCompressed = true;
300 return this;
301 }
302
303 private ContentType getContentOrDefault(final ContentType def) {
304 return this.contentType != null ? this.contentType : def;
305 }
306
307 /**
308 * Creates new instance of {@link HttpEntity} based on the current state.
309 */
310 public HttpEntity build() {
311 final AbstractHttpEntity e;
312 if (this.text != null) {
313 e = new StringEntity(this.text, getContentOrDefault(ContentType.DEFAULT_TEXT), this.contentEncoding,
314 this.chunked);
315 } else if (this.binary != null) {
316 e = new ByteArrayEntity(this.binary, getContentOrDefault(ContentType.DEFAULT_BINARY),
317 this.contentEncoding, this.chunked);
318 } else if (this.stream != null) {
319 e = new InputStreamEntity(this.stream, -1, getContentOrDefault(ContentType.DEFAULT_BINARY),
320 this.contentEncoding);
321 } else if (this.parameters != null) {
322 e = new UrlEncodedFormEntity(this.parameters,
323 this.contentType != null ? this.contentType.getCharset() : null);
324 } else if (this.serializable != null) {
325 e = new SerializableEntity(this.serializable, ContentType.DEFAULT_BINARY, this.contentEncoding);
326 } else if (this.file != null) {
327 e = new FileEntity(this.file, getContentOrDefault(ContentType.DEFAULT_BINARY), this.contentEncoding);
328 } else {
329 throw new IllegalStateException("No entity set");
330 }
331 if (this.gzipCompressed) {
332 return new GzipCompressingEntity(e);
333 }
334 return e;
335 }
336
337 }