org.eclipse.mylyn.commons.repositories.http.core.HttpUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.mylyn.commons.repositories.http.core.HttpUtil.java

Source

/*******************************************************************************
 * Copyright (c) 2011 Tasktop Technologies and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Tasktop Technologies - initial API and implementation
 *******************************************************************************/

package org.eclipse.mylyn.commons.repositories.http.core;

import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.Locale;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.NTCredentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.params.AuthPolicy;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.scheme.SchemeSocketFactory;
import org.apache.http.impl.EnglishReasonPhraseCatalog;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.eclipse.core.net.proxy.IProxyData;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.mylyn.commons.core.CoreUtil;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.commons.core.net.AuthenticatedProxy;
import org.eclipse.mylyn.commons.core.net.NetUtil;
import org.eclipse.mylyn.commons.core.operations.CancellableOperationMonitorThread;
import org.eclipse.mylyn.commons.core.operations.ICancellableOperation;
import org.eclipse.mylyn.commons.core.operations.IOperationMonitor;
import org.eclipse.mylyn.commons.core.operations.OperationUtil;
import org.eclipse.mylyn.commons.repositories.core.RepositoryLocation;
import org.eclipse.mylyn.commons.repositories.core.auth.AuthenticationType;
import org.eclipse.mylyn.commons.repositories.core.auth.UserCredentials;
import org.eclipse.mylyn.internal.commons.repositories.http.core.IdleConnectionMonitorThread;
import org.eclipse.mylyn.internal.commons.repositories.http.core.PollingProtocolSocketFactory;
import org.eclipse.mylyn.internal.commons.repositories.http.core.PollingSslProtocolSocketFactory;

/**
 * @author Steffen Pingel
 * @author Shawn Minto
 * @author Christian Janz
 * @noinstantiate This class is not intended to be instantiated by clients.
 */
public class HttpUtil {

    static {
        CoreUtil.initializeLoggingSettings();
    }

    @SuppressWarnings("unused")
    private static final int BUFFER_SIZE = 4096;

    @SuppressWarnings("unused")
    private static final long CLOSE_TIMEOUT = -1;

    /**
     * @see IdleConnectionMonitorThread
     */
    private static final int CONNECTION_TIMEOUT_INTERVAL = 1 * 30 * 1000;

    private static final int CONNNECT_TIMEOUT = 60 * 1000;

    private static final int HTTP_PORT = 80;

    private static final int HTTPS_PORT = 443;

    private static final int POLL_INTERVAL = 500;

    private static final int SOCKET_TIMEOUT = 3 * 60 * 1000;

    @SuppressWarnings("unused")
    private static final int POLL_ATTEMPTS = SOCKET_TIMEOUT / POLL_INTERVAL;

    private static SchemeSocketFactory socketFactory = new PollingProtocolSocketFactory();

    private static SchemeSocketFactory sslSocketFactory = new PollingSslProtocolSocketFactory();

    static final String ID_PLUGIN = "org.eclipse.mylyn.commons.repositories.http"; //$NON-NLS-1$

    private static ThreadSafeClientConnManager connectionManager;

    static final String CONTEXT_KEY_MONITOR_THREAD = CancellableOperationMonitorThread.class.getName();

    public static void configureClient(AbstractHttpClient client, String userAgent) {
        HttpClientParams.setCookiePolicy(client.getParams(), CookiePolicy.BEST_MATCH);

        if (userAgent != null) {
            HttpProtocolParams.setUserAgent(client.getParams(), userAgent);
        }
        HttpProtocolParams.setUseExpectContinue(client.getParams(), true);
        client.getParams().setBooleanParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);

        HttpConnectionParams.setConnectionTimeout(client.getParams(), CONNNECT_TIMEOUT);
        HttpConnectionParams.setSoTimeout(client.getParams(), SOCKET_TIMEOUT);

