1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
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 }