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.nio.conn;
28  
29  import java.io.IOException;
30  import java.net.InetAddress;
31  import java.util.concurrent.TimeUnit;
32  
33  import javax.net.ssl.SSLSession;
34  
35  import org.apache.http.HttpConnectionMetrics;
36  import org.apache.http.HttpException;
37  import org.apache.http.HttpHost;
38  import org.apache.http.HttpRequest;
39  import org.apache.http.HttpResponse;
40  import org.apache.http.client.protocol.ClientContext;
41  import org.apache.http.conn.routing.HttpRoute;
42  import org.apache.http.conn.routing.RouteTracker;
43  import org.apache.http.impl.conn.ConnectionShutdownException;
44  import org.apache.http.nio.conn.ClientAsyncConnection;
45  import org.apache.http.nio.conn.ClientAsyncConnectionFactory;
46  import org.apache.http.nio.conn.ClientAsyncConnectionManager;
47  import org.apache.http.nio.conn.ManagedClientAsyncConnection;
48  import org.apache.http.nio.conn.scheme.AsyncScheme;
49  import org.apache.http.nio.conn.scheme.AsyncSchemeRegistry;
50  import org.apache.http.nio.conn.scheme.LayeringStrategy;
51  import org.apache.http.nio.reactor.IOEventDispatch;
52  import org.apache.http.nio.reactor.IOSession;
53  import org.apache.http.nio.reactor.ssl.SSLIOSession;
54  import org.apache.http.params.HttpParams;
55  import org.apache.http.protocol.HttpContext;
56  
57  @Deprecated
58  class ManagedClientAsyncConnectionImpl implements ManagedClientAsyncConnection {
59  
60      private final ClientAsyncConnectionManager manager;
61      private final ClientAsyncConnectionFactory connFactory;
62      private volatile HttpPoolEntry poolEntry;
63      private volatile boolean reusable;
64      private volatile long duration;
65  
66      ManagedClientAsyncConnectionImpl(
67              final ClientAsyncConnectionManager manager,
68              final ClientAsyncConnectionFactory connFactory,
69              final HttpPoolEntry poolEntry) {
70          super();
71          this.manager = manager;
72          this.connFactory = connFactory;
73          this.poolEntry = poolEntry;
74          this.reusable = true;
75          this.duration = Long.MAX_VALUE;
76      }
77  
78      HttpPoolEntry getPoolEntry() {
79          return this.poolEntry;
80      }
81  
82      HttpPoolEntry detach() {
83          final HttpPoolEntry local = this.poolEntry;
84          this.poolEntry = null;
85          return local;
86      }
87  
88      public ClientAsyncConnectionManager getManager() {
89          return this.manager;
90      }
91  
92      private ClientAsyncConnection getConnection() {
93          final HttpPoolEntry local = this.poolEntry;
94          if (local == null) {
95              return null;
96          }
97          final IOSession session = local.getConnection();
98          return (ClientAsyncConnection) session.getAttribute(IOEventDispatch.CONNECTION_KEY);
99      }
100 
101     private ClientAsyncConnection ensureConnection() {
102         final HttpPoolEntry local = this.poolEntry;
103         if (local == null) {
104             throw new ConnectionShutdownException();
105         }
106         final IOSession session = local.getConnection();
107         return (ClientAsyncConnection) session.getAttribute(IOEventDispatch.CONNECTION_KEY);
108     }
109 
110     private HttpPoolEntry ensurePoolEntry() {
111         final HttpPoolEntry local = this.poolEntry;
112         if (local == null) {
113             throw new ConnectionShutdownException();
114         }
115         return local;
116     }
117 
118     @Override
119     public void close() throws IOException {
120         final ClientAsyncConnection conn = getConnection();
121         if (conn != null) {
122             conn.close();
123         }
124     }
125 
126     @Override
127     public void shutdown() throws IOException {
128         final ClientAsyncConnection conn = getConnection();
129         if (conn != null) {
130             conn.shutdown();
131         }
132     }
133 
134     @Override
135     public boolean isOpen() {
136         final ClientAsyncConnection conn = getConnection();
137         if (conn != null) {
138             return conn.isOpen();
139         } else {
140             return false;
141         }
142     }
143 
144     @Override
145     public boolean isStale() {
146         return isOpen();
147     }
148 
149     @Override
150     public void setSocketTimeout(final int timeout) {
151         final ClientAsyncConnection conn = ensureConnection();
152         conn.setSocketTimeout(timeout);
153     }
154 
155     @Override
156     public int getSocketTimeout() {
157         final ClientAsyncConnection conn = ensureConnection();
158         return conn.getSocketTimeout();
159     }
160 
161     @Override
162     public HttpConnectionMetrics getMetrics() {
163         final ClientAsyncConnection conn = ensureConnection();
164         return conn.getMetrics();
165     }
166 
167     @Override
168     public InetAddress getLocalAddress() {
169         final ClientAsyncConnection conn = ensureConnection();
170         return conn.getLocalAddress();
171     }
172 
173     @Override
174     public int getLocalPort() {
175         final ClientAsyncConnection conn = ensureConnection();
176         return conn.getLocalPort();
177     }
178 
179     @Override
180     public InetAddress getRemoteAddress() {
181         final ClientAsyncConnection conn = ensureConnection();
182         return conn.getRemoteAddress();
183     }
184 
185     @Override
186     public int getRemotePort() {
187         final ClientAsyncConnection conn = ensureConnection();
188         return conn.getRemotePort();
189     }
190 
191     @Override
192     public int getStatus() {
193         final ClientAsyncConnection conn = ensureConnection();
194         return conn.getStatus();
195     }
196 
197     @Override
198     public HttpRequest getHttpRequest() {
199         final ClientAsyncConnection conn = ensureConnection();
200         return conn.getHttpRequest();
201     }
202 
203     @Override
204     public HttpResponse getHttpResponse() {
205         final ClientAsyncConnection conn = ensureConnection();
206         return conn.getHttpResponse();
207     }
208 
209     @Override
210     public HttpContext getContext() {
211         final ClientAsyncConnection conn = ensureConnection();
212         return conn.getContext();
213     }
214 
215     @Override
216     public void requestInput() {
217         final ClientAsyncConnection conn = ensureConnection();
218         conn.requestInput();
219     }
220 
221     @Override
222     public void suspendInput() {
223         final ClientAsyncConnection conn = ensureConnection();
224         conn.suspendInput();
225     }
226 
227     @Override
228     public void requestOutput() {
229         final ClientAsyncConnection conn = ensureConnection();
230         conn.requestOutput();
231     }
232 
233     @Override
234     public void suspendOutput() {
235         final ClientAsyncConnection conn = ensureConnection();
236         conn.suspendOutput();
237     }
238 
239     @Override
240     public void submitRequest(final HttpRequest request) throws IOException, HttpException {
241         final ClientAsyncConnection conn = ensureConnection();
242         conn.submitRequest(request);
243     }
244 
245     @Override
246     public boolean isRequestSubmitted() {
247         final ClientAsyncConnection conn = ensureConnection();
248         return conn.isRequestSubmitted();
249     }
250 
251     @Override
252     public void resetOutput() {
253         final ClientAsyncConnection conn = ensureConnection();
254         conn.resetOutput();
255     }
256 
257     @Override
258     public void resetInput() {
259         final ClientAsyncConnection conn = ensureConnection();
260         conn.resetInput();
261     }
262 
263     @Override
264     public boolean isSecure() {
265         final ClientAsyncConnection conn = ensureConnection();
266         return conn.getIOSession() instanceof SSLIOSession;
267     }
268 
269     @Override
270     public HttpRoute getRoute() {
271         final HttpPoolEntry entry = ensurePoolEntry();
272         return entry.getEffectiveRoute();
273     }
274 
275     @Override
276     public SSLSession getSSLSession() {
277         final ClientAsyncConnection conn = ensureConnection();
278         final IOSession iosession = conn.getIOSession();
279         if (iosession instanceof SSLIOSession) {
280             return ((SSLIOSession) iosession).getSSLSession();
281         } else {
282             return null;
283         }
284     }
285 
286     @Override
287     public Object getState() {
288         final HttpPoolEntry entry = ensurePoolEntry();
289         return entry.getState();
290     }
291 
292     @Override
293     public void setState(final Object state) {
294         final HttpPoolEntry entry = ensurePoolEntry();
295         entry.setState(state);
296     }
297 
298     @Override
299     public void markReusable() {
300         this.reusable = true;
301     }
302 
303     @Override
304     public void unmarkReusable() {
305         this.reusable = false;
306     }
307 
308     @Override
309     public boolean isMarkedReusable() {
310         return this.reusable;
311     }
312 
313     @Override
314     public void setIdleDuration(final long duration, final TimeUnit unit) {
315         if(duration > 0) {
316             this.duration = unit.toMillis(duration);
317         } else {
318             this.duration = -1;
319         }
320     }
321 
322     private AsyncSchemeRegistry getSchemeRegistry(final HttpContext context) {
323         AsyncSchemeRegistry reg = (AsyncSchemeRegistry) context.getAttribute(
324                 ClientContext.SCHEME_REGISTRY);
325         if (reg == null) {
326             reg = this.manager.getSchemeRegistry();
327         }
328         return reg;
329     }
330 
331     @Override
332     public synchronized void open(
333             final HttpRoute route,
334             final HttpContext context,
335             final HttpParams params) throws IOException {
336         final HttpPoolEntry entry = ensurePoolEntry();
337         final RouteTracker tracker = entry.getTracker();
338         if (tracker.isConnected()) {
339             throw new IllegalStateException("Connection already open");
340         }
341 
342         final HttpHost target = route.getTargetHost();
343         final HttpHost proxy = route.getProxyHost();
344         IOSession iosession = entry.getConnection();
345 
346         if (proxy == null) {
347             final AsyncScheme scheme = getSchemeRegistry(context).getScheme(target);
348             final LayeringStrategy layeringStrategy = scheme.getLayeringStrategy();
349             if (layeringStrategy != null) {
350                 iosession = layeringStrategy.layer(iosession);
351             }
352         }
353 
354         final ClientAsyncConnection conn = this.connFactory.create(
355                 "http-outgoing-" + entry.getId(),
356                 iosession,
357                 params);
358         iosession.setAttribute(IOEventDispatch.CONNECTION_KEY, conn);
359 
360         if (proxy == null) {
361             tracker.connectTarget(conn.getIOSession() instanceof SSLIOSession);
362         } else {
363             tracker.connectProxy(proxy, false);
364         }
365     }
366 
367     @Override
368     public synchronized void tunnelProxy(
369             final HttpHost next, final HttpParams params) throws IOException {
370         final HttpPoolEntry entry = ensurePoolEntry();
371         final RouteTracker tracker = entry.getTracker();
372         if (!tracker.isConnected()) {
373             throw new IllegalStateException("Connection not open");
374         }
375         tracker.tunnelProxy(next, false);
376     }
377 
378     @Override
379     public synchronized void tunnelTarget(
380             final HttpParams params) throws IOException {
381         final HttpPoolEntry entry = ensurePoolEntry();
382         final RouteTracker tracker = entry.getTracker();
383         if (!tracker.isConnected()) {
384             throw new IllegalStateException("Connection not open");
385         }
386         if (tracker.isTunnelled()) {
387             throw new IllegalStateException("Connection is already tunnelled");
388         }
389         tracker.tunnelTarget(false);
390     }
391 
392     @Override
393     public synchronized void layerProtocol(
394             final HttpContext context, final HttpParams params) throws IOException {
395         final HttpPoolEntry entry = ensurePoolEntry();
396         final RouteTracker tracker = entry.getTracker();
397         if (!tracker.isConnected()) {
398             throw new IllegalStateException("Connection not open");
399         }
400         if (!tracker.isTunnelled()) {
401             throw new IllegalStateException("Protocol layering without a tunnel not supported");
402         }
403         if (tracker.isLayered()) {
404             throw new IllegalStateException("Multiple protocol layering not supported");
405         }
406         final HttpHost target = tracker.getTargetHost();
407         final AsyncScheme scheme = getSchemeRegistry(context).getScheme(target);
408         final LayeringStrategy layeringStrategy = scheme.getLayeringStrategy();
409         if (layeringStrategy == null) {
410             throw new IllegalStateException(scheme.getName() +
411                     " scheme does not provider support for protocol layering");
412         }
413         final IOSession iosession = entry.getConnection();
414         final ClientAsyncConnection conn = (ClientAsyncConnection) iosession.getAttribute(
415                 IOEventDispatch.CONNECTION_KEY);
416         conn.upgrade((SSLIOSession) layeringStrategy.layer(iosession));
417         tracker.layerProtocol(layeringStrategy.isSecure());
418     }
419 
420     @Override
421     public synchronized void releaseConnection() {
422         if (this.poolEntry == null) {
423             return;
424         }
425         this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS);
426         this.poolEntry = null;
427     }
428 
429     @Override
430     public synchronized void abortConnection() {
431         if (this.poolEntry == null) {
432             return;
433         }
434         this.reusable = false;
435         final IOSession iosession = this.poolEntry.getConnection();
436         final ClientAsyncConnection conn = (ClientAsyncConnection) iosession.getAttribute(
437                 IOEventDispatch.CONNECTION_KEY);
438         try {
439             conn.shutdown();
440         } catch (final IOException ignore) {
441         }
442         this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS);
443         this.poolEntry = null;
444     }
445 
446     @Override
447     public synchronized String toString() {
448         if (this.poolEntry != null) {
449             return this.poolEntry.toString();
450         } else {
451             return "released";
452         }
453     }
454 
455 }