001/*
002 * ====================================================================
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *   http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied.  See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 * ====================================================================
020 *
021 * This software consists of voluntary contributions made by many
022 * individuals on behalf of the Apache Software Foundation.  For more
023 * information on the Apache Software Foundation, please see
024 * <http://www.apache.org/>.
025 *
026 */
027package org.apache.http.impl.conn;
028
029import java.io.IOException;
030import java.net.InetAddress;
031import java.net.Socket;
032
033import javax.net.ssl.SSLSession;
034
035import org.apache.http.HttpClientConnection;
036import org.apache.http.HttpConnectionMetrics;
037import org.apache.http.HttpEntityEnclosingRequest;
038import org.apache.http.HttpException;
039import org.apache.http.HttpRequest;
040import org.apache.http.HttpResponse;
041import org.apache.http.conn.ManagedHttpClientConnection;
042import org.apache.http.protocol.HttpContext;
043
044/**
045 * @since 4.3
046 */
047class CPoolProxy implements ManagedHttpClientConnection, HttpContext {
048
049    private volatile CPoolEntry poolEntry;
050
051    CPoolProxy(final CPoolEntry entry) {
052        super();
053        this.poolEntry = entry;
054    }
055
056    CPoolEntry getPoolEntry() {
057        return this.poolEntry;
058    }
059
060    CPoolEntry detach() {
061        final CPoolEntry local = this.poolEntry;
062        this.poolEntry = null;
063        return local;
064    }
065
066    ManagedHttpClientConnection getConnection() {
067        final CPoolEntry local = this.poolEntry;
068        if (local == null) {
069            return null;
070        }
071        return local.getConnection();
072    }
073
074    ManagedHttpClientConnection getValidConnection() {
075        final ManagedHttpClientConnection conn = getConnection();
076        if (conn == null) {
077            throw new ConnectionShutdownException();
078        }
079        return conn;
080    }
081
082    @Override
083    public void close() throws IOException {
084        final CPoolEntry local = this.poolEntry;
085        if (local != null) {
086            local.closeConnection();
087        }
088    }
089
090    @Override
091    public void shutdown() throws IOException {
092        final CPoolEntry local = this.poolEntry;
093        if (local != null) {
094            local.shutdownConnection();
095        }
096    }
097
098    @Override
099    public boolean isOpen() {
100        final CPoolEntry local = this.poolEntry;
101        if (local != null) {
102            return !local.isClosed();
103        } else {
104            return false;
105        }
106    }
107
108    @Override
109    public boolean isStale() {
110        final HttpClientConnection conn = getConnection();
111        if (conn != null) {
112            return conn.isStale();
113        } else {
114            return true;
115        }
116    }
117
118    @Override
119    public void setSocketTimeout(final int timeout) {
120        getValidConnection().setSocketTimeout(timeout);
121    }
122
123    @Override
124    public int getSocketTimeout() {
125        return getValidConnection().getSocketTimeout();
126    }
127
128    @Override
129    public String getId() {
130        return getValidConnection().getId();
131    }
132
133    @Override
134    public void bind(final Socket socket) throws IOException {
135        getValidConnection().bind(socket);
136    }
137
138    @Override
139    public Socket getSocket() {
140        return getValidConnection().getSocket();
141    }
142
143    @Override
144    public SSLSession getSSLSession() {
145        return getValidConnection().getSSLSession();
146    }
147
148    @Override
149    public boolean isResponseAvailable(final int timeout) throws IOException {
150        return getValidConnection().isResponseAvailable(timeout);
151    }
152
153    @Override
154    public void sendRequestHeader(final HttpRequest request) throws HttpException, IOException {
155        getValidConnection().sendRequestHeader(request);
156    }
157
158    @Override
159    public void sendRequestEntity(final HttpEntityEnclosingRequest request) throws HttpException, IOException {
160        getValidConnection().sendRequestEntity(request);
161    }
162
163    @Override
164    public HttpResponse receiveResponseHeader() throws HttpException, IOException {
165        return getValidConnection().receiveResponseHeader();
166    }
167
168    @Override
169    public void receiveResponseEntity(final HttpResponse response) throws HttpException, IOException {
170        getValidConnection().receiveResponseEntity(response);
171    }
172
173    @Override
174    public void flush() throws IOException {
175        getValidConnection().flush();
176    }
177
178    @Override
179    public HttpConnectionMetrics getMetrics() {
180        return getValidConnection().getMetrics();
181    }
182
183    @Override
184    public InetAddress getLocalAddress() {
185        return getValidConnection().getLocalAddress();
186    }
187
188    @Override
189    public int getLocalPort() {
190        return getValidConnection().getLocalPort();
191    }
192
193    @Override
194    public InetAddress getRemoteAddress() {
195        return getValidConnection().getRemoteAddress();
196    }
197
198    @Override
199    public int getRemotePort() {
200        return getValidConnection().getRemotePort();
201    }
202
203    @Override
204    public Object getAttribute(final String id) {
205        final ManagedHttpClientConnection conn = getValidConnection();
206        if (conn instanceof HttpContext) {
207            return ((HttpContext) conn).getAttribute(id);
208        } else {
209            return null;
210        }
211    }
212
213    @Override
214    public void setAttribute(final String id, final Object obj) {
215        final ManagedHttpClientConnection conn = getValidConnection();
216        if (conn instanceof HttpContext) {
217            ((HttpContext) conn).setAttribute(id, obj);
218        }
219    }
220
221    @Override
222    public Object removeAttribute(final String id) {
223        final ManagedHttpClientConnection conn = getValidConnection();
224        if (conn instanceof HttpContext) {
225            return ((HttpContext) conn).removeAttribute(id);
226        } else {
227            return null;
228        }
229    }
230
231    @Override
232    public String toString() {
233        final StringBuilder sb = new StringBuilder("CPoolProxy{");
234        final ManagedHttpClientConnection conn = getConnection();
235        if (conn != null) {
236            sb.append(conn);
237        } else {
238            sb.append("detached");
239        }
240        sb.append('}');
241        return sb.toString();
242    }
243
244    public static HttpClientConnection newProxy(final CPoolEntry poolEntry) {
245        return new CPoolProxy(poolEntry);
246    }
247
248    private static CPoolProxy getProxy(final HttpClientConnection conn) {
249        if (!CPoolProxy.class.isInstance(conn)) {
250            throw new IllegalStateException("Unexpected connection proxy class: " + conn.getClass());
251        }
252        return CPoolProxy.class.cast(conn);
253    }
254
255    public static CPoolEntry getPoolEntry(final HttpClientConnection proxy) {
256        final CPoolEntry entry = getProxy(proxy).getPoolEntry();
257        if (entry == null) {
258            throw new ConnectionShutdownException();
259        }
260        return entry;
261    }
262
263    public static CPoolEntry detach(final HttpClientConnection conn) {
264        return getProxy(conn).detach();
265    }
266
267}