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             }
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 }