        //AuthParams.setCredentialCharset(client.getParams(), "UTF-8");
    }

    public static void configureAuthentication(AbstractHttpClient client, RepositoryLocation location) {
        UserCredentials credentials = location.getCredentials(AuthenticationType.HTTP);
        if (credentials != null) {
            configureAuthentication(client, location, credentials);
        }
    }

    public static void configureAuthentication(AbstractHttpClient client, RepositoryLocation location,
            UserCredentials credentials) {
        Assert.isNotNull(client);
        Assert.isNotNull(location);
        Assert.isNotNull(credentials);
        String url = location.getUrl();
        Assert.isNotNull(url, "The location url must not be null"); //$NON-NLS-1$

        String host = NetUtil.getHost(url);
        int port = NetUtil.getPort(url);

        NTCredentials ntlmCredentials = getNtCredentials(credentials, ""); //$NON-NLS-1$
        if (ntlmCredentials != null) {
            AuthScope authScopeNtlm = new AuthScope(host, port, AuthScope.ANY_REALM, AuthPolicy.NTLM);
            client.getCredentialsProvider().setCredentials(authScopeNtlm, ntlmCredentials);
        }

        UsernamePasswordCredentials usernamePasswordCredentials = getUserNamePasswordCredentials(credentials);
        AuthScope authScopeAny = new AuthScope(host, port, AuthScope.ANY_REALM);
        client.getCredentialsProvider().setCredentials(authScopeAny, usernamePasswordCredentials);
    }

    public static HttpHost createHost(HttpRequestBase method) {
        URI uri = method.getURI();
        return new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
    }

    public static HttpResponse execute(final AbstractHttpClient client, final HttpContext context,
            final HttpRequestBase method, IProgressMonitor monitor) throws IOException {
        return execute(client, createHost(method), context, method, monitor);
    }

    public static HttpResponse execute(final AbstractHttpClient client, final HttpHost host,
            final HttpContext context, final HttpRequestBase method, final IProgressMonitor progress)
            throws IOException {
        Assert.isNotNull(client);
        Assert.isNotNull(method);

        final IOperationMonitor monitor = OperationUtil.convert(progress);
        ICancellableOperation operation = new ICancellableOperation() {
            @Override
            public void abort() {
                method.abort();
            }

            @Override
            public boolean isCanceled() {
                return monitor.isCanceled();
            }
        };

        CancellableOperationMonitorThread thread = null;
        if (context != null) {
            thread = (CancellableOperationMonitorThread) context.getAttribute(CONTEXT_KEY_MONITOR_THREAD);
        }
        if (thread != null) {
            thread.addOperation(operation);
        }
        try {
            return client.execute(host, method, context);
        } catch (InterruptedIOException e) {
            if (monitor.isCanceled()) {
                throw new OperationCanceledException();
            }
            throw e;
        } finally {
            if (thread != null) {
                thread.removeOperation(operation);
            }
        }
    }

    public static NTCredentials getNtCredentials(UserCredentials credentials, String workstation) {
        String username = credentials.getUserName();
        int i = username.indexOf("\\"); //$NON-NLS-1$
        if (i > 0 && i < username.length() - 1) {
            //         try {
            //            InetAddress localHost = InetAddress.getLocalHost();
            //            if (localHost != null) {
            //               hostName = localHost.getHostName();
            //            }
            //         } catch (UnknownHostException e) {
            //            StatusHandler.log(new Status(IStatus.ERROR, ID_PLUGIN,
            //                  "Unable to get hostname.  Defaulting to servers host.", e));
            //         }
            return new NTCredentials(username.substring(i + 1), credentials.getPassword(), workstation,
                    username.substring(0, i));
        }
        return null;
    }

    public static UsernamePasswordCredentials getUserNamePasswordCredentials(UserCredentials credentials) {
        return new UsernamePasswordCredentials(credentials.getUserName(), credentials.getPassword());
    }

    public static InputStream getResponseBodyAsStream(HttpEntity entity, IProgressMonitor monitor)
            throws IOException {
        monitor = OperationUtil.convert(monitor);
        return entity.getContent();
        //      return new PollingInputStream(new TimeoutInputStream(entity.getContent(), BUFFER_SIZE, POLL_INTERVAL,
        //            CLOSE_TIMEOUT), POLL_ATTEMPTS, monitor);
    }

    public static SchemeRegistry getSchemeRegistry() {
        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme("http", HTTP_PORT, socketFactory)); //$NON-NLS-1$
        schemeRegistry.register(new Scheme("https", HTTPS_PORT, sslSocketFactory)); //$NON-NLS-1$
        return schemeRegistry;
    }

    public static void configureProxy(AbstractHttpClient client, RepositoryLocation location) {
        Assert.isNotNull(client);
        Assert.isNotNull(location);
        String url = location.getUrl();
        Assert.isNotNull(url, "The location url must not be null"); //$NON-NLS-1$

        String host = NetUtil.getHost(url);
        Proxy proxy;
        if (NetUtil.isUrlHttps(url)) {
            proxy = location.getProxyForHost(host, IProxyData.HTTPS_PROXY_TYPE);
        } else {
            proxy = location.getProxyForHost(host, IProxyData.HTTP_PROXY_TYPE);
        }

        if (proxy != null && !Proxy.NO_PROXY.equals(proxy)) {
            InetSocketAddress address = (InetSocketAddress) proxy.address();

            client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,
                    new HttpHost(address.getHostName(), address.getPort()));

            if (proxy instanceof AuthenticatedProxy) {
                AuthenticatedProxy authProxy = (AuthenticatedProxy) proxy;
                Credentials credentials = getCredentials(authProxy.getUserName(), authProxy.getPassword(),
                        address.getAddress(), false);
                if (credentials instanceof NTCredentials) {
                    AuthScope proxyAuthScopeNTLM = new AuthScope(address.getHostName(), address.getPort(),
                            AuthScope.ANY_REALM, AuthPolicy.NTLM);
                    client.getCredentialsProvider().setCredentials(proxyAuthScopeNTLM, credentials);

                    AuthScope proxyAuthScopeAny = new AuthScope(address.getHostName(), address.getPort(),
                            AuthScope.ANY_REALM);
                    Credentials usernamePasswordCredentials = getCredentials(authProxy.getUserName(),
                            authProxy.getPassword(), address.getAddress(), true);
                    client.getCredentialsProvider().setCredentials(proxyAuthScopeAny, usernamePasswordCredentials);

                } else {
                    AuthScope proxyAuthScope = new AuthScope(address.getHostName(), address.getPort(),
                            AuthScope.ANY_REALM);
                    client.getCredentialsProvider().setCredentials(proxyAuthScope, credentials);
                }
            }
        } else {
            client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, null);
        }
    }

    static Credentials getCredentials(final String username, final String password, final InetAddress address,
            boolean forceUserNamePassword) {
        int i = username.indexOf("\\"); //$NON-NLS-1$
        if (i > 0 && i < username.length() - 1 && address != null && !forceUserNamePassword) {
            String hostName = address.getHostName();
            try {
                InetAddress localHost = InetAddress.getLocalHost();
                if (localHost != null) {
                    hostName = localHost.getHostName();
                }
            } catch (UnknownHostException e) {
                StatusHandler.log(new Status(IStatus.ERROR, ID_PLUGIN,
                        "Unable to get hostname.  Defaulting to servers host.", e)); //$NON-NLS-1$
            }
            if (hostName == null) {
                hostName = address.getHostName();
            }
            return new NTCredentials(username.substring(i + 1), password, hostName, username.substring(0, i));
        } else {
            return new UsernamePasswordCredentials(username, password);
        }
    }

    public static synchronized ThreadSafeClientConnManager getConnectionManager() {
        if (connectionManager == null) {
            connectionManager = new ThreadSafeClientConnManager(HttpUtil.getSchemeRegistry());
            if (CoreUtil.TEST_MODE) {
                connectionManager.setDefaultMaxPerRoute(2);
            } else {
                connectionManager.setDefaultMaxPerRoute(NetUtil.getMaxHttpConnectionsPerHost());
                connectionManager.setMaxTotal(NetUtil.getMaxHttpConnections());
            }

            IdleConnectionMonitorThread thread = new IdleConnectionMonitorThread(CONNECTION_TIMEOUT_INTERVAL);
            thread.setTimeout(CONNNECT_TIMEOUT);
            thread.addConnectionManager(connectionManager);
            thread.start();
        }
        return connectionManager;
    }

    public static String getStatusText(int statusCode) {
        return EnglishReasonPhraseCatalog.INSTANCE.getReason(statusCode, Locale.getDefault());
    }

    public static void release(HttpRequest request, HttpResponse response, IProgressMonitor monitor) {
        Assert.isNotNull(request);
        Assert.isNotNull(response);
        if (monitor != null && monitor.isCanceled() && request instanceof HttpUriRequest) {
            // force a connection close on cancel to avoid blocking to do reading the remainder of the response
            try {
                ((HttpUriRequest) request).abort();
            } catch (UnsupportedOperationException e) {
                // fall back to standard close
                consume(request, response);
            }
        } else {
            consume(request, response);
        }
    }

    private static void consume(HttpRequest request, HttpResponse response) {
        try {
            EntityUtils.consume(response.getEntity());
        } catch (IOException e) {
            // if construction of the stream fails the connection has to be aborted to be released
            try {
                ((HttpUriRequest) request).abort();
            } catch (UnsupportedOperationException e2) {
            }
        } catch (NullPointerException e2) {
            // XXX work-around for bug 368830
        }
    }

}