View Javadoc
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       * Gets the entity content as a string if set using {@link #setText(String)}.
96       *
97       * @return the entity content as a string, may be null.
98       */
99      public String getText() {
100         return text;
101     }
102 
103     /**
104      * Sets entity content as a string. This method is mutually exclusive with
105      * {@link #setBinary(byte[])},
106      * {@link #setStream(java.io.InputStream)},
107      * {@link #setSerializable(java.io.Serializable)},
108      * {@link #setParameters(java.util.List)},
109      * {@link #setParameters(NameValuePair...)}
110      * {@link #setFile(java.io.File)} methods.
111      *
112      * @param text entity content as a string.
113      * @return this
114      */
115     public EntityBuilder setText(final String text) {
116         clearContent();
117         this.text = text;
118         return this;
119     }
120 
121     /**
122      * Gets entity content as a byte array if set using
123      * {@link #setBinary(byte[])}.
124      *
125      * @return entity content as a byte array.
126      */
127     public byte[] getBinary() {
128         return binary;
129     }
130 
131     /**
132      * Sets entity content as a byte array. This method is mutually exclusive with
133      * {@link #setText(String)},
134      * {@link #setStream(java.io.InputStream)},
135      * {@link #setSerializable(java.io.Serializable)},
136      * {@link #setParameters(java.util.List)},
137      * {@link #setParameters(NameValuePair...)}
138      * {@link #setFile(java.io.File)}.
139      *
140      * @param binary The new entity content as a byte array.
141      * @return this
142      */
143     public EntityBuilder setBinary(final byte[] binary) {
144         clearContent();
145         this.binary = binary;
146         return this;
147     }
148 
149     /**
150      * Gets entity content as an {@link InputStream} if set using
151      * {@link #setStream(java.io.InputStream)} method.
152      *
153      * @return entity content as an {@link InputStream}
154      */
155     public InputStream getStream() {
156         return stream;
157     }
158 
159     /**
160      * Sets entity content as an {@link InputStream}. This method is mutually exclusive with
161      * {@link #setText(String)},
162      * {@link #setBinary(byte[])},
163      * {@link #setSerializable(java.io.Serializable)},
164      * {@link #setParameters(java.util.List)},
165      * {@link #setParameters(NameValuePair...)}
166      * {@link #setFile(java.io.File)}.
167      *
168      * @param stream The new entity content as an InputStream.
169      * @return this
170      */
171     public EntityBuilder setStream(final InputStream stream) {
172         clearContent();
173         this.stream = stream;
174         return this;
175     }
176 
177     /**
178      * Gets entity content as a parameter list if set using
179      * {@link #setParameters(java.util.List)} or
180      * {@link #setParameters(NameValuePair...)}.
181      *
182      * @return entity content as a parameter list.
183      */
184     public List<NameValuePair> getParameters() {
185         return parameters;
186     }
187 
188     /**
189      * Sets entity content as a parameter list. This method is mutually exclusive with
190      * {@link #setText(String)},
191      * {@link #setBinary(byte[])},
192      * {@link #setStream(java.io.InputStream)},
193      * {@link #setSerializable(java.io.Serializable)},
194      * {@link #setFile(java.io.File)}.
195      *
196      * @param parameters entity content as a parameter list.
197      * @return this
198      */
199     public EntityBuilder setParameters(final List<NameValuePair> parameters) {
200         clearContent();
201         this.parameters = parameters;
202         return this;
203     }
204 
205     /**
206      * Sets entity content as a parameter list. This method is mutually exclusive with
207      * {@link #setText(String)},
208      * {@link #setBinary(byte[])},
209      * {@link #setStream(java.io.InputStream)},
210      * {@link #setSerializable(java.io.Serializable)},
211      * {@link #setFile(java.io.File)}.
212      *
213      * @param parameters entity content as a parameter list.
214      * @return this
215      */
216     public EntityBuilder setParameters(final NameValuePair... parameters) {
217         return setParameters(Arrays.asList(parameters));
218     }
219 
220     /**
221      * Gets entity content as a {@link Serializable} if set using
222      * {@link #setSerializable(java.io.Serializable)} method.
223      *
224      * @return entity content as a {@link Serializable}.
225      */
226     public Serializable getSerializable() {
227         return serializable;
228     }
229 
230     /**
231      * Sets entity content as a {@link Serializable}. This method is mutually exclusive with
232      * {@link #setText(String)},
233      * {@link #setBinary(byte[])},
234      * {@link #setStream(java.io.InputStream)},
235      * {@link #setParameters(java.util.List)},
236      * {@link #setParameters(NameValuePair...)}
237      * {@link #setFile(java.io.File)}.
238      *
239      * @param serializable entity content as a {@link Serializable}.
240      * @return this
241      */
242     public EntityBuilder setSerializable(final Serializable serializable) {
243         clearContent();
244         this.serializable = serializable;
245         return this;
246     }
247 
248     /**
249      * Gets the entity content as a {@link File} if set using
250      * {@link #setFile(java.io.File)}.
251      *
252      * @return Gets the entity content as a {@link File}.
253      */
254     public File getFile() {
255         return file;
256     }
257 
258     /**
259      * Sets entity content as a {@link File}. This method is mutually exclusive with
260      * {@link #setText(String)},
261      * {@link #setBinary(byte[])},
262      * {@link #setStream(java.io.InputStream)},
263      * {@link #setParameters(java.util.List)},
264      * {@link #setParameters(NameValuePair...)}
265      * {@link #setSerializable(java.io.Serializable)}.
266      *
267      * @param file entity content as a {@link File}.
268      * @return this
269      */
270     public EntityBuilder setFile(final File file) {
271         clearContent();
272         this.file = file;
273         return this;
274     }
275 
276     /**
277      * Gets the {@link ContentType} of the entity, may be null.
278      *
279      * @return the {@link ContentType} of the entity, may be null.
280      */
281     public ContentType getContentType() {
282         return contentType;
283     }
284 
285     /**
286      * Sets the {@link ContentType} of the entity.
287      *
288      * @param contentType the {@link ContentType} of the entity, may be null.
289      * @return this
290      */
291     public EntityBuilder setContentType(final ContentType contentType) {
292         this.contentType = contentType;
293         return this;
294     }
295 
296     /**
297      * Gets the content encoding of the entity, may be null.
298      *
299      * @return the content encoding of the entity, may be null.
300      */
301     public String getContentEncoding() {
302         return contentEncoding;
303     }
304 
305     /**
306      * Sets the content encoding of the entity.
307      *
308      * @param contentEncoding the content encoding of the entity, may be null.
309      * @return this
310      */
311     public EntityBuilder setContentEncoding(final String contentEncoding) {
312         this.contentEncoding = contentEncoding;
313         return this;
314     }
315 
316     /**
317      * Tests if the entity is to be chunk coded ({@code true}), or not ({@code false}).
318      *
319      * @return {@code true} if entity is to be chunk coded, {@code false} otherwise.
320      */
321     public boolean isChunked() {
322         return chunked;
323     }
324 
325     /**
326      * Sets entities to be chunked.
327      * @return this
328      */
329     public EntityBuilder chunked() {
330         this.chunked = true;
331         return this;
332     }
333 
334     /**
335      * Tests if entities are to be GZIP compressed ({@code true}), or not ({@code false}).
336      *
337      * @return {@code true} if entity is to be GZIP compressed, {@code false} otherwise.
338      */
339     public boolean isGzipCompressed() {
340         return gzipCompressed;
341     }
342 
343     /**
344      * Sets entities to be GZIP compressed.
345      *
346      * @return this
347      */
348     public EntityBuilder gzipCompressed() {
349         this.gzipCompressed = true;
350         return this;
351     }
352 
353     private ContentType getContentOrDefault(final ContentType def) {
354         return this.contentType != null ? this.contentType : def;
355     }
356 
357     /**
358      * Builds a new instance of {@link HttpEntity} based on the current state.
359      *
360      * @return a new instance.
361      */
362     public HttpEntity build() {
363         final AbstractHttpEntity e;
364         if (this.text != null) {
365             e = new StringEntity(this.text, getContentOrDefault(ContentType.DEFAULT_TEXT), this.contentEncoding,
366                 this.chunked);
367         } else if (this.binary != null) {
368             e = new ByteArrayEntity(this.binary, getContentOrDefault(ContentType.DEFAULT_BINARY),
369                 this.contentEncoding, this.chunked);
370         } else if (this.stream != null) {
371             e = new InputStreamEntity(this.stream, -1, getContentOrDefault(ContentType.DEFAULT_BINARY),
372                 this.contentEncoding);
373         } else if (this.parameters != null) {
374             e = new UrlEncodedFormEntity(this.parameters,
375                     this.contentType != null ? this.contentType.getCharset() : null);
376         } else if (this.serializable != null) {
377             e = new SerializableEntity(this.serializable, ContentType.DEFAULT_BINARY, this.contentEncoding);
378         } else if (this.file != null) {
379             e = new FileEntity(this.file, getContentOrDefault(ContentType.DEFAULT_BINARY), this.contentEncoding);
380         } else {
381             throw new IllegalStateException("No entity set");
382         }
383         if (this.gzipCompressed) {
384             return new GzipCompressingEntity(e);
385         }
386         return e;
387     }
388 
389 }