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