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 ch.boye.httpclientandroidlib.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 ch.boye.httpclientandroidlib.HttpEntity; 35 import ch.boye.httpclientandroidlib.annotation.NotThreadSafe; 36 import ch.boye.httpclientandroidlib.entity.HttpEntityWrapper; 37 import ch.boye.httpclientandroidlib.util.Args; 38 import ch.boye.httpclientandroidlib.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 */ BasicManagedEntity(final HttpEntity entity, final ManagedClientConnection conn, final boolean reuse)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 isRepeatable()81 public boolean isRepeatable() { 82 return false; 83 } 84 85 @Override getContent()86 public InputStream getContent() throws IOException { 87 return new EofSensorInputStream(wrappedEntity.getContent(), this); 88 } 89 ensureConsumed()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 } else { 101 managedConn.unmarkReusable(); 102 } 103 } finally { 104 releaseManagedConnection(); 105 } 106 } 107 108 /** 109 * @deprecated (4.1) Use {@link EntityUtils#consume(HttpEntity)} 110 */ 111 @Deprecated 112 @Override consumeContent()113 public void consumeContent() throws IOException { 114 ensureConsumed(); 115 } 116 117 @Override writeTo(final OutputStream outstream)118 public void writeTo(final OutputStream outstream) throws IOException { 119 super.writeTo(outstream); 120 ensureConsumed(); 121 } 122 releaseConnection()123 public void releaseConnection() throws IOException { 124 ensureConsumed(); 125 } 126 abortConnection()127 public void abortConnection() throws IOException { 128 129 if (managedConn != null) { 130 try { 131 managedConn.abortConnection(); 132 } finally { 133 managedConn = null; 134 } 135 } 136 } 137 eofDetected(final InputStream wrapped)138 public boolean eofDetected(final InputStream wrapped) throws IOException { 139 try { 140 if (managedConn != null) { 141 if (attemptReuse) { 142 // there may be some cleanup required, such as 143 // reading trailers after the response body: 144 wrapped.close(); 145 managedConn.markReusable(); 146 } else { 147 managedConn.unmarkReusable(); 148 } 149 } 150 } finally { 151 releaseManagedConnection(); 152 } 153 return false; 154 } 155 streamClosed(final InputStream wrapped)156 public boolean streamClosed(final InputStream wrapped) throws IOException { 157 try { 158 if (managedConn != null) { 159 if (attemptReuse) { 160 final boolean valid = managedConn.isOpen(); 161 // this assumes that closing the stream will 162 // consume the remainder of the response body: 163 try { 164 wrapped.close(); 165 managedConn.markReusable(); 166 } catch (final SocketException ex) { 167 if (valid) { 168 throw ex; 169 } 170 } 171 } else { 172 managedConn.unmarkReusable(); 173 } 174 } 175 } finally { 176 releaseManagedConnection(); 177 } 178 return false; 179 } 180 streamAbort(final InputStream wrapped)181 public boolean streamAbort(final InputStream wrapped) throws IOException { 182 if (managedConn != null) { 183 managedConn.abortConnection(); 184 } 185 return false; 186 } 187 188 /** 189 * Releases the connection gracefully. 190 * The connection attribute will be nullified. 191 * Subsequent invocations are no-ops. 192 * 193 * @throws IOException in case of an IO problem. 194 * The connection attribute will be nullified anyway. 195 */ releaseManagedConnection()196 protected void releaseManagedConnection() 197 throws IOException { 198 199 if (managedConn != null) { 200 try { 201 managedConn.releaseConnection(); 202 } finally { 203 managedConn = null; 204 } 205 } 206 } 207 208 } 209