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