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 */
027package org.apache.http.impl.pool;
028
029import java.io.IOException;
030import java.net.InetSocketAddress;
031import java.net.Socket;
032
033import javax.net.SocketFactory;
034import javax.net.ssl.SSLSocketFactory;
035
036import org.apache.http.HttpClientConnection;
037import org.apache.http.HttpConnectionFactory;
038import org.apache.http.HttpHost;
039import org.apache.http.annotation.ThreadingBehavior;
040import org.apache.http.annotation.Contract;
041import org.apache.http.config.ConnectionConfig;
042import org.apache.http.config.SocketConfig;
043import org.apache.http.impl.DefaultBHttpClientConnection;
044import org.apache.http.impl.DefaultBHttpClientConnectionFactory;
045import org.apache.http.params.CoreConnectionPNames;
046import org.apache.http.params.HttpParamConfig;
047import org.apache.http.params.HttpParams;
048import org.apache.http.pool.ConnFactory;
049import org.apache.http.util.Args;
050
051/**
052 * A very basic {@link ConnFactory} implementation that creates
053 * {@link HttpClientConnection} instances given a {@link HttpHost} instance.
054 *
055 * @see HttpHost
056 * @since 4.2
057 */
058@SuppressWarnings("deprecation")
059@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
060public class BasicConnFactory implements ConnFactory<HttpHost, HttpClientConnection> {
061
062    private final SocketFactory plainfactory;
063    private final SSLSocketFactory sslfactory;
064    private final int connectTimeout;
065    private final SocketConfig sconfig;
066    private final HttpConnectionFactory<? extends HttpClientConnection> connFactory;
067
068    /**
069     * @deprecated (4.3) use
070     *   {@link BasicConnFactory#BasicConnFactory(SocketFactory, SSLSocketFactory, int,
071     *     SocketConfig, ConnectionConfig)}.
072     */
073    @Deprecated
074    public BasicConnFactory(final SSLSocketFactory sslfactory, final HttpParams params) {
075        super();
076        Args.notNull(params, "HTTP params");
077        this.plainfactory = null;
078        this.sslfactory = sslfactory;
079        this.connectTimeout = params.getIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 0);
080        this.sconfig = HttpParamConfig.getSocketConfig(params);
081        this.connFactory = new DefaultBHttpClientConnectionFactory(
082                HttpParamConfig.getConnectionConfig(params));
083    }
084
085    /**
086     * @deprecated (4.3) use
087     *   {@link BasicConnFactory#BasicConnFactory(int, SocketConfig, ConnectionConfig)}.
088     */
089    @Deprecated
090    public BasicConnFactory(final HttpParams params) {
091        this(null, params);
092    }
093
094    /**
095     * @since 4.3
096     */
097    public BasicConnFactory(
098            final SocketFactory plainfactory,
099            final SSLSocketFactory sslfactory,
100            final int connectTimeout,
101            final SocketConfig sconfig,
102            final ConnectionConfig cconfig) {
103        super();
104        this.plainfactory = plainfactory;
105        this.sslfactory = sslfactory;
106        this.connectTimeout = connectTimeout;
107        this.sconfig = sconfig != null ? sconfig : SocketConfig.DEFAULT;
108        this.connFactory = new DefaultBHttpClientConnectionFactory(
109                cconfig != null ? cconfig : ConnectionConfig.DEFAULT);
110    }
111
112    /**
113     * @since 4.3
114     */
115    public BasicConnFactory(
116            final int connectTimeout, final SocketConfig sconfig, final ConnectionConfig cconfig) {
117        this(null, null, connectTimeout, sconfig, cconfig);
118    }
119
120    /**
121     * @since 4.3
122     */
123    public BasicConnFactory(final SocketConfig sconfig, final ConnectionConfig cconfig) {
124        this(null, null, 0, sconfig, cconfig);
125    }
126
127    /**
128     * @since 4.3
129     */
130    public BasicConnFactory() {
131        this(null, null, 0, SocketConfig.DEFAULT, ConnectionConfig.DEFAULT);
132    }
133
134    /**
135     * @deprecated (4.3) no longer used.
136     */
137    @Deprecated
138    protected HttpClientConnection create(final Socket socket, final HttpParams params) throws IOException {
139        final int bufsize = params.getIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024);
140        final DefaultBHttpClientConnection conn = new DefaultBHttpClientConnection(bufsize);
141        conn.bind(socket);
142        return conn;
143    }
144
145    @Override
146    public HttpClientConnection create(final HttpHost host) throws IOException {
147        final String scheme = host.getSchemeName();
148        Socket socket = null;
149        if ("http".equalsIgnoreCase(scheme)) {
150            socket = this.plainfactory != null ? this.plainfactory.createSocket() :
151                    new Socket();
152        } if ("https".equalsIgnoreCase(scheme)) {
153            socket = (this.sslfactory != null ? this.sslfactory :
154                    SSLSocketFactory.getDefault()).createSocket();
155        }
156        if (socket == null) {
157            throw new IOException(scheme + " scheme is not supported");
158        }
159        final String hostname = host.getHostName();
160        int port = host.getPort();
161        if (port == -1) {
162            if (host.getSchemeName().equalsIgnoreCase("http")) {
163                port = 80;
164            } else if (host.getSchemeName().equalsIgnoreCase("https")) {
165                port = 443;
166            }
167        }
168        socket.setSoTimeout(this.sconfig.getSoTimeout());
169        if (this.sconfig.getSndBufSize() > 0) {
170            socket.setSendBufferSize(this.sconfig.getSndBufSize());
171        }
172        if (this.sconfig.getRcvBufSize() > 0) {
173            socket.setReceiveBufferSize(this.sconfig.getRcvBufSize());
174        }
175        socket.setTcpNoDelay(this.sconfig.isTcpNoDelay());
176        final int linger = this.sconfig.getSoLinger();
177        if (linger >= 0) {
178            socket.setSoLinger(true, linger);
179        }
180        socket.setKeepAlive(this.sconfig.isSoKeepAlive());
181        socket.connect(new InetSocketAddress(hostname, port), this.connectTimeout);
182        return this.connFactory.createConnection(socket);
183    }
184
185}