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     @Override
124     public void releaseConnection() throws IOException {
125         ensureConsumed();
126     }
127 
128     @Override
129     public void abortConnection() throws IOException {
130 
131         if (managedConn != null) {
132             try {
133                 managedConn.abortConnection();
134             } finally {
135                 managedConn = null;
136             }
137         }
138     }
139 
140     @Override
141     public boolean eofDetected(final InputStream wrapped) throws IOException {
142         try {
143             if (managedConn != null) {
144                 if (attemptReuse) {
145                     // there may be some cleanup required, such as
146                     // reading trailers after the response body:
147                     wrapped.close();
148                     managedConn.markReusable();
149                 } else {
150                     managedConn.unmarkReusable();
151                 }
152             }
153         } finally {
154             releaseManagedConnection();
155         }
156         return false;
157     }
158 
159     @Override
160     public boolean streamClosed(final InputStream wrapped) throws IOException {
161         try {
162             if (managedConn != null) {
163                 if (attemptReuse) {
164                     final boolean valid = managedConn.isOpen();
165                     // this assumes that closing the stream will
166                     // consume the remainder of the response body:
167                     try {
168                         wrapped.close();
169                         managedConn.markReusable();
170                     } catch (final SocketException ex) {
171                         if (valid) {
172                             throw ex;
173                         }
174                     }
175                 } else {
176                     managedConn.unmarkReusable();
177                 }
178             }
179         } finally {
180             releaseManagedConnection();
181         }
182         return false;
183     }
184 
185     @Override
186     public boolean streamAbort(final InputStream wrapped) throws IOException {
187         if (managedConn != null) {
188             managedConn.abortConnection();
189         }
190         return false;
191     }
192 
193     /**
194      * Releases the connection gracefully.
195      * The connection attribute will be nullified.
196      * Subsequent invocations are no-ops.
197      *
198      * @throws IOException      in case of an IO problem.
199      *         The connection attribute will be nullified anyway.
200      */
201     protected void releaseManagedConnection()
202         throws IOException {
203 
204         if (managedConn != null) {
205             try {
206                 managedConn.releaseConnection();
207             } finally {
208                 managedConn = null;
209             }
210         }
211     }
212 
213 }