View Javadoc
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.entity.HttpEntityWrapper;
36  import org.apache.http.util.Args;
37  import org.apache.http.util.EntityUtils;
38  
39  /**
40   * An entity that releases a {@link ManagedClientConnection connection}.
41   * A {@link ManagedClientConnection} will
42   * typically <i>not</i> return a managed entity, but you can replace
43   * the unmanaged entity in the response with a managed one.
44   *
45   * @since 4.0
46   *
47   * @deprecated (4.3) do not use.
48   */
49  @Deprecated
50  public class BasicManagedEntity extends HttpEntityWrapper
51      implements ConnectionReleaseTrigger, EofSensorWatcher {
52  
53      /** The connection to release. */
54      protected ManagedClientConnection managedConn;
55  
56      /** Whether to keep the connection alive. */
57      protected final boolean attemptReuse;
58  
59      /**
60       * Creates a new managed entity that can release a connection.
61       *
62       * @param entity    the entity of which to wrap the content.
63       *                  Note that the argument entity can no longer be used
64       *                  afterwards, since the content will be taken by this
65       *                  managed entity.
66       * @param conn      the connection to release
67       * @param reuse     whether the connection should be re-used
68       */
69      public BasicManagedEntity(final HttpEntity entity,
70                                final ManagedClientConnection conn,
71                                final boolean reuse) {
72          super(entity);
73          Args.notNull(conn, "Connection");
74          this.managedConn = conn;
75          this.attemptReuse = reuse;
76      }
77  
78      @Override
79      public boolean isRepeatable() {
80          return false;
81      }
82  
83      @Override
84      public InputStream getContent() throws IOException {
85          return new EofSensorInputStream(wrappedEntity.getContent(), this);
86      }
87  
88      private void ensureConsumed() throws IOException {
89          if (managedConn == null) {
90              return;
91          }
92  
93          try {
94              if (attemptReuse) {
95                  // this will not trigger a callback from EofSensorInputStream
96                  EntityUtils.consume(wrappedEntity);
97                  managedConn.markReusable();
98              } else {
99                  managedConn.unmarkReusable();
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     @Override
122     public void releaseConnection() throws IOException {
123         ensureConsumed();
124     }
125 
126     @Override
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 
138     @Override
139     public boolean eofDetected(final InputStream wrapped) throws IOException {
140         try {
141             if (managedConn != null) {
142                 if (attemptReuse) {
143                     // there may be some cleanup required, such as
144                     // reading trailers after the response body:
145                     wrapped.close();
146                     managedConn.markReusable();
147                 } else {
148                     managedConn.unmarkReusable();
149                 }
150             }
151         } finally {
152             releaseManagedConnection();
153         }
154         return false;
155     }
156 
157     @Override
158     public boolean streamClosed(final InputStream wrapped) throws IOException {
159         try {
160             if (managedConn != null) {
161                 if (attemptReuse) {
162                     final boolean valid = managedConn.isOpen();
163                     // this assumes that closing the stream will
164                     // consume the remainder of the response body:
165                     try {
166                         wrapped.close();
167                         managedConn.markReusable();
168                     } catch (final SocketException ex) {
169                         if (valid) {
170                             throw ex;
171                         }
172                     }
173                 } else {
174                     managedConn.unmarkReusable();
175                 }
176             }
177         } finally {
178             releaseManagedConnection();
179         }
180         return false;
181     }
182 
183     @Override
184     public boolean streamAbort(final InputStream wrapped) throws IOException {
185         if (managedConn != null) {
186             managedConn.abortConnection();
187         }
188         return false;
189     }
190 
191     /**
192      * Releases the connection gracefully.
193      * The connection attribute will be nullified.
194      * Subsequent invocations are no-ops.
195      *
196      * @throws IOException      in case of an IO problem.
197      *         The connection attribute will be nullified anyway.
198      */
199     protected void releaseManagedConnection()
200         throws IOException {
201 
202         if (managedConn != null) {
203             try {
204                 managedConn.releaseConnection();
205             } finally {
206                 managedConn = null;
207             }
208         }
209     }
210 
211 }