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.net.InetAddress;
31 import java.net.Socket;
32
33 import javax.net.ssl.SSLSession;
34
35 import org.apache.http.HttpClientConnection;
36 import org.apache.http.HttpConnectionMetrics;
37 import org.apache.http.HttpEntityEnclosingRequest;
38 import org.apache.http.HttpException;
39 import org.apache.http.HttpRequest;
40 import org.apache.http.HttpResponse;
41 import org.apache.http.conn.ManagedHttpClientConnection;
42 import org.apache.http.protocol.HttpContext;
43
44 /**
45  * @since 4.3
46  */

47 class CPoolProxy implements ManagedHttpClientConnection, HttpContext {
48
49     private volatile CPoolEntry poolEntry;
50
51     CPoolProxy(final CPoolEntry entry) {
52         super();
53         this.poolEntry = entry;
54     }
55
56     CPoolEntry getPoolEntry() {
57         return this.poolEntry;
58     }
59
60     CPoolEntry detach() {
61         final CPoolEntry local = this.poolEntry;
62         this.poolEntry = null;
63         return local;
64     }
65
66     ManagedHttpClientConnection getConnection() {
67         final CPoolEntry local = this.poolEntry;
68         if (local == null) {
69             return null;
70         }
71         return local.getConnection();
72     }
73
74     ManagedHttpClientConnection getValidConnection() {
75         final ManagedHttpClientConnection conn = getConnection();
76         if (conn == null) {
77             throw new ConnectionShutdownException();
78         }
79         return conn;
80     }
81
82     @Override
83     public void close() throws IOException {
84         final CPoolEntry local = this.poolEntry;
85         if (local != null) {
86             local.closeConnection();
87         }
88     }
89
90     @Override
91     public void shutdown() throws IOException {
92         final CPoolEntry local = this.poolEntry;
93         if (local != null) {
94             local.shutdownConnection();
95         }
96     }
97
98     @Override
99     public boolean isOpen() {
100         final CPoolEntry local = this.poolEntry;
101         return local != null ? !local.isClosed() : false;
102     }
103
104     @Override
105     public boolean isStale() {
106         final HttpClientConnection conn = getConnection();
107         return conn != null ? conn.isStale() : true;
108     }
109
110     @Override
111     public void setSocketTimeout(final int timeout) {
112         getValidConnection().setSocketTimeout(timeout);
113     }
114
115     @Override
116     public int getSocketTimeout() {
117         return getValidConnection().getSocketTimeout();
118     }
119
120     @Override
121     public String getId() {
122         return getValidConnection().getId();
123     }
124
125     @Override
126     public void bind(final Socket socket) throws IOException {
127         getValidConnection().bind(socket);
128     }
129
130     @Override
131     public Socket getSocket() {
132         return getValidConnection().getSocket();
133     }
134
135     @Override
136     public SSLSession getSSLSession() {
137         return getValidConnection().getSSLSession();
138     }
139
140     @Override
141     public boolean isResponseAvailable(final int timeout) throws IOException {
142         return getValidConnection().isResponseAvailable(timeout);
143     }
144
145     @Override
146     public void sendRequestHeader(final HttpRequest request) throws HttpException, IOException {
147         getValidConnection().sendRequestHeader(request);
148     }
149
150     @Override
151     public void sendRequestEntity(final HttpEntityEnclosingRequest request) throws HttpException, IOException {
152         getValidConnection().sendRequestEntity(request);
153     }
154
155     @Override
156     public HttpResponse receiveResponseHeader() throws HttpException, IOException {
157         return getValidConnection().receiveResponseHeader();
158     }
159
160     @Override
161     public void receiveResponseEntity(final HttpResponse response) throws HttpException, IOException {
162         getValidConnection().receiveResponseEntity(response);
163     }
164
165     @Override
166     public void flush() throws IOException {
167         getValidConnection().flush();
168     }
169
170     @Override
171     public HttpConnectionMetrics getMetrics() {
172         return getValidConnection().getMetrics();
173     }
174
175     @Override
176     public InetAddress getLocalAddress() {
177         return getValidConnection().getLocalAddress();
178     }
179
180     @Override
181     public int getLocalPort() {
182         return getValidConnection().getLocalPort();
183     }
184
185     @Override
186     public InetAddress getRemoteAddress() {
187         return getValidConnection().getRemoteAddress();
188     }
189
190     @Override
191     public int getRemotePort() {
192         return getValidConnection().getRemotePort();
193     }
194
195     @Override
196     public Object getAttribute(final String id) {
197         final ManagedHttpClientConnection conn = getValidConnection();
198         return conn instanceof HttpContext ? ((HttpContext) conn).getAttribute(id) : null;
199     }
200
201     @Override
202     public void setAttribute(final String id, final Object obj) {
203         final ManagedHttpClientConnection conn = getValidConnection();
204         if (conn instanceof HttpContext) {
205             ((HttpContext) conn).setAttribute(id, obj);
206         }
207     }
208
209     @Override
210     public Object removeAttribute(final String id) {
211         final ManagedHttpClientConnection conn = getValidConnection();
212         return conn instanceof HttpContext ? ((HttpContext) conn).removeAttribute(id) : null;
213     }
214
215     @Override
216     public String toString() {
217         final StringBuilder sb = new StringBuilder("CPoolProxy{");
218         final ManagedHttpClientConnection conn = getConnection();
219         if (conn != null) {
220             sb.append(conn);
221         } else {
222             sb.append("detached");
223         }
224         sb.append('}');
225         return sb.toString();
226     }
227
228     public static HttpClientConnection newProxy(final CPoolEntry poolEntry) {
229         return new CPoolProxy(poolEntry);
230     }
231
232     private static CPoolProxy getProxy(final HttpClientConnection conn) {
233         if (!CPoolProxy.class.isInstance(conn)) {
234             throw new IllegalStateException("Unexpected connection proxy class: " + conn.getClass());
235         }
236         return CPoolProxy.class.cast(conn);
237     }
238
239     public static CPoolEntry getPoolEntry(final HttpClientConnection proxy) {
240         final CPoolEntry entry = getProxy(proxy).getPoolEntry();
241         if (entry == null) {
242             throw new ConnectionShutdownException();
243         }
244         return entry;
245     }
246
247     public static CPoolEntry detach(final HttpClientConnection conn) {
248         return getProxy(conn).detach();
249     }
250
251 }
252