PageRenderTime 130ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 0ms

/src/org/apache/http/impl/conn/AbstractClientConnAdapter.java

https://github.com/MIPS/external-apache-http
Java | 399 lines | 204 code | 71 blank | 124 comment | 16 complexity | 9f7e5877a09be4c52a1b06b06ca59c8d MD5 | raw file
  1. /*
  2. * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/AbstractClientConnAdapter.java $
  3. * $Revision: 672969 $
  4. * $Date: 2008-06-30 18:09:50 -0700 (Mon, 30 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. package org.apache.http.impl.conn;
  31. import java.io.IOException;
  32. import java.io.InterruptedIOException;
  33. import java.net.InetAddress;
  34. import java.net.Socket;
  35. import java.util.concurrent.TimeUnit;
  36. import javax.net.ssl.SSLSocket;
  37. import javax.net.ssl.SSLSession;
  38. import org.apache.http.HttpException;
  39. import org.apache.http.HttpRequest;
  40. import org.apache.http.HttpEntityEnclosingRequest;
  41. import org.apache.http.HttpResponse;
  42. import org.apache.http.HttpConnectionMetrics;
  43. import org.apache.http.conn.OperatedClientConnection;
  44. import org.apache.http.conn.ManagedClientConnection;
  45. import org.apache.http.conn.ClientConnectionManager;
  46. /**
  47. * Abstract adapter from {@link OperatedClientConnection operated} to
  48. * {@link ManagedClientConnection managed} client connections.
  49. * Read and write methods are delegated to the wrapped connection.
  50. * Operations affecting the connection state have to be implemented
  51. * by derived classes. Operations for querying the connection state
  52. * are delegated to the wrapped connection if there is one, or
  53. * return a default value if there is none.
  54. * <br/>
  55. * This adapter tracks the checkpoints for reusable communication states,
  56. * as indicated by {@link #markReusable markReusable} and queried by
  57. * {@link #isMarkedReusable isMarkedReusable}.
  58. * All send and receive operations will automatically clear the mark.
  59. * <br/>
  60. * Connection release calls are delegated to the connection manager,
  61. * if there is one. {@link #abortConnection abortConnection} will
  62. * clear the reusability mark first. The connection manager is
  63. * expected to tolerate multiple calls to the release method.
  64. *
  65. * @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
  66. *
  67. *
  68. * <!-- empty lines to avoid svn diff problems -->
  69. * @version $Revision: 672969 $ $Date: 2008-06-30 18:09:50 -0700 (Mon, 30 Jun 2008) $
  70. *
  71. * @since 4.0
  72. */
  73. public abstract class AbstractClientConnAdapter
  74. implements ManagedClientConnection {
  75. /** Thread that requested this connection. */
  76. private final Thread executionThread;
  77. /**
  78. * The connection manager, if any.
  79. * This attribute MUST NOT be final, so the adapter can be detached
  80. * from the connection manager without keeping a hard reference there.
  81. */
  82. private volatile ClientConnectionManager connManager;
  83. /** The wrapped connection. */
  84. private volatile OperatedClientConnection wrappedConnection;
  85. /** The reusability marker. */
  86. private volatile boolean markedReusable;
  87. /** True if the connection has been aborted. */
  88. private volatile boolean aborted;
  89. /** The duration this is valid for while idle (in ms). */
  90. private volatile long duration;
  91. /**
  92. * Creates a new connection adapter.
  93. * The adapter is initially <i>not</i>
  94. * {@link #isMarkedReusable marked} as reusable.
  95. *
  96. * @param mgr the connection manager, or <code>null</code>
  97. * @param conn the connection to wrap, or <code>null</code>
  98. */
  99. protected AbstractClientConnAdapter(ClientConnectionManager mgr,
  100. OperatedClientConnection conn) {
  101. super();
  102. executionThread = Thread.currentThread();
  103. connManager = mgr;
  104. wrappedConnection = conn;
  105. markedReusable = false;
  106. aborted = false;
  107. duration = Long.MAX_VALUE;
  108. } // <constructor>
  109. /**
  110. * Detaches this adapter from the wrapped connection.
  111. * This adapter becomes useless.
  112. */
  113. protected void detach() {
  114. wrappedConnection = null;
  115. connManager = null; // base class attribute
  116. duration = Long.MAX_VALUE;
  117. }
  118. protected OperatedClientConnection getWrappedConnection() {
  119. return wrappedConnection;
  120. }
  121. protected ClientConnectionManager getManager() {
  122. return connManager;
  123. }
  124. /**
  125. * Asserts that the connection has not been aborted.
  126. *
  127. * @throws InterruptedIOException if the connection has been aborted
  128. */
  129. protected final void assertNotAborted() throws InterruptedIOException {
  130. if (aborted) {
  131. throw new InterruptedIOException("Connection has been shut down.");
  132. }
  133. }
  134. /**
  135. * Asserts that there is a wrapped connection to delegate to.
  136. *
  137. * @throws IllegalStateException if there is no wrapped connection
  138. * or connection has been aborted
  139. */
  140. protected final void assertValid(
  141. final OperatedClientConnection wrappedConn) {
  142. if (wrappedConn == null) {
  143. throw new IllegalStateException("No wrapped connection.");
  144. }
  145. }
  146. // non-javadoc, see interface HttpConnection
  147. public boolean isOpen() {
  148. OperatedClientConnection conn = getWrappedConnection();
  149. if (conn == null)
  150. return false;
  151. return conn.isOpen();
  152. }
  153. // non-javadoc, see interface HttpConnection
  154. public boolean isStale() {
  155. if (aborted)
  156. return true;
  157. OperatedClientConnection conn = getWrappedConnection();
  158. if (conn == null)
  159. return true;
  160. return conn.isStale();
  161. }
  162. // non-javadoc, see interface HttpConnection
  163. public void setSocketTimeout(int timeout) {
  164. OperatedClientConnection conn = getWrappedConnection();
  165. assertValid(conn);
  166. conn.setSocketTimeout(timeout);
  167. }
  168. // non-javadoc, see interface HttpConnection
  169. public int getSocketTimeout() {
  170. OperatedClientConnection conn = getWrappedConnection();
  171. assertValid(conn);
  172. return conn.getSocketTimeout();
  173. }
  174. // non-javadoc, see interface HttpConnection
  175. public HttpConnectionMetrics getMetrics() {
  176. OperatedClientConnection conn = getWrappedConnection();
  177. assertValid(conn);
  178. return conn.getMetrics();
  179. }
  180. // non-javadoc, see interface HttpClientConnection
  181. public void flush()
  182. throws IOException {
  183. assertNotAborted();
  184. OperatedClientConnection conn = getWrappedConnection();
  185. assertValid(conn);
  186. conn.flush();
  187. }
  188. // non-javadoc, see interface HttpClientConnection
  189. public boolean isResponseAvailable(int timeout)
  190. throws IOException {
  191. assertNotAborted();
  192. OperatedClientConnection conn = getWrappedConnection();
  193. assertValid(conn);
  194. return conn.isResponseAvailable(timeout);
  195. }
  196. // non-javadoc, see interface HttpClientConnection
  197. public void receiveResponseEntity(HttpResponse response)
  198. throws HttpException, IOException {
  199. assertNotAborted();
  200. OperatedClientConnection conn = getWrappedConnection();
  201. assertValid(conn);
  202. unmarkReusable();
  203. conn.receiveResponseEntity(response);
  204. }
  205. // non-javadoc, see interface HttpClientConnection
  206. public HttpResponse receiveResponseHeader()
  207. throws HttpException, IOException {
  208. assertNotAborted();
  209. OperatedClientConnection conn = getWrappedConnection();
  210. assertValid(conn);
  211. unmarkReusable();
  212. return conn.receiveResponseHeader();
  213. }
  214. // non-javadoc, see interface HttpClientConnection
  215. public void sendRequestEntity(HttpEntityEnclosingRequest request)
  216. throws HttpException, IOException {
  217. assertNotAborted();
  218. OperatedClientConnection conn = getWrappedConnection();
  219. assertValid(conn);
  220. unmarkReusable();
  221. conn.sendRequestEntity(request);
  222. }
  223. // non-javadoc, see interface HttpClientConnection
  224. public void sendRequestHeader(HttpRequest request)
  225. throws HttpException, IOException {
  226. assertNotAborted();
  227. OperatedClientConnection conn = getWrappedConnection();
  228. assertValid(conn);
  229. unmarkReusable();
  230. conn.sendRequestHeader(request);
  231. }
  232. // non-javadoc, see interface HttpInetConnection
  233. public InetAddress getLocalAddress() {
  234. OperatedClientConnection conn = getWrappedConnection();
  235. assertValid(conn);
  236. return conn.getLocalAddress();
  237. }
  238. // non-javadoc, see interface HttpInetConnection
  239. public int getLocalPort() {
  240. OperatedClientConnection conn = getWrappedConnection();
  241. assertValid(conn);
  242. return conn.getLocalPort();
  243. }
  244. // non-javadoc, see interface HttpInetConnection
  245. public InetAddress getRemoteAddress() {
  246. OperatedClientConnection conn = getWrappedConnection();
  247. assertValid(conn);
  248. return conn.getRemoteAddress();
  249. }
  250. // non-javadoc, see interface HttpInetConnection
  251. public int getRemotePort() {
  252. OperatedClientConnection conn = getWrappedConnection();
  253. assertValid(conn);
  254. return conn.getRemotePort();
  255. }
  256. // non-javadoc, see interface ManagedClientConnection
  257. public boolean isSecure() {
  258. OperatedClientConnection conn = getWrappedConnection();
  259. assertValid(conn);
  260. return conn.isSecure();
  261. }
  262. // non-javadoc, see interface ManagedClientConnection
  263. public SSLSession getSSLSession() {
  264. OperatedClientConnection conn = getWrappedConnection();
  265. assertValid(conn);
  266. if (!isOpen())
  267. return null;
  268. SSLSession result = null;
  269. Socket sock = conn.getSocket();
  270. if (sock instanceof SSLSocket) {
  271. result = ((SSLSocket)sock).getSession();
  272. }
  273. return result;
  274. }
  275. // non-javadoc, see interface ManagedClientConnection
  276. public void markReusable() {
  277. markedReusable = true;
  278. }
  279. // non-javadoc, see interface ManagedClientConnection
  280. public void unmarkReusable() {
  281. markedReusable = false;
  282. }
  283. // non-javadoc, see interface ManagedClientConnection
  284. public boolean isMarkedReusable() {
  285. return markedReusable;
  286. }
  287. public void setIdleDuration(long duration, TimeUnit unit) {
  288. if(duration > 0) {
  289. this.duration = unit.toMillis(duration);
  290. } else {
  291. this.duration = -1;
  292. }
  293. }
  294. // non-javadoc, see interface ConnectionReleaseTrigger
  295. public void releaseConnection() {
  296. if (connManager != null) {
  297. connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
  298. }
  299. }
  300. // non-javadoc, see interface ConnectionReleaseTrigger
  301. public void abortConnection() {
  302. if (aborted) {
  303. return;
  304. }
  305. aborted = true;
  306. unmarkReusable();
  307. try {
  308. shutdown();
  309. } catch (IOException ignore) {
  310. }
  311. // Usually #abortConnection() is expected to be called from
  312. // a helper thread in order to unblock the main execution thread
  313. // blocked in an I/O operation. It may be unsafe to call
  314. // #releaseConnection() from the helper thread, so we have to rely
  315. // on an IOException thrown by the closed socket on the main thread
  316. // to trigger the release of the connection back to the
  317. // connection manager.
  318. //
  319. // However, if this method is called from the main execution thread
  320. // it should be safe to release the connection immediately. Besides,
  321. // this also helps ensure the connection gets released back to the
  322. // manager if #abortConnection() is called from the main execution
  323. // thread while there is no blocking I/O operation.
  324. if (executionThread.equals(Thread.currentThread())) {
  325. releaseConnection();
  326. }
  327. }
  328. } // class AbstractClientConnAdapter