| /* |
| * ==================================================================== |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| * |
| */ |
| package org.apache.http.impl.nio.conn; |
| |
| import java.io.IOException; |
| import java.net.InetAddress; |
| import java.util.concurrent.TimeUnit; |
| |
| import javax.net.ssl.SSLSession; |
| |
| import org.apache.http.HttpConnectionMetrics; |
| import org.apache.http.HttpException; |
| import org.apache.http.HttpHost; |
| import org.apache.http.HttpRequest; |
| import org.apache.http.HttpResponse; |
| import org.apache.http.client.protocol.ClientContext; |
| import org.apache.http.conn.routing.HttpRoute; |
| import org.apache.http.conn.routing.RouteTracker; |
| import org.apache.http.impl.conn.ConnectionShutdownException; |
| import org.apache.http.nio.conn.ClientAsyncConnection; |
| import org.apache.http.nio.conn.ClientAsyncConnectionFactory; |
| import org.apache.http.nio.conn.ClientAsyncConnectionManager; |
| import org.apache.http.nio.conn.ManagedClientAsyncConnection; |
| import org.apache.http.nio.conn.scheme.AsyncScheme; |
| import org.apache.http.nio.conn.scheme.AsyncSchemeRegistry; |
| import org.apache.http.nio.conn.scheme.LayeringStrategy; |
| import org.apache.http.nio.reactor.IOEventDispatch; |
| import org.apache.http.nio.reactor.IOSession; |
| import org.apache.http.nio.reactor.ssl.SSLIOSession; |
| import org.apache.http.params.HttpParams; |
| import org.apache.http.protocol.HttpContext; |
| |
| @Deprecated |
| class ManagedClientAsyncConnectionImpl implements ManagedClientAsyncConnection { |
| |
| private final ClientAsyncConnectionManager manager; |
| private final ClientAsyncConnectionFactory connFactory; |
| private volatile HttpPoolEntry poolEntry; |
| private volatile boolean reusable; |
| private volatile long duration; |
| |
| ManagedClientAsyncConnectionImpl( |
| final ClientAsyncConnectionManager manager, |
| final ClientAsyncConnectionFactory connFactory, |
| final HttpPoolEntry poolEntry) { |
| super(); |
| this.manager = manager; |
| this.connFactory = connFactory; |
| this.poolEntry = poolEntry; |
| this.reusable = true; |
| this.duration = Long.MAX_VALUE; |
| } |
| |
| HttpPoolEntry getPoolEntry() { |
| return this.poolEntry; |
| } |
| |
| HttpPoolEntry detach() { |
| final HttpPoolEntry local = this.poolEntry; |
| this.poolEntry = null; |
| return local; |
| } |
| |
| public ClientAsyncConnectionManager getManager() { |
| return this.manager; |
| } |
| |
| private ClientAsyncConnection getConnection() { |
| final HttpPoolEntry local = this.poolEntry; |
| if (local == null) { |
| return null; |
| } |
| final IOSession session = local.getConnection(); |
| return (ClientAsyncConnection) session.getAttribute(IOEventDispatch.CONNECTION_KEY); |
| } |
| |
| private ClientAsyncConnection ensureConnection() { |
| final HttpPoolEntry local = this.poolEntry; |
| if (local == null) { |
| throw new ConnectionShutdownException(); |
| } |
| final IOSession session = local.getConnection(); |
| return (ClientAsyncConnection) session.getAttribute(IOEventDispatch.CONNECTION_KEY); |
| } |
| |
| private HttpPoolEntry ensurePoolEntry() { |
| final HttpPoolEntry local = this.poolEntry; |
| if (local == null) { |
| throw new ConnectionShutdownException(); |
| } |
| return local; |
| } |
| |
| @Override |
| public void close() throws IOException { |
| final ClientAsyncConnection conn = getConnection(); |
| if (conn != null) { |
| conn.close(); |
| } |
| } |
| |
| @Override |
| public void shutdown() throws IOException { |
| final ClientAsyncConnection conn = getConnection(); |
| if (conn != null) { |
| conn.shutdown(); |
| } |
| } |
| |
| @Override |
| public boolean isOpen() { |
| final ClientAsyncConnection conn = getConnection(); |
| if (conn != null) { |
| return conn.isOpen(); |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public boolean isStale() { |
| return isOpen(); |
| } |
| |
| @Override |
| public void setSocketTimeout(final int timeout) { |
| final ClientAsyncConnection conn = ensureConnection(); |
| conn.setSocketTimeout(timeout); |
| } |
| |
| @Override |
| public int getSocketTimeout() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| return conn.getSocketTimeout(); |
| } |
| |
| @Override |
| public HttpConnectionMetrics getMetrics() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| return conn.getMetrics(); |
| } |
| |
| @Override |
| public InetAddress getLocalAddress() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| return conn.getLocalAddress(); |
| } |
| |
| @Override |
| public int getLocalPort() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| return conn.getLocalPort(); |
| } |
| |
| @Override |
| public InetAddress getRemoteAddress() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| return conn.getRemoteAddress(); |
| } |
| |
| @Override |
| public int getRemotePort() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| return conn.getRemotePort(); |
| } |
| |
| @Override |
| public int getStatus() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| return conn.getStatus(); |
| } |
| |
| @Override |
| public HttpRequest getHttpRequest() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| return conn.getHttpRequest(); |
| } |
| |
| @Override |
| public HttpResponse getHttpResponse() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| return conn.getHttpResponse(); |
| } |
| |
| @Override |
| public HttpContext getContext() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| return conn.getContext(); |
| } |
| |
| @Override |
| public void requestInput() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| conn.requestInput(); |
| } |
| |
| @Override |
| public void suspendInput() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| conn.suspendInput(); |
| } |
| |
| @Override |
| public void requestOutput() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| conn.requestOutput(); |
| } |
| |
| @Override |
| public void suspendOutput() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| conn.suspendOutput(); |
| } |
| |
| @Override |
| public void submitRequest(final HttpRequest request) throws IOException, HttpException { |
| final ClientAsyncConnection conn = ensureConnection(); |
| conn.submitRequest(request); |
| } |
| |
| @Override |
| public boolean isRequestSubmitted() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| return conn.isRequestSubmitted(); |
| } |
| |
| @Override |
| public void resetOutput() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| conn.resetOutput(); |
| } |
| |
| @Override |
| public void resetInput() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| conn.resetInput(); |
| } |
| |
| @Override |
| public boolean isSecure() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| return conn.getIOSession() instanceof SSLIOSession; |
| } |
| |
| @Override |
| public HttpRoute getRoute() { |
| final HttpPoolEntry entry = ensurePoolEntry(); |
| return entry.getEffectiveRoute(); |
| } |
| |
| @Override |
| public SSLSession getSSLSession() { |
| final ClientAsyncConnection conn = ensureConnection(); |
| final IOSession iosession = conn.getIOSession(); |
| if (iosession instanceof SSLIOSession) { |
| return ((SSLIOSession) iosession).getSSLSession(); |
| } else { |
| return null; |
| } |
| } |
| |
| @Override |
| public Object getState() { |
| final HttpPoolEntry entry = ensurePoolEntry(); |
| return entry.getState(); |
| } |
| |
| @Override |
| public void setState(final Object state) { |
| final HttpPoolEntry entry = ensurePoolEntry(); |
| entry.setState(state); |
| } |
| |
| @Override |
| public void markReusable() { |
| this.reusable = true; |
| } |
| |
| @Override |
| public void unmarkReusable() { |
| this.reusable = false; |
| } |
| |
| @Override |
| public boolean isMarkedReusable() { |
| return this.reusable; |
| } |
| |
| @Override |
| public void setIdleDuration(final long duration, final TimeUnit unit) { |
| if(duration > 0) { |
| this.duration = unit.toMillis(duration); |
| } else { |
| this.duration = -1; |
| } |
| } |
| |
| private AsyncSchemeRegistry getSchemeRegistry(final HttpContext context) { |
| AsyncSchemeRegistry reg = (AsyncSchemeRegistry) context.getAttribute( |
| ClientContext.SCHEME_REGISTRY); |
| if (reg == null) { |
| reg = this.manager.getSchemeRegistry(); |
| } |
| return reg; |
| } |
| |
| @Override |
| public synchronized void open( |
| final HttpRoute route, |
| final HttpContext context, |
| final HttpParams params) throws IOException { |
| final HttpPoolEntry entry = ensurePoolEntry(); |
| final RouteTracker tracker = entry.getTracker(); |
| if (tracker.isConnected()) { |
| throw new IllegalStateException("Connection already open"); |
| } |
| |
| final HttpHost target = route.getTargetHost(); |
| final HttpHost proxy = route.getProxyHost(); |
| IOSession iosession = entry.getConnection(); |
| |
| if (proxy == null) { |
| final AsyncScheme scheme = getSchemeRegistry(context).getScheme(target); |
| final LayeringStrategy layeringStrategy = scheme.getLayeringStrategy(); |
| if (layeringStrategy != null) { |
| iosession = layeringStrategy.layer(iosession); |
| } |
| } |
| |
| final ClientAsyncConnection conn = this.connFactory.create( |
| "http-outgoing-" + entry.getId(), |
| iosession, |
| params); |
| iosession.setAttribute(IOEventDispatch.CONNECTION_KEY, conn); |
| |
| if (proxy == null) { |
| tracker.connectTarget(conn.getIOSession() instanceof SSLIOSession); |
| } else { |
| tracker.connectProxy(proxy, false); |
| } |
| } |
| |
| @Override |
| public synchronized void tunnelProxy( |
| final HttpHost next, final HttpParams params) throws IOException { |
| final HttpPoolEntry entry = ensurePoolEntry(); |
| final RouteTracker tracker = entry.getTracker(); |
| if (!tracker.isConnected()) { |
| throw new IllegalStateException("Connection not open"); |
| } |
| tracker.tunnelProxy(next, false); |
| } |
| |
| @Override |
| public synchronized void tunnelTarget( |
| final HttpParams params) throws IOException { |
| final HttpPoolEntry entry = ensurePoolEntry(); |
| final RouteTracker tracker = entry.getTracker(); |
| if (!tracker.isConnected()) { |
| throw new IllegalStateException("Connection not open"); |
| } |
| if (tracker.isTunnelled()) { |
| throw new IllegalStateException("Connection is already tunnelled"); |
| } |
| tracker.tunnelTarget(false); |
| } |
| |
| @Override |
| public synchronized void layerProtocol( |
| final HttpContext context, final HttpParams params) throws IOException { |
| final HttpPoolEntry entry = ensurePoolEntry(); |
| final RouteTracker tracker = entry.getTracker(); |
| if (!tracker.isConnected()) { |
| throw new IllegalStateException("Connection not open"); |
| } |
| if (!tracker.isTunnelled()) { |
| throw new IllegalStateException("Protocol layering without a tunnel not supported"); |
| } |
| if (tracker.isLayered()) { |
| throw new IllegalStateException("Multiple protocol layering not supported"); |
| } |
| final HttpHost target = tracker.getTargetHost(); |
| final AsyncScheme scheme = getSchemeRegistry(context).getScheme(target); |
| final LayeringStrategy layeringStrategy = scheme.getLayeringStrategy(); |
| if (layeringStrategy == null) { |
| throw new IllegalStateException(scheme.getName() + |
| " scheme does not provider support for protocol layering"); |
| } |
| final IOSession iosession = entry.getConnection(); |
| final ClientAsyncConnection conn = (ClientAsyncConnection) iosession.getAttribute( |
| IOEventDispatch.CONNECTION_KEY); |
| conn.upgrade((SSLIOSession) layeringStrategy.layer(iosession)); |
| tracker.layerProtocol(layeringStrategy.isSecure()); |
| } |
| |
| @Override |
| public synchronized void releaseConnection() { |
| if (this.poolEntry == null) { |
| return; |
| } |
| this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS); |
| this.poolEntry = null; |
| } |
| |
| @Override |
| public synchronized void abortConnection() { |
| if (this.poolEntry == null) { |
| return; |
| } |
| this.reusable = false; |
| final IOSession iosession = this.poolEntry.getConnection(); |
| final ClientAsyncConnection conn = (ClientAsyncConnection) iosession.getAttribute( |
| IOEventDispatch.CONNECTION_KEY); |
| try { |
| conn.shutdown(); |
| } catch (final IOException ignore) { |
| } |
| this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS); |
| this.poolEntry = null; |
| } |
| |
| @Override |
| public synchronized String toString() { |
| if (this.poolEntry != null) { |
| return this.poolEntry.toString(); |
| } else { |
| return "released"; |
| } |
| } |
| |
| } |