001 package org.sonar.ide.wsclient;
002
003 import java.net.Authenticator;
004 import java.net.InetAddress;
005 import java.net.InetSocketAddress;
006 import java.net.PasswordAuthentication;
007 import java.net.Proxy;
008 import java.net.ProxySelector;
009 import java.net.URI;
010 import java.util.List;
011
012 import org.apache.commons.httpclient.Credentials;
013 import org.apache.commons.httpclient.HttpClient;
014 import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
015 import org.apache.commons.httpclient.UsernamePasswordCredentials;
016 import org.apache.commons.httpclient.auth.AuthScope;
017 import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
018 import org.sonar.wsclient.Host;
019 import org.sonar.wsclient.connectors.HttpClient3Connector;
020
021 /**
022 * @author Evgeny Mandrikov
023 */
024 public final class HttpClient3ConnectorFactory {
025 protected static final int TIMEOUT_MS = 30000;
026 private static final int MAX_TOTAL_CONNECTIONS = 40;
027 private static final int MAX_HOST_CONNECTIONS = 4;
028
029 /**
030 * Hide utility-class constructor.
031 */
032 private HttpClient3ConnectorFactory() {
033 }
034
035 /**
036 * Workaround for <a href="http://jira.codehaus.org/browse/SONAR-1715">SONAR-1715</a> and
037 * for <a href="http://jira.codehaus.org/browse/SONAR-1586">SONAR-1586</a>.
038 * <p>
039 * TODO Godin: I suppose that call of method {@link HttpClient3Connector#configureCredentials()} should be added to constructor
040 * {@link HttpClient3Connector#HttpClient3Connector(Host, HttpClient)}
041 * </p>
042 *
043 * @param server Sonar server
044 * @return configured {@link HttpClient3Connector}
045 * @see org.sonar.wsclient.connectors.HttpClient3Connector#createClient()
046 * @see org.sonar.wsclient.connectors.HttpClient3Connector#configureCredentials()
047 */
048 public static HttpClient3Connector createConnector(Host server) {
049 // createClient
050 final HttpConnectionManagerParams params = new HttpConnectionManagerParams();
051 params.setConnectionTimeout(TIMEOUT_MS);
052 params.setSoTimeout(TIMEOUT_MS);
053 params.setDefaultMaxConnectionsPerHost(MAX_HOST_CONNECTIONS);
054 params.setMaxTotalConnections(MAX_TOTAL_CONNECTIONS);
055 final MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
056 connectionManager.setParams(params);
057 HttpClient httpClient = new HttpClient(connectionManager);
058
059 // configureCredentials
060 if (server.getUsername() != null) {
061 httpClient.getParams().setAuthenticationPreemptive(true);
062 Credentials defaultcreds = new UsernamePasswordCredentials(server.getUsername(), server.getPassword());
063 httpClient.getState().setCredentials(AuthScope.ANY, defaultcreds);
064 }
065
066 // TODO Godin: ugly hack to use ProxySelector with commons-httpclient 3.1
067 try {
068 List<Proxy> list = ProxySelector.getDefault().select(new URI(server.getHost()));
069 for (Proxy proxy : list) {
070 if (proxy.type() == Proxy.Type.HTTP) {
071 // Proxy
072 InetSocketAddress addr = (InetSocketAddress) proxy.address();
073 httpClient.getHostConfiguration().setProxy(addr.getHostName(), addr.getPort());
074 // Proxy auth
075 InetAddress proxyInetAddress = InetAddress.getByName(addr.getHostName());
076 PasswordAuthentication auth = Authenticator.requestPasswordAuthentication(proxyInetAddress, addr.getPort(), null, null, null);
077 if (auth != null) {
078 Credentials defaultcreds = new UsernamePasswordCredentials(auth.getUserName(), new String(auth.getPassword()));
079 httpClient.getState().setProxyCredentials(AuthScope.ANY, defaultcreds);
080 }
081 }
082 }
083 } catch (Exception e) {
084 e.printStackTrace();
085 }
086
087 return new HttpClient3Connector(server, httpClient);
088 }
089 }