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 */
027
028package org.apache.http.impl.nio;
029
030import java.io.IOException;
031
032import javax.net.ssl.SSLContext;
033
034import org.apache.http.annotation.Contract;
035import org.apache.http.annotation.ThreadingBehavior;
036import org.apache.http.config.ConnectionConfig;
037import org.apache.http.impl.nio.reactor.AbstractIODispatch;
038import org.apache.http.nio.NHttpClientEventHandler;
039import org.apache.http.nio.NHttpConnectionFactory;
040import org.apache.http.nio.reactor.IOSession;
041import org.apache.http.nio.reactor.ssl.SSLSetupHandler;
042import org.apache.http.params.HttpParams;
043import org.apache.http.util.Args;
044
045/**
046 * Default {@link org.apache.http.nio.reactor.IOEventDispatch} implementation
047 * that supports both plain (non-encrypted) and SSL encrypted client side HTTP
048 * connections.
049 *
050 * @since 4.2
051 */
052@SuppressWarnings("deprecation")
053@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
054public class DefaultHttpClientIODispatch
055                    extends AbstractIODispatch<DefaultNHttpClientConnection> {
056
057    /**
058     * Creates a new instance of this class to be used for dispatching I/O event
059     * notifications to the given protocol handler.
060     *
061     * @param handler the client protocol handler.
062     * @param sslContext an SSLContext or null (for a plain text connection.)
063     * @param config a connection configuration
064     * @return a new instance
065     * @since 4.4.7
066     */
067    public static DefaultHttpClientIODispatch create(final NHttpClientEventHandler handler,
068            final SSLContext sslContext,
069            final ConnectionConfig config) {
070        return sslContext == null ? new DefaultHttpClientIODispatch(handler, config)
071                : new DefaultHttpClientIODispatch(handler, sslContext, config);
072    }
073
074    /**
075     * Creates a new instance of this class to be used for dispatching I/O event
076     * notifications to the given protocol handler.
077     *
078     * @param handler the client protocol handler.
079     * @param sslContext an SSLContext or null (for a plain text connection.)
080     * @param sslHandler customizes various aspects of the TLS/SSL protocol.
081     * @param config a connection configuration
082     * @return a new instance
083     * @since 4.4.7
084     */
085    public static DefaultHttpClientIODispatch create(final NHttpClientEventHandler handler,
086            final SSLContext sslContext,
087            final SSLSetupHandler sslHandler,
088            final ConnectionConfig config) {
089        return sslContext == null ? new DefaultHttpClientIODispatch(handler, config)
090                : new DefaultHttpClientIODispatch(handler, sslContext, sslHandler, config);
091    }
092
093    private final NHttpClientEventHandler handler;
094    private final NHttpConnectionFactory<DefaultNHttpClientConnection> connFactory;
095
096    /**
097     * Creates a new instance of this class to be used for dispatching I/O event
098     * notifications to the given protocol handler.
099     *
100     * @param handler the client protocol handler.
101     * @param connFactory HTTP client connection factory.
102     */
103    public DefaultHttpClientIODispatch(
104            final NHttpClientEventHandler handler,
105            final NHttpConnectionFactory<DefaultNHttpClientConnection> connFactory) {
106        super();
107        this.handler = Args.notNull(handler, "HTTP client handler");
108        this.connFactory = Args.notNull(connFactory, "HTTP client connection factory");
109    }
110
111    /**
112     * @deprecated (4.3) use {@link DefaultHttpClientIODispatch#DefaultHttpClientIODispatch(
113     *  NHttpClientEventHandler, ConnectionConfig)}
114     */
115    @Deprecated
116    public DefaultHttpClientIODispatch(
117            final NHttpClientEventHandler handler,
118            final HttpParams params) {
119        this(handler, new DefaultNHttpClientConnectionFactory(params));
120    }
121
122    /**
123     * @deprecated (4.3) use {@link DefaultHttpClientIODispatch#DefaultHttpClientIODispatch(
124     *  NHttpClientEventHandler, SSLContext, SSLSetupHandler, ConnectionConfig)}
125     */
126    @Deprecated
127    public DefaultHttpClientIODispatch(
128            final NHttpClientEventHandler handler,
129            final SSLContext sslContext,
130            final SSLSetupHandler sslHandler,
131            final HttpParams params) {
132        this(handler, new SSLNHttpClientConnectionFactory(sslContext, sslHandler, params));
133    }
134
135    /**
136     * @deprecated (4.3) use {@link DefaultHttpClientIODispatch#DefaultHttpClientIODispatch(
137     *   NHttpClientEventHandler, SSLContext, ConnectionConfig)}
138     */
139    @Deprecated
140    public DefaultHttpClientIODispatch(
141            final NHttpClientEventHandler handler,
142            final SSLContext sslContext,
143            final HttpParams params) {
144        this(handler, sslContext, null, params);
145    }
146
147    /**
148     * @since 4.3
149     */
150    public DefaultHttpClientIODispatch(final NHttpClientEventHandler handler, final ConnectionConfig config) {
151        this(handler, new DefaultNHttpClientConnectionFactory(config));
152    }
153
154    /**
155     * @since 4.3
156     */
157    public DefaultHttpClientIODispatch(
158            final NHttpClientEventHandler handler,
159            final SSLContext sslContext,
160            final SSLSetupHandler sslHandler,
161            final ConnectionConfig config) {
162        this(handler, new SSLNHttpClientConnectionFactory(sslContext, sslHandler, config));
163    }
164
165    /**
166     * @since 4.3
167     */
168    public DefaultHttpClientIODispatch(
169            final NHttpClientEventHandler handler,
170            final SSLContext sslContext,
171            final ConnectionConfig config) {
172        this(handler, new SSLNHttpClientConnectionFactory(sslContext, null, config));
173    }
174
175    @Override
176    protected DefaultNHttpClientConnection createConnection(final IOSession session) {
177        return this.connFactory.createConnection(session);
178    }
179
180    @Override
181    protected void onConnected(final DefaultNHttpClientConnection conn) {
182        final Object attachment = conn.getContext().getAttribute(IOSession.ATTACHMENT_KEY);
183        try {
184            this.handler.connected(conn, attachment);
185        } catch (final Exception ex) {
186            this.handler.exception(conn, ex);
187        }
188    }
189
190    @Override
191    protected void onClosed(final DefaultNHttpClientConnection conn) {
192        this.handler.closed(conn);
193    }
194
195    @Override
196    protected void onException(final DefaultNHttpClientConnection conn, final IOException ex) {
197        this.handler.exception(conn, ex);
198    }
199
200    @Override
201    protected void onInputReady(final DefaultNHttpClientConnection conn) {
202        conn.consumeInput(this.handler);
203    }
204
205    @Override
206    protected void onOutputReady(final DefaultNHttpClientConnection conn) {
207        conn.produceOutput(this.handler);
208    }
209
210    @Override
211    protected void onTimeout(final DefaultNHttpClientConnection conn) {
212        try {
213            this.handler.timeout(conn);
214        } catch (final Exception ex) {
215            this.handler.exception(conn, ex);
216        }
217    }
218
219}