001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.vfs2.provider.http;
018
019import org.apache.commons.httpclient.Cookie;
020import org.apache.commons.httpclient.HostConfiguration;
021import org.apache.commons.httpclient.HttpClient;
022import org.apache.commons.httpclient.HttpConnectionManager;
023import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
024import org.apache.commons.httpclient.UsernamePasswordCredentials;
025import org.apache.commons.httpclient.auth.AuthScope;
026import org.apache.commons.httpclient.params.HttpClientParams;
027import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
028import org.apache.commons.vfs2.FileSystemException;
029import org.apache.commons.vfs2.FileSystemOptions;
030import org.apache.commons.vfs2.UserAuthenticationData;
031import org.apache.commons.vfs2.UserAuthenticator;
032import org.apache.commons.vfs2.util.UserAuthenticatorUtils;
033
034/**
035 * Create a HttpClient instance.
036 */
037public final class HttpClientFactory {
038    private HttpClientFactory() {
039    }
040
041    public static HttpClient createConnection(final String scheme, final String hostname, final int port,
042            final String username, final String password, final FileSystemOptions fileSystemOptions)
043            throws FileSystemException {
044        return createConnection(HttpFileSystemConfigBuilder.getInstance(), scheme, hostname, port, username, password,
045                fileSystemOptions);
046    }
047
048    /**
049     * Creates a new connection to the server.
050     *
051     * @param builder The HttpFileSystemConfigBuilder.
052     * @param scheme The protocol.
053     * @param hostname The hostname.
054     * @param port The port number.
055     * @param username The username.
056     * @param password The password
057     * @param fileSystemOptions The file system options.
058     * @return a new HttpClient connection.
059     * @throws FileSystemException if an error occurs.
060     * @since 2.0
061     */
062    public static HttpClient createConnection(final HttpFileSystemConfigBuilder builder, final String scheme,
063            final String hostname, final int port, final String username, final String password,
064            final FileSystemOptions fileSystemOptions) throws FileSystemException {
065        HttpClient client;
066        try {
067            final HttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
068            final HttpConnectionManagerParams connectionMgrParams = mgr.getParams();
069
070            client = new HttpClient(mgr);
071
072            final HostConfiguration config = new HostConfiguration();
073            config.setHost(hostname, port, scheme);
074
075            if (fileSystemOptions != null) {
076                final String proxyHost = builder.getProxyHost(fileSystemOptions);
077                final int proxyPort = builder.getProxyPort(fileSystemOptions);
078
079                if (proxyHost != null && proxyHost.length() > 0 && proxyPort > 0) {
080                    config.setProxy(proxyHost, proxyPort);
081                }
082
083                final UserAuthenticator proxyAuth = builder.getProxyAuthenticator(fileSystemOptions);
084                if (proxyAuth != null) {
085                    final UserAuthenticationData authData = UserAuthenticatorUtils.authenticate(proxyAuth,
086                            new UserAuthenticationData.Type[] { UserAuthenticationData.USERNAME,
087                                    UserAuthenticationData.PASSWORD });
088
089                    if (authData != null) {
090                        final UsernamePasswordCredentials proxyCreds = new UsernamePasswordCredentials(
091                                UserAuthenticatorUtils.toString(UserAuthenticatorUtils.getData(authData,
092                                        UserAuthenticationData.USERNAME, null)),
093                                UserAuthenticatorUtils.toString(UserAuthenticatorUtils.getData(authData,
094                                        UserAuthenticationData.PASSWORD, null)));
095
096                        final AuthScope scope = new AuthScope(proxyHost, AuthScope.ANY_PORT);
097                        client.getState().setProxyCredentials(scope, proxyCreds);
098                    }
099
100                    if (builder.isPreemptiveAuth(fileSystemOptions)) {
101                        final HttpClientParams httpClientParams = new HttpClientParams();
102                        httpClientParams.setAuthenticationPreemptive(true);
103                        client.setParams(httpClientParams);
104                    }
105                }
106
107                final Cookie[] cookies = builder.getCookies(fileSystemOptions);
108                if (cookies != null) {
109                    client.getState().addCookies(cookies);
110                }
111            }
112            /**
113             * ConnectionManager set methods must be called after the host & port and proxy host & port are set in the
114             * HostConfiguration. They are all used as part of the key when HttpConnectionManagerParams tries to locate
115             * the host configuration.
116             */
117            connectionMgrParams.setMaxConnectionsPerHost(config, builder.getMaxConnectionsPerHost(fileSystemOptions));
118            connectionMgrParams.setMaxTotalConnections(builder.getMaxTotalConnections(fileSystemOptions));
119
120            connectionMgrParams.setConnectionTimeout(builder.getConnectionTimeout(fileSystemOptions));
121            connectionMgrParams.setSoTimeout(builder.getSoTimeout(fileSystemOptions));
122
123            client.setHostConfiguration(config);
124
125            if (username != null) {
126                final UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);
127                final AuthScope scope = new AuthScope(hostname, AuthScope.ANY_PORT);
128                client.getState().setCredentials(scope, creds);
129            }
130        } catch (final Exception exc) {
131            throw new FileSystemException("vfs.provider.http/connect.error", exc, hostname);
132        }
133
134        return client;
135    }
136}