1 /*
2 * ====================================================================
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 * ====================================================================
20 *
21 * This software consists of voluntary contributions made by many
22 * individuals on behalf of the Apache Software Foundation. For more
23 * information on the Apache Software Foundation, please see
24 * <http://www.apache.org/>.
25 *
26 */
27 package org.apache.http.conn;
28
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.io.OutputStream;
32 import java.net.SocketException;
33
34 import org.apache.http.HttpEntity;
35 import org.apache.http.annotation.NotThreadSafe;
36 import org.apache.http.entity.HttpEntityWrapper;
37 import org.apache.http.util.Args;
38 import org.apache.http.util.EntityUtils;
39
40 /**
41 * An entity that releases a {@link ManagedClientConnection connection}.
42 * A {@link ManagedClientConnection} will
43 * typically <i>not</i> return a managed entity, but you can replace
44 * the unmanaged entity in the response with a managed one.
45 *
46 * @since 4.0
47 *
48 * @deprecated (4.3) do not use.
49 */
50 @Deprecated
51 @NotThreadSafe
52 public class BasicManagedEntity extends HttpEntityWrapper
53 implements ConnectionReleaseTrigger, EofSensorWatcher {
54
55 /** The connection to release. */
56 protected ManagedClientConnection managedConn;
57
58 /** Whether to keep the connection alive. */
59 protected final boolean attemptReuse;
60
61 /**
62 * Creates a new managed entity that can release a connection.
63 *
64 * @param entity the entity of which to wrap the content.
65 * Note that the argument entity can no longer be used
66 * afterwards, since the content will be taken by this
67 * managed entity.
68 * @param conn the connection to release
69 * @param reuse whether the connection should be re-used
70 */
71 public BasicManagedEntity(final HttpEntity entity,
72 final ManagedClientConnection conn,
73 final boolean reuse) {
74 super(entity);
75 Args.notNull(conn, "Connection");
76 this.managedConn = conn;
77 this.attemptReuse = reuse;
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(wrappedEntity.getContent(), this);
88 }
89
90 private void ensureConsumed() throws IOException {
91 if (managedConn == null) {
92 return;
93 }
94
95 try {
96 if (attemptReuse) {
97 // this will not trigger a callback from EofSensorInputStream
98 EntityUtils.consume(wrappedEntity);
99 managedConn.markReusable();
100 }
101 } finally {
102 releaseManagedConnection();
103 }
104 }
105
106 /**
107 * @deprecated (4.1) Use {@link EntityUtils#consume(HttpEntity)}
108 */
109 @Deprecated
110 @Override
111 public void consumeContent() throws IOException {
112 ensureConsumed();
113 }
114
115 @Override
116 public void writeTo(final OutputStream outstream) throws IOException {
117 super.writeTo(outstream);
118 ensureConsumed();
119 }
120
121 public void releaseConnection() throws IOException {
122 ensureConsumed();
123 }
124
125 public void abortConnection() throws IOException {
126
127 if (managedConn != null) {
128 try {
129 managedConn.abortConnection();
130 } finally {
131 managedConn = null;
132 }
133 }
134 }
135
136 public boolean eofDetected(final InputStream wrapped) throws IOException {
137 try {
138 if (attemptReuse && (managedConn != null)) {
139 // there may be some cleanup required, such as
140 // reading trailers after the response body:
141 wrapped.close();
142 managedConn.markReusable();
143 }
144 } finally {
145 releaseManagedConnection();
146 }
147 return false;
148 }
149
150 public boolean streamClosed(final InputStream wrapped) throws IOException {
151 try {
152 if (attemptReuse && (managedConn != null)) {
153 final boolean valid = managedConn.isOpen();
154 // this assumes that closing the stream will
155 // consume the remainder of the response body:
156 try {
157 wrapped.close();
158 managedConn.markReusable();
159 } catch (final SocketException ex) {
160 if (valid) {
161 throw ex;
162 }
163 }
164 }
165 } finally {
166 releaseManagedConnection();
167 }
168 return false;
169 }
170
171 public boolean streamAbort(final InputStream wrapped) throws IOException {
172 if (managedConn != null) {
173 managedConn.abortConnection();
174 }
175 return false;
176 }
177
178 /**
179 * Releases the connection gracefully.
180 * The connection attribute will be nullified.
181 * Subsequent invocations are no-ops.
182 *
183 * @throws IOException in case of an IO problem.
184 * The connection attribute will be nullified anyway.
185 */
186 protected void releaseManagedConnection()
187 throws IOException {
188
189 if (managedConn != null) {
190 try {
191 managedConn.releaseConnection();
192 } finally {
193 managedConn = null;
194 }
195 }
196 }
197
198 }