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 package org.apache.hc.core5.http.io.entity;
29
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.InputStreamReader;
33 import java.io.Reader;
34 import java.io.UnsupportedEncodingException;
35 import java.nio.charset.Charset;
36 import java.nio.charset.StandardCharsets;
37 import java.nio.charset.UnsupportedCharsetException;
38 import java.util.Collections;
39 import java.util.HashMap;
40 import java.util.List;
41 import java.util.Map;
42
43 import org.apache.hc.core5.http.ContentType;
44 import org.apache.hc.core5.http.EntityDetails;
45 import org.apache.hc.core5.http.HttpEntity;
46 import org.apache.hc.core5.http.NameValuePair;
47 import org.apache.hc.core5.http.ParseException;
48 import org.apache.hc.core5.io.Closer;
49 import org.apache.hc.core5.net.WWWFormCodec;
50 import org.apache.hc.core5.util.Args;
51 import org.apache.hc.core5.util.ByteArrayBuffer;
52 import org.apache.hc.core5.util.CharArrayBuffer;
53
54
55
56
57
58
59 public final class EntityUtils {
60
61
62 private static final int DEFAULT_ENTITY_RETURN_MAX_LENGTH = Integer.MAX_VALUE;
63 private static final Charset DEFAULT_CHARSET = StandardCharsets.ISO_8859_1;
64 private static final int DEFAULT_CHAR_BUFFER_SIZE = 1024;
65 private static final int DEFAULT_BYTE_BUFFER_SIZE = 4096;
66
67 private EntityUtils() {
68
69 }
70
71
72
73
74
75
76
77
78
79 public static void consumeQuietly(final HttpEntity entity) {
80 try {
81 consume(entity);
82 } catch (final IOException ignore) {
83
84 }
85 }
86
87
88
89
90
91
92
93
94
95
96 public static void consume(final HttpEntity entity) throws IOException {
97 if (entity == null) {
98 return;
99 }
100 if (entity.isStreaming()) {
101 Closer.close(entity.getContent());
102 }
103 }
104
105
106
107
108
109
110
111 private static int toContentLength(final int contentLength) {
112 return contentLength < 0 ? DEFAULT_BYTE_BUFFER_SIZE : contentLength;
113 }
114
115 static long checkContentLength(final EntityDetails entityDetails) {
116
117
118
119 return Args.checkRange(entityDetails.getContentLength(), -1, Integer.MAX_VALUE,
120 "HTTP entity too large to be buffered in memory)");
121 }
122
123
124
125
126
127
128
129
130
131
132 public static byte[] toByteArray(final HttpEntity entity) throws IOException {
133 Args.notNull(entity, "HttpEntity");
134 final int contentLength = toContentLength((int) checkContentLength(entity));
135 try (final InputStream inStream = entity.getContent()) {
136 if (inStream == null) {
137 return null;
138 }
139 final ByteArrayBuffer buffer = new ByteArrayBuffer(contentLength);
140 final byte[] tmp = new byte[DEFAULT_BYTE_BUFFER_SIZE];
141 int l;
142 while ((l = inStream.read(tmp)) != -1) {
143 buffer.append(tmp, 0, l);
144 }
145 return buffer.toByteArray();
146 }
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160 public static byte[] toByteArray(final HttpEntity entity, final int maxResultLength) throws IOException {
161 Args.notNull(entity, "HttpEntity");
162 final int contentLength = toContentLength((int) checkContentLength(entity));
163 try (final InputStream inStream = entity.getContent()) {
164 if (inStream == null) {
165 return null;
166 }
167 final ByteArrayBuffer buffer = new ByteArrayBuffer(Math.min(maxResultLength, contentLength));
168 final byte[] tmp = new byte[DEFAULT_BYTE_BUFFER_SIZE];
169 int l;
170 while ((l = inStream.read(tmp)) != -1 && buffer.length() < maxResultLength) {
171 buffer.append(tmp, 0, l);
172 }
173 buffer.setLength(Math.min(buffer.length(), maxResultLength));
174 return buffer.toByteArray();
175 }
176 }
177
178 private static CharArrayBuffer toCharArrayBuffer(final InputStream inStream, final int contentLength,
179 final Charset charset, final int maxResultLength) throws IOException {
180 Args.notNull(inStream, "InputStream");
181 Args.positive(maxResultLength, "maxResultLength");
182 final Charset actualCharset = charset == null ? DEFAULT_CHARSET : charset;
183 final CharArrayBuffer buf = new CharArrayBuffer(
184 Math.min(maxResultLength, contentLength > 0 ? contentLength : DEFAULT_CHAR_BUFFER_SIZE));
185 final Reader reader = new InputStreamReader(inStream, actualCharset);
186 final char[] tmp = new char[DEFAULT_CHAR_BUFFER_SIZE];
187 int chReadCount;
188 while ((chReadCount = reader.read(tmp)) != -1 && buf.length() < maxResultLength) {
189 buf.append(tmp, 0, chReadCount);
190 }
191 buf.setLength(Math.min(buf.length(), maxResultLength));
192 return buf;
193 }
194
195 private static final Map<String, ContentType> CONTENT_TYPE_MAP;
196 static {
197 final ContentType[] contentTypes = {
198 ContentType.APPLICATION_ATOM_XML,
199 ContentType.APPLICATION_FORM_URLENCODED,
200 ContentType.APPLICATION_JSON,
201 ContentType.APPLICATION_SVG_XML,
202 ContentType.APPLICATION_XHTML_XML,
203 ContentType.APPLICATION_XML,
204 ContentType.MULTIPART_FORM_DATA,
205 ContentType.TEXT_HTML,
206 ContentType.TEXT_PLAIN,
207 ContentType.TEXT_XML };
208 final HashMap<String, ContentType> map = new HashMap<>();
209 for (final ContentType contentType: contentTypes) {
210 map.put(contentType.getMimeType(), contentType);
211 }
212 CONTENT_TYPE_MAP = Collections.unmodifiableMap(map);
213 }
214
215 private static String toString(final HttpEntity entity, final ContentType contentType, final int maxResultLength)
216 throws IOException {
217 Args.notNull(entity, "HttpEntity");
218 final int contentLength = toContentLength((int) checkContentLength(entity));
219 try (final InputStream inStream = entity.getContent()) {
220 if (inStream == null) {
221 return null;
222 }
223 Charset charset = null;
224 if (contentType != null) {
225 charset = contentType.getCharset();
226 if (charset == null) {
227 final ContentType defaultContentType = CONTENT_TYPE_MAP.get(contentType.getMimeType());
228 charset = defaultContentType != null ? defaultContentType.getCharset() : null;
229 }
230 }
231 return toCharArrayBuffer(inStream, contentLength, charset, maxResultLength).toString();
232 }
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251 public static String toString(
252 final HttpEntity entity, final Charset defaultCharset) throws IOException, ParseException {
253 return toString(entity, defaultCharset, DEFAULT_ENTITY_RETURN_MAX_LENGTH);
254 }
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274 public static String toString(
275 final HttpEntity entity, final Charset defaultCharset, final int maxResultLength) throws IOException, ParseException {
276 Args.notNull(entity, "HttpEntity");
277 ContentType contentType = null;
278 try {
279 contentType = ContentType.parse(entity.getContentType());
280 } catch (final UnsupportedCharsetException ex) {
281 if (defaultCharset == null) {
282 throw new UnsupportedEncodingException(ex.getMessage());
283 }
284 }
285 if (contentType != null) {
286 if (contentType.getCharset() == null) {
287 contentType = contentType.withCharset(defaultCharset);
288 }
289 } else {
290 contentType = ContentType.DEFAULT_TEXT.withCharset(defaultCharset);
291 }
292 return toString(entity, contentType, maxResultLength);
293 }
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310 public static String toString(
311 final HttpEntity entity, final String defaultCharset) throws IOException, ParseException {
312 return toString(entity, defaultCharset, DEFAULT_ENTITY_RETURN_MAX_LENGTH);
313 }
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332 public static String toString(
333 final HttpEntity entity, final String defaultCharset, final int maxResultLength) throws IOException, ParseException {
334 return toString(entity, defaultCharset != null ? Charset.forName(defaultCharset) : null, maxResultLength);
335 }
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350 public static String toString(final HttpEntity entity) throws IOException, ParseException {
351 return toString(entity, DEFAULT_ENTITY_RETURN_MAX_LENGTH);
352 }
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369 public static String toString(final HttpEntity entity, final int maxResultLength) throws IOException, ParseException {
370 Args.notNull(entity, "HttpEntity");
371 return toString(entity, ContentType.parse(entity.getContentType()), maxResultLength);
372 }
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387 public static List<NameValuePair> parse(final HttpEntity entity) throws IOException {
388 return parse(entity, DEFAULT_ENTITY_RETURN_MAX_LENGTH);
389 }
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406 public static List<NameValuePair> parse(final HttpEntity entity, final int maxStreamLength) throws IOException {
407 Args.notNull(entity, "HttpEntity");
408 final int contentLength = toContentLength((int) checkContentLength(entity));
409 final ContentType contentType = ContentType.parse(entity.getContentType());
410 if (!ContentType.APPLICATION_FORM_URLENCODED.isSameMimeType(contentType)) {
411 return Collections.emptyList();
412 }
413 final Charset charset = contentType.getCharset(DEFAULT_CHARSET);
414 final CharArrayBuffer buf;
415 try (final InputStream inStream = entity.getContent()) {
416 if (inStream == null) {
417 return Collections.emptyList();
418 }
419 buf = toCharArrayBuffer(inStream, contentLength, charset, maxStreamLength);
420
421 }
422 if (buf.isEmpty()) {
423 return Collections.emptyList();
424 }
425 return WWWFormCodec.parse(buf, charset);
426 }
427
428 }