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.WWWFormCodec;
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 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 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)) != -1 && buffer.length() < maxResultLength) {
162 buffer.append(tmp, 0, l);
163 }
164 buffer.setLength(Math.min(buffer.length(), maxResultLength));
165 return buffer.toByteArray();
166 }
167 }
168
169 private static CharArrayBuffer toCharArrayBuffer(final InputStream inStream, final int contentLength,
170 final Charset charset, final int maxResultLength) throws IOException {
171 Args.notNull(inStream, "InputStream");
172 Args.positive(maxResultLength, "maxResultLength");
173 final Charset actualCharset = charset == null ? DEFAULT_CHARSET : charset;
174 final CharArrayBuffer buf = new CharArrayBuffer(
175 Math.min(maxResultLength, contentLength > 0 ? contentLength : DEFAULT_CHAR_BUFFER_SIZE));
176 final Reader reader = new InputStreamReader(inStream, actualCharset);
177 final char[] tmp = new char[DEFAULT_CHAR_BUFFER_SIZE];
178 int chReadCount;
179 while ((chReadCount = reader.read(tmp)) != -1 && buf.length() < maxResultLength) {
180 buf.append(tmp, 0, chReadCount);
181 }
182 buf.setLength(Math.min(buf.length(), maxResultLength));
183 return buf;
184 }
185
186 private static final Map<String, ContentType> CONTENT_TYPE_MAP;
187 static {
188 final ContentType[] contentTypes = {
189 ContentType.APPLICATION_ATOM_XML,
190 ContentType.APPLICATION_FORM_URLENCODED,
191 ContentType.APPLICATION_JSON,
192 ContentType.APPLICATION_SVG_XML,
193 ContentType.APPLICATION_XHTML_XML,
194 ContentType.APPLICATION_XML,
195 ContentType.MULTIPART_FORM_DATA,
196 ContentType.TEXT_HTML,
197 ContentType.TEXT_PLAIN,
198 ContentType.TEXT_XML };
199 final HashMap<String, ContentType> map = new HashMap<>();
200 for (final ContentType contentType: contentTypes) {
201 map.put(contentType.getMimeType(), contentType);
202 }
203 CONTENT_TYPE_MAP = Collections.unmodifiableMap(map);
204 }
205
206 private static String toString(final HttpEntity entity, final ContentType contentType, final int maxResultLength)
207 throws IOException {
208 Args.notNull(entity, "HttpEntity");
209 final int contentLength = toContentLength((int) Args.checkContentLength(entity));
210 try (final InputStream inStream = entity.getContent()) {
211 if (inStream == null) {
212 return null;
213 }
214 Charset charset = null;
215 if (contentType != null) {
216 charset = contentType.getCharset();
217 if (charset == null) {
218 final ContentType defaultContentType = CONTENT_TYPE_MAP.get(contentType.getMimeType());
219 charset = defaultContentType != null ? defaultContentType.getCharset() : null;
220 }
221 }
222 return toCharArrayBuffer(inStream, contentLength, charset, maxResultLength).toString();
223 }
224 }
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242 public static String toString(
243 final HttpEntity entity, final Charset defaultCharset) throws IOException, ParseException {
244 return toString(entity, defaultCharset, DEFAULT_ENTITY_RETURN_MAX_LENGTH);
245 }
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265 public static String toString(
266 final HttpEntity entity, final Charset defaultCharset, final int maxResultLength) throws IOException, ParseException {
267 Args.notNull(entity, "HttpEntity");
268 ContentType contentType = null;
269 try {
270 contentType = ContentType.parse(entity.getContentType());
271 } catch (final UnsupportedCharsetException ex) {
272 if (defaultCharset == null) {
273 throw new UnsupportedEncodingException(ex.getMessage());
274 }
275 }
276 if (contentType != null) {
277 if (contentType.getCharset() == null) {
278 contentType = contentType.withCharset(defaultCharset);
279 }
280 } else {
281 contentType = ContentType.DEFAULT_TEXT.withCharset(defaultCharset);
282 }
283 return toString(entity, contentType, maxResultLength);
284 }
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301 public static String toString(
302 final HttpEntity entity, final String defaultCharset) throws IOException, ParseException {
303 return toString(entity, defaultCharset, DEFAULT_ENTITY_RETURN_MAX_LENGTH);
304 }
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323 public static String toString(
324 final HttpEntity entity, final String defaultCharset, final int maxResultLength) throws IOException, ParseException {
325 return toString(entity, defaultCharset != null ? Charset.forName(defaultCharset) : null, maxResultLength);
326 }
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341 public static String toString(final HttpEntity entity) throws IOException, ParseException {
342 return toString(entity, DEFAULT_ENTITY_RETURN_MAX_LENGTH);
343 }
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360 public static String toString(final HttpEntity entity, final int maxResultLength) throws IOException, ParseException {
361 Args.notNull(entity, "HttpEntity");
362 return toString(entity, ContentType.parse(entity.getContentType()), maxResultLength);
363 }
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378 public static List<NameValuePair> parse(final HttpEntity entity) throws IOException {
379 return parse(entity, DEFAULT_ENTITY_RETURN_MAX_LENGTH);
380 }
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397 public static List<NameValuePair> parse(final HttpEntity entity, final int maxStreamLength) throws IOException {
398 Args.notNull(entity, "HttpEntity");
399 final int contentLength = toContentLength((int) Args.checkContentLength(entity));
400 final ContentType contentType = ContentType.parse(entity.getContentType());
401 if (!ContentType.APPLICATION_FORM_URLENCODED.isSameMimeType(contentType)) {
402 return Collections.emptyList();
403 }
404 final Charset charset = contentType.getCharset(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 WWWFormCodec.parse(buf, charset);
417 }
418
419 }