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         return conn != null ? conn.isOpen() : false;
138     }
139 
140     @Override
141     public boolean isStale() {
142         return isOpen();
143     }
144 
145     @Override
146     public void setSocketTimeout(final int timeout) {
147         final ClientAsyncConnection conn = ensureConnection();
148         conn.setSocketTimeout(timeout);
149     }
150 
151     @Override
152     public int getSocketTimeout() {
153         final ClientAsyncConnection conn = ensureConnection();
154         return conn.getSocketTimeout();
155     }
156 
157     @Override
158     public HttpConnectionMetrics getMetrics() {
159         final ClientAsyncConnection conn = ensureConnection();
160         return conn.getMetrics();
161     }
162 
163     @Override
164     public InetAddress getLocalAddress() {
165         final ClientAsyncConnection conn = ensureConnection();
166         return conn.getLocalAddress();
167     }
168 
169     @Override
170     public int getLocalPort() {
171         final ClientAsyncConnection conn = ensureConnection();
172         return conn.getLocalPort();
173     }
174 
175     @Override
176     public InetAddress getRemoteAddress() {
177         final ClientAsyncConnection conn = ensureConnection();
178         return conn.getRemoteAddress();
179     }
180 
181     @Override
182     public int getRemotePort() {
183         final ClientAsyncConnection conn = ensureConnection();
184         return conn.getRemotePort();
185     }
186 
187     @Override
188     public int getStatus() {
189         final ClientAsyncConnection conn = ensureConnection();
190         return conn.getStatus();
191     }
192 
193     @Override
194     public HttpRequest getHttpRequest() {
195         final ClientAsyncConnection conn = ensureConnection();
196         return conn.getHttpRequest();
197     }
198 
199     @Override
200     public HttpResponse getHttpResponse() {
201         final ClientAsyncConnection conn = ensureConnection();
202         return conn.getHttpResponse();
203     }
204 
205     @Override
206     public HttpContext getContext() {
207         final ClientAsyncConnection conn = ensureConnection();
208         return conn.getContext();
209     }
210 
211     @Override
212     public void requestInput() {
213         final ClientAsyncConnection conn = ensureConnection();
214         conn.requestInput();
215     }
216 
217     @Override
218     public void suspendInput() {
219         final ClientAsyncConnection conn = ensureConnection();
220         conn.suspendInput();
221     }
222 
223     @Override
224     public void requestOutput() {
225         final ClientAsyncConnection conn = ensureConnection();
226         conn.requestOutput();
227     }
228 
229     @Override
230     public void suspendOutput() {
231         final ClientAsyncConnection conn = ensureConnection();
232         conn.suspendOutput();
233     }
234 
235     @Override
236     public void submitRequest(final HttpRequest request) throws IOException, HttpException {
237         final ClientAsyncConnection conn = ensureConnection();
238         conn.submitRequest(request);
239     }
240 
241     @Override
242     public boolean isRequestSubmitted() {
243         final ClientAsyncConnection conn = ensureConnection();
244         return conn.isRequestSubmitted();
245     }
246 
247     @Override
248     public void resetOutput() {
249         final ClientAsyncConnection conn = ensureConnection();
250         conn.resetOutput();
251     }
252 
253     @Override
254     public void resetInput() {
255         final ClientAsyncConnection conn = ensureConnection();
256         conn.resetInput();
257     }
258 
259     @Override
260     public boolean isSecure() {
261         final ClientAsyncConnection conn = ensureConnection();
262         return conn.getIOSession() instanceof SSLIOSession;
263     }
264 
265     @Override
266     public HttpRoute getRoute() {
267         final HttpPoolEntry entry = ensurePoolEntry();
268         return entry.getEffectiveRoute();
269     }
270 
271     @Override
272     public SSLSession getSSLSession() {
273         final ClientAsyncConnection conn = ensureConnection();
274         final IOSession ioSession = conn.getIOSession();
275         return ioSession instanceof SSLIOSession
276                         ? ((SSLIOSession) ioSession).getSSLSession()
277                         : null;
278     }
279 
280     @Override
281     public Object getState() {
282         final HttpPoolEntry entry = ensurePoolEntry();
283         return entry.getState();
284     }
285 
286     @Override
287     public void setState(final Object state) {
288         final HttpPoolEntry entry = ensurePoolEntry();
289         entry.setState(state);
290     }
291 
292     @Override
293     public void markReusable() {
294         this.reusable = true;
295     }
296 
297     @Override
298     public void unmarkReusable() {
299         this.reusable = false;
300     }
301 
302     @Override
303     public boolean isMarkedReusable() {
304         return this.reusable;
305     }
306 
307     @Override
308     public void setIdleDuration(final long duration, final TimeUnit unit) {
309         if(duration > 0) {
310             this.duration = unit.toMillis(duration);
311         } else {
312             this.duration = -1;
313         }
314     }
315 
316     private AsyncSchemeRegistry getSchemeRegistry(final HttpContext context) {
317         AsyncSchemeRegistry./../../org/apache/http/nio/conn/scheme/AsyncSchemeRegistry.html#AsyncSchemeRegistry">AsyncSchemeRegistry reg = (AsyncSchemeRegistry) context.getAttribute(
318                 ClientContext.SCHEME_REGISTRY);
319         if (reg == null) {
320             reg = this.manager.getSchemeRegistry();
321         }
322         return reg;
323     }
324 
325     @Override
326     public synchronized void open(
327             final HttpRoute route,
328             final HttpContext context,
329             final HttpParams params) throws IOException {
330         final HttpPoolEntry entry = ensurePoolEntry();
331         final RouteTracker tracker = entry.getTracker();
332         if (tracker.isConnected()) {
333             throw new IllegalStateException("Connection already open");
334         }
335 
336         final HttpHost target = route.getTargetHost();
337         final HttpHost proxy = route.getProxyHost();
338         IOSession ioSession = entry.getConnection();
339 
340         if (proxy == null) {
341             final AsyncScheme scheme = getSchemeRegistry(context).getScheme(target);
342             final LayeringStrategy layeringStrategy = scheme.getLayeringStrategy();
343             if (layeringStrategy != null) {
344                 ioSession = layeringStrategy.layer(ioSession);
345             }
346         }
347 
348         final ClientAsyncConnection conn = this.connFactory.create(
349                 "http-outgoing-" + entry.getId(),
350                 ioSession,
351                 params);
352         ioSession.setAttribute(IOEventDispatch.CONNECTION_KEY, conn);
353 
354         if (proxy == null) {
355             tracker.connectTarget(conn.getIOSession() instanceof SSLIOSession);
356         } else {
357             tracker.connectProxy(proxy, false);
358         }
359     }
360 
361     @Override
362     public synchronized void tunnelProxy(
363             final HttpHost next, final HttpParams params) throws IOException {
364         final HttpPoolEntry entry = ensurePoolEntry();
365         final RouteTracker tracker = entry.getTracker();
366         if (!tracker.isConnected()) {
367             throw new IllegalStateException("Connection not open");
368         }
369         tracker.tunnelProxy(next, false);
370     }
371 
372     @Override
373     public synchronized void tunnelTarget(
374             final HttpParams params) throws IOException {
375         final HttpPoolEntry entry = ensurePoolEntry();
376         final RouteTracker tracker = entry.getTracker();
377         if (!tracker.isConnected()) {
378             throw new IllegalStateException("Connection not open");
379         }
380         if (tracker.isTunnelled()) {
381             throw new IllegalStateException("Connection is already tunnelled");
382         }
383         tracker.tunnelTarget(false);
384     }
385 
386     @Override
387     public synchronized void layerProtocol(
388             final HttpContext context, final HttpParams params) throws IOException {
389         final HttpPoolEntry entry = ensurePoolEntry();
390         final RouteTracker tracker = entry.getTracker();
391         if (!tracker.isConnected()) {
392             throw new IllegalStateException("Connection not open");
393         }
394         if (!tracker.isTunnelled()) {
395             throw new IllegalStateException("Protocol layering without a tunnel not supported");
396         }
397         if (tracker.isLayered()) {
398             throw new IllegalStateException("Multiple protocol layering not supported");
399         }
400         final HttpHost target = tracker.getTargetHost();
401         final AsyncScheme scheme = getSchemeRegistry(context).getScheme(target);
402         final LayeringStrategy layeringStrategy = scheme.getLayeringStrategy();
403         if (layeringStrategy == null) {
404             throw new IllegalStateException(scheme.getName() +
405                     " scheme does not provider support for protocol layering");
406         }
407         final IOSession ioSession = entry.getConnection();
408         final ClientAsyncConnection./../org/apache/http/nio/conn/ClientAsyncConnection.html#ClientAsyncConnection">ClientAsyncConnection conn = (ClientAsyncConnection) ioSession.getAttribute(
409                 IOEventDispatch.CONNECTION_KEY);
410         conn.upgrade(layeringStrategy.layer(ioSession));
411         tracker.layerProtocol(layeringStrategy.isSecure());
412     }
413 
414     @Override
415     public synchronized void releaseConnection() {
416         if (this.poolEntry == null) {
417             return;
418         }
419         this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS);
420         this.poolEntry = null;
421     }
422 
423     @Override
424     public synchronized void abortConnection() {
425         if (this.poolEntry == null) {
426             return;
427         }
428         this.reusable = false;
429         final IOSession ioSession = this.poolEntry.getConnection();
430         final ClientAsyncConnection./../org/apache/http/nio/conn/ClientAsyncConnection.html#ClientAsyncConnection">ClientAsyncConnection conn = (ClientAsyncConnection) ioSession.getAttribute(
431                 IOEventDispatch.CONNECTION_KEY);
432         try {
433             conn.shutdown();
434         } catch (final IOException ignore) {
435         }
436         this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS);
437         this.poolEntry = null;
438     }
439 
440     @Override
441     public synchronized String toString() {
442         return this.poolEntry != null ? this.poolEntry.toString() : "released";
443     }
444 
445 }