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.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             } 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
113     public void consumeContent() throws IOException {
114         ensureConsumed();
115     }
116 
117     @Override
118     public void writeTo(final OutputStream outstream) throws IOException {
119         super.writeTo(outstream);
120         ensureConsumed();
121     }
122 
123     public void releaseConnection() throws IOException {
124         ensureConsumed();
125     }
126 
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     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 
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 
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      */
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 }