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 package org.apache.http.impl.client.cache;
28
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.lang.reflect.Proxy;
32
33 import org.apache.http.HttpEntity;
34 import org.apache.http.HttpRequest;
35 import org.apache.http.HttpResponse;
36 import org.apache.http.client.cache.InputLimit;
37 import org.apache.http.client.cache.Resource;
38 import org.apache.http.client.cache.ResourceFactory;
39 import org.apache.http.client.methods.CloseableHttpResponse;
40 import org.apache.http.message.BasicHttpResponse;
41
42
43
44
45 class SizeLimitedResponseReader {
46
47 private final ResourceFactory resourceFactory;
48 private final long maxResponseSizeBytes;
49 private final HttpRequest request;
50 private final CloseableHttpResponse response;
51
52 private InputStream inStream;
53 private InputLimit limit;
54 private Resource resource;
55 private boolean consumed;
56
57
58
59
60
61 public SizeLimitedResponseReader(
62 final ResourceFactory resourceFactory,
63 final long maxResponseSizeBytes,
64 final HttpRequest request,
65 final CloseableHttpResponse response) {
66 super();
67 this.resourceFactory = resourceFactory;
68 this.maxResponseSizeBytes = maxResponseSizeBytes;
69 this.request = request;
70 this.response = response;
71 }
72
73 protected void readResponse() throws IOException {
74 if (!consumed) {
75 doConsume();
76 }
77 }
78
79 private void ensureNotConsumed() {
80 if (consumed) {
81 throw new IllegalStateException("Response has already been consumed");
82 }
83 }
84
85 private void ensureConsumed() {
86 if (!consumed) {
87 throw new IllegalStateException("Response has not been consumed");
88 }
89 }
90
91 private void doConsume() throws IOException {
92 ensureNotConsumed();
93 consumed = true;
94
95 limit = new InputLimit(maxResponseSizeBytes);
96
97 final HttpEntity entity = response.getEntity();
98 if (entity == null) {
99 return;
100 }
101 final String uri = request.getRequestLine().getUri();
102 inStream = entity.getContent();
103 try {
104 resource = resourceFactory.generate(uri, inStream, limit);
105 } finally {
106 if (!limit.isReached()) {
107 inStream.close();
108 }
109 }
110 }
111
112 boolean isLimitReached() {
113 ensureConsumed();
114 return limit.isReached();
115 }
116
117 Resource getResource() {
118 ensureConsumed();
119 return resource;
120 }
121
122 CloseableHttpResponse getReconstructedResponse() throws IOException {
123 ensureConsumed();
124 final HttpResponse reconstructed = new BasicHttpResponse(response.getStatusLine());
125 reconstructed.setHeaders(response.getAllHeaders());
126
127 final CombinedEntityinedEntity.html#CombinedEntity">CombinedEntity combinedEntity = new CombinedEntity(resource, inStream);
128 final HttpEntity entity = response.getEntity();
129 if (entity != null) {
130 combinedEntity.setContentType(entity.getContentType());
131 combinedEntity.setContentEncoding(entity.getContentEncoding());
132 combinedEntity.setChunked(entity.isChunked());
133 }
134 reconstructed.setEntity(combinedEntity);
135 return (CloseableHttpResponse) Proxy.newProxyInstance(
136 ResponseProxyHandler.class.getClassLoader(),
137 new Class<?>[] { CloseableHttpResponse.class },
138 new ResponseProxyHandler(reconstructed) {
139
140 @Override
141 public void close() throws IOException {
142 response.close();
143 }
144
145 });
146 }
147
148 }