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  
28  package org.apache.http.impl.nio;
29  
30  import java.io.IOException;
31  
32  import javax.net.ssl.SSLContext;
33  import javax.net.ssl.SSLException;
34  
35  import org.apache.http.HttpResponse;
36  import org.apache.http.HttpResponseFactory;
37  import org.apache.http.impl.DefaultHttpResponseFactory;
38  import org.apache.http.impl.nio.reactor.SSLIOSession;
39  import org.apache.http.impl.nio.reactor.SSLIOSessionHandler;
40  import org.apache.http.impl.nio.reactor.SSLMode;
41  import org.apache.http.nio.NHttpClientHandler;
42  import org.apache.http.nio.NHttpClientIOTarget;
43  import org.apache.http.nio.reactor.IOEventDispatch;
44  import org.apache.http.nio.reactor.IOSession;
45  import org.apache.http.nio.util.ByteBufferAllocator;
46  import org.apache.http.nio.util.HeapByteBufferAllocator;
47  import org.apache.http.params.HttpParams;
48  import org.apache.http.protocol.ExecutionContext;
49  
50  /**
51   * Default implementation of {@link IOEventDispatch} interface for SSL
52   * (encrypted) client-side HTTP connections.
53   * <p>
54   * The following parameters can be used to customize the behavior of this
55   * class:
56   * <ul>
57   *  <li>{@link org.apache.http.params.CoreProtocolPNames#HTTP_ELEMENT_CHARSET}</li>
58   *  <li>{@link org.apache.http.params.CoreConnectionPNames#SOCKET_BUFFER_SIZE}</li>
59   *  <li>{@link org.apache.http.params.CoreConnectionPNames#MAX_HEADER_COUNT}</li>
60   *  <li>{@link org.apache.http.params.CoreConnectionPNames#MAX_LINE_LENGTH}</li>
61   * </ul>
62   *
63   * @since 4.0
64   *
65   * @deprecated (4.2) use {@link org.apache.http.impl.nio.ssl.SSLClientIOEventDispatch}
66   */
67  @Deprecated
68  public class SSLClientIOEventDispatch implements IOEventDispatch {
69  
70      private static final String SSL_SESSION = "SSL_SESSION";
71  
72      protected final NHttpClientHandler handler;
73      protected final SSLContext sslcontext;
74      protected final SSLIOSessionHandler sslHandler;
75      protected final HttpParams params;
76  
77      /**
78       * Creates a new instance of this class to be used for dispatching I/O event
79       * notifications to the given protocol handler using the given
80       * {@link SSLContext}. This I/O dispatcher will transparently handle SSL
81       * protocol aspects for HTTP connections.
82       *
83       * @param handler the client protocol handler.
84       * @param sslcontext the SSL context.
85       * @param sslHandler the SSL handler.
86       * @param params HTTP parameters.
87       */
88      public SSLClientIOEventDispatch(
89              final NHttpClientHandler handler,
90              final SSLContext sslcontext,
91              final SSLIOSessionHandler sslHandler,
92              final HttpParams params) {
93          super();
94          if (handler == null) {
95              throw new IllegalArgumentException("HTTP client handler may not be null");
96          }
97          if (sslcontext == null) {
98              throw new IllegalArgumentException("SSL context may not be null");
99          }
100         if (params == null) {
101             throw new IllegalArgumentException("HTTP parameters may not be null");
102         }
103         this.handler = handler;
104         this.params = params;
105         this.sslcontext = sslcontext;
106         this.sslHandler = sslHandler;
107     }
108 
109     /**
110      * Creates a new instance of this class to be used for dispatching I/O event
111      * notifications to the given protocol handler using the given
112      * {@link SSLContext}. This I/O dispatcher will transparently handle SSL
113      * protocol aspects for HTTP connections.
114      *
115      * @param handler the client protocol handler.
116      * @param sslcontext the SSL context.
117      * @param params HTTP parameters.
118      */
119     public SSLClientIOEventDispatch(
120             final NHttpClientHandler handler,
121             final SSLContext sslcontext,
122             final HttpParams params) {
123         this(handler, sslcontext, null, params);
124     }
125 
126     /**
127      * Creates an instance of {@link HeapByteBufferAllocator} to be used
128      * by HTTP connections for allocating {@link java.nio.ByteBuffer} objects.
129      * <p>
130      * This method can be overridden in a super class in order to provide
131      * a different implementation of the {@link ByteBufferAllocator} interface.
132      *
133      * @return byte buffer allocator.
134      */
135     protected ByteBufferAllocator createByteBufferAllocator() {
136         return new HeapByteBufferAllocator();
137     }
138 
139     /**
140      * Creates an instance of {@link DefaultHttpResponseFactory} to be used
141      * by HTTP connections for creating {@link HttpResponse} objects.
142      * <p>
143      * This method can be overridden in a super class in order to provide
144      * a different implementation of the {@link HttpResponseFactory} interface.
145      *
146      * @return HTTP response factory.
147      */
148     protected HttpResponseFactory createHttpResponseFactory() {
149         return new DefaultHttpResponseFactory();
150     }
151 
152     /**
153      * Creates an instance of {@link DefaultNHttpClientConnection} based on the
154      * given SSL {@link IOSession}.
155      * <p>
156      * This method can be overridden in a super class in order to provide
157      * a different implementation of the {@link NHttpClientIOTarget} interface.
158      *
159      * @param session the underlying SSL I/O session.
160      *
161      * @return newly created HTTP connection.
162      */
163     protected NHttpClientIOTarget createConnection(final IOSession session) {
164         return new DefaultNHttpClientConnection(
165                 session,
166                 createHttpResponseFactory(),
167                 createByteBufferAllocator(),
168                 this.params);
169     }
170 
171     /**
172      * Creates an instance of {@link SSLIOSession} decorating the given
173      * {@link IOSession}.
174      * <p>
175      * This method can be overridden in a super class in order to provide
176      * a different implementation of SSL I/O session.
177      *
178      * @param session the underlying I/O session.
179      * @param sslcontext the SSL context.
180      * @param sslHandler the SSL handler.
181      * @return newly created SSL I/O session.
182      */
183     protected SSLIOSession createSSLIOSession(
184             final IOSession session,
185             final SSLContext sslcontext,
186             final SSLIOSessionHandler sslHandler) {
187         return new SSLIOSession(session, sslcontext, sslHandler);
188     }
189 
190     public void connected(final IOSession session) {
191 
192         SSLIOSession sslSession = createSSLIOSession(
193                 session,
194                 this.sslcontext,
195                 this.sslHandler);
196 
197         NHttpClientIOTarget conn = createConnection(
198                 sslSession);
199 
200         session.setAttribute(ExecutionContext.HTTP_CONNECTION, conn);
201         session.setAttribute(SSL_SESSION, sslSession);
202 
203         Object attachment = session.getAttribute(IOSession.ATTACHMENT_KEY);
204         this.handler.connected(conn, attachment);
205 
206         try {
207             sslSession.bind(SSLMode.CLIENT, this.params);
208         } catch (SSLException ex) {
209             this.handler.exception(conn, ex);
210             sslSession.shutdown();
211         }
212     }
213 
214     public void disconnected(final IOSession session) {
215         NHttpClientIOTarget conn =
216             (NHttpClientIOTarget) session.getAttribute(ExecutionContext.HTTP_CONNECTION);
217         if (conn != null) {
218             this.handler.closed(conn);
219         }
220     }
221 
222     public void inputReady(final IOSession session) {
223         NHttpClientIOTarget conn =
224             (NHttpClientIOTarget) session.getAttribute(ExecutionContext.HTTP_CONNECTION);
225         SSLIOSession sslSession =
226             (SSLIOSession) session.getAttribute(SSL_SESSION);
227 
228         try {
229             if (sslSession.isAppInputReady()) {
230                 conn.consumeInput(this.handler);
231             }
232             sslSession.inboundTransport();
233         } catch (IOException ex) {
234             this.handler.exception(conn, ex);
235             sslSession.shutdown();
236         }
237     }
238 
239     public void outputReady(final IOSession session) {
240         NHttpClientIOTarget conn =
241             (NHttpClientIOTarget) session.getAttribute(ExecutionContext.HTTP_CONNECTION);
242         SSLIOSession sslSession =
243             (SSLIOSession) session.getAttribute(SSL_SESSION);
244 
245         try {
246             if (sslSession.isAppOutputReady()) {
247                 conn.produceOutput(this.handler);
248             }
249             sslSession.outboundTransport();
250         } catch (IOException ex) {
251             this.handler.exception(conn, ex);
252             sslSession.shutdown();
253         }
254     }
255 
256     public void timeout(final IOSession session) {
257         NHttpClientIOTarget conn =
258             (NHttpClientIOTarget) session.getAttribute(ExecutionContext.HTTP_CONNECTION);
259         SSLIOSession sslSession =
260             (SSLIOSession) session.getAttribute(SSL_SESSION);
261 
262         this.handler.timeout(conn);
263         synchronized (sslSession) {
264             if (sslSession.isOutboundDone() && !sslSession.isInboundDone()) {
265                 // The session failed to terminate cleanly
266                 sslSession.shutdown();
267             }
268         }
269     }
270 
271 }