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.http.impl.execchain;
29
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.OutputStream;
33 import java.net.SocketException;
34
35 import org.apache.http.HttpEntity;
36 import org.apache.http.HttpResponse;
37 import org.apache.http.conn.EofSensorInputStream;
38 import org.apache.http.conn.EofSensorWatcher;
39 import org.apache.http.entity.HttpEntityWrapper;
40
41
42
43
44
45
46 class ResponseEntityProxy extends HttpEntityWrapper implements EofSensorWatcher {
47
48 private final ConnectionHolder connHolder;
49
50 public static void enchance(final HttpResponse response, final ConnectionHolder connHolder) {
51 final HttpEntity entity = response.getEntity();
52 if (entity != null && entity.isStreaming() && connHolder != null) {
53 response.setEntity(new ResponseEntityProxy(entity, connHolder));
54 }
55 }
56
57 ResponseEntityProxy(final HttpEntity entity, final ConnectionHolder connHolder) {
58 super(entity);
59 this.connHolder = connHolder;
60 }
61
62 private void cleanup() throws IOException {
63 if (this.connHolder != null) {
64 this.connHolder.close();
65 }
66 }
67
68 private void abortConnection() {
69 if (this.connHolder != null) {
70 this.connHolder.abortConnection();
71 }
72 }
73
74 public void releaseConnection() {
75 if (this.connHolder != null) {
76 this.connHolder.releaseConnection();
77 }
78 }
79
80 @Override
81 public boolean isRepeatable() {
82 return false;
83 }
84
85 @Override
86 public InputStream getContent() throws IOException {
87 return new EofSensorInputStream(this.wrappedEntity.getContent(), this);
88 }
89
90 @Override
91 public void consumeContent() throws IOException {
92 releaseConnection();
93 }
94
95 @Override
96 public void writeTo(final OutputStream outStream) throws IOException {
97 try {
98 if (outStream != null) {
99 this.wrappedEntity.writeTo(outStream);
100 }
101 releaseConnection();
102 } catch (final IOException ex) {
103 abortConnection();
104 throw ex;
105 } catch (final RuntimeException ex) {
106 abortConnection();
107 throw ex;
108 } finally {
109 cleanup();
110 }
111 }
112
113 @Override
114 public boolean eofDetected(final InputStream wrapped) throws IOException {
115 try {
116
117
118 if (wrapped != null) {
119 wrapped.close();
120 }
121 releaseConnection();
122 } catch (final IOException ex) {
123 abortConnection();
124 throw ex;
125 } catch (final RuntimeException ex) {
126 abortConnection();
127 throw ex;
128 } finally {
129 cleanup();
130 }
131 return false;
132 }
133
134 @Override
135 public boolean streamClosed(final InputStream wrapped) throws IOException {
136 try {
137 final boolean open = connHolder != null && !connHolder.isReleased();
138
139
140 try {
141 if (wrapped != null) {
142 wrapped.close();
143 }
144 releaseConnection();
145 } catch (final SocketException ex) {
146 if (open) {
147 throw ex;
148 }
149 }
150 } catch (final IOException ex) {
151 abortConnection();
152 throw ex;
153 } catch (final RuntimeException ex) {
154 abortConnection();
155 throw ex;
156 } finally {
157 cleanup();
158 }
159 return false;
160 }
161
162 @Override
163 public boolean streamAbort(final InputStream wrapped) throws IOException {
164 cleanup();
165 return false;
166 }
167
168 @Override
169 public String toString() {
170 final StringBuilder sb = new StringBuilder("ResponseEntityProxy{");
171 sb.append(wrappedEntity);
172 sb.append('}');
173 return sb.toString();
174 }
175
176 }