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.impl.conn;
28  
29  import java.io.IOException;
30  import java.lang.reflect.InvocationHandler;
31  import java.lang.reflect.InvocationTargetException;
32  import java.lang.reflect.Method;
33  import java.lang.reflect.Proxy;
34  
35  import org.apache.http.HttpClientConnection;
36  import org.apache.http.HttpConnection;
37  import org.apache.http.annotation.NotThreadSafe;
38  import org.apache.http.conn.ManagedHttpClientConnection;
39  import org.apache.http.protocol.HttpContext;
40  
41  /**
42   * @since 4.3
43   */
44  @NotThreadSafe
45  class CPoolProxy implements InvocationHandler {
46  
47      private static final Method CLOSE_METHOD;
48      private static final Method SHUTDOWN_METHOD;
49      private static final Method IS_OPEN_METHOD;
50      private static final Method IS_STALE_METHOD;
51  
52      static {
53          try {
54              CLOSE_METHOD = HttpConnection.class.getMethod("close");
55              SHUTDOWN_METHOD = HttpConnection.class.getMethod("shutdown");
56              IS_OPEN_METHOD = HttpConnection.class.getMethod("isOpen");
57              IS_STALE_METHOD = HttpConnection.class.getMethod("isStale");
58          } catch (final NoSuchMethodException ex) {
59              throw new Error(ex);
60          }
61      }
62  
63      private volatile CPoolEntry poolEntry;
64  
65      CPoolProxy(final CPoolEntry entry) {
66          super();
67          this.poolEntry = entry;
68      }
69  
70      CPoolEntry getPoolEntry() {
71          return this.poolEntry;
72      }
73  
74      CPoolEntry detach() {
75          final CPoolEntry local = this.poolEntry;
76          this.poolEntry = null;
77          return local;
78      }
79  
80      HttpClientConnection getConnection() {
81          final CPoolEntry local = this.poolEntry;
82          if (local == null) {
83              return null;
84          }
85          return local.getConnection();
86      }
87  
88      public void close() throws IOException {
89          final CPoolEntry local = this.poolEntry;
90          if (local != null) {
91              local.closeConnection();
92          }
93      }
94  
95      public void shutdown() throws IOException {
96          final CPoolEntry local = this.poolEntry;
97          if (local != null) {
98              local.shutdownConnection();
99          }
100     }
101 
102     public boolean isOpen() {
103         final CPoolEntry local = this.poolEntry;
104         if (local != null) {
105             return !local.isClosed();
106         } else {
107             return false;
108         }
109     }
110 
111     public boolean isStale() {
112         final HttpClientConnection conn = getConnection();
113         if (conn != null) {
114             return conn.isStale();
115         } else {
116             return true;
117         }
118     }
119 
120     public Object invoke(
121             final Object proxy, final Method method, final Object[] args) throws Throwable {
122         if (method.equals(CLOSE_METHOD)) {
123             close();
124             return null;
125         } else if (method.equals(SHUTDOWN_METHOD)) {
126             shutdown();
127             return null;
128         } else if (method.equals(IS_OPEN_METHOD)) {
129             return Boolean.valueOf(isOpen());
130         } else if (method.equals(IS_STALE_METHOD)) {
131             return Boolean.valueOf(isStale());
132         } else {
133             final HttpClientConnection conn = getConnection();
134             if (conn == null) {
135                 throw new ConnectionShutdownException();
136             }
137             try {
138                 return method.invoke(conn, args);
139             } catch (final InvocationTargetException ex) {
140                 final Throwable cause = ex.getCause();
141                 if (cause != null) {
142                     throw cause;
143                 } else {
144                     throw ex;
145                 }
146             }
147         }
148     }
149 
150     public static HttpClientConnection newProxy(
151             final CPoolEntry poolEntry) {
152         return (HttpClientConnection) Proxy.newProxyInstance(
153                 CPoolProxy.class.getClassLoader(),
154                 new Class<?>[] { ManagedHttpClientConnection.class, HttpContext.class },
155                 new CPoolProxy(poolEntry));
156     }
157 
158     private static CPoolProxy getHandler(
159             final HttpClientConnection proxy) {
160         final InvocationHandler handler = Proxy.getInvocationHandler(proxy);
161         if (!CPoolProxy.class.isInstance(handler)) {
162             throw new IllegalStateException("Unexpected proxy handler class: " + handler);
163         }
164         return CPoolProxy.class.cast(handler);
165     }
166 
167     public static CPoolEntry getPoolEntry(final HttpClientConnection proxy) {
168         final CPoolEntry entry = getHandler(proxy).getPoolEntry();
169         if (entry == null) {
170             throw new ConnectionShutdownException();
171         }
172         return entry;
173     }
174 
175     public static CPoolEntry detach(final HttpClientConnection proxy) {
176         return getHandler(proxy).detach();
177     }
178 
179 }