fedora.common.http.WebClient.java Source code

Java tutorial

Introduction

Here is the source code for fedora.common.http.WebClient.java

Source

/* The contents of this file are subject to the license and copyright terms
 * detailed in the license directory at the root of the source tree (also 
 * available online at http://fedora-commons.org/license/).
 */
package fedora.common.http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import java.net.URL;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;

/**
 * A general-purpose, connection-pooling HTTP Client. All methods are
 * thread-safe. Provides option for client to handle HTTP redirects
 * 
 * @version $Id$
 */
public class WebClient {

    /** Seconds to wait before a connection is established. */
    public int TIMEOUT_SECONDS = 20;

    /** Seconds to wait while waiting for data over the socket (SO_TIMEOUT). */
    public int SOCKET_TIMEOUT_SECONDS = 120;

    /** Maxiumum http connections per host */
    public int MAX_CONNECTIONS_PER_HOST = 5;

    /** Maxiumum total http connections */
    public int MAX_TOTAL_CONNECTIONS = 20;

    /** Whether to automatically follow HTTP redirects. */
    public boolean FOLLOW_REDIRECTS = true;

    /**
     * Maximum number of redirects to follow per request if FOLLOW_REDIRECTS is
     * true.
     */
    public int MAX_REDIRECTS = 3;

    /**
     * What the "User-Agent" request header should say. Default is null, which
     * indicates that the header should not be provided.
     */
    public String USER_AGENT = null;

    private MultiThreadedHttpConnectionManager m_cManager;

    /**
     * The proxy configuration for the web client. 
     */
    private static ProxyConfiguration proxy = new ProxyConfiguration();

    public WebClient() {
        configureConnectionManager();
    }

    public WebClient(ProxyConfiguration configuration) {
        proxy = configuration;
        configureConnectionManager();
    }

    private void configureConnectionManager() {
        m_cManager = new MultiThreadedHttpConnectionManager();
        m_cManager.getParams().setDefaultMaxConnectionsPerHost(MAX_CONNECTIONS_PER_HOST);
        m_cManager.getParams().setMaxTotalConnections(MAX_TOTAL_CONNECTIONS);
        m_cManager.getParams().setConnectionTimeout(TIMEOUT_SECONDS * 1000);
        m_cManager.getParams().setSoTimeout(SOCKET_TIMEOUT_SECONDS * 1000);
    }

    public HttpClient getHttpClient(String hostOrUrl) throws IOException {
        return getHttpClient(hostOrUrl, null);
    }

    public HttpClient getHttpClient(String hostOrURL, UsernamePasswordCredentials creds) throws IOException {

        String host = null;

        if (hostOrURL != null) {
            if (hostOrURL.indexOf("/") != -1) {
                URL url = new URL(hostOrURL);
                host = url.getHost();
            } else {
                host = hostOrURL;
            }
        }

        HttpClient client = new HttpClient(m_cManager);
        if (host != null && creds != null) {
            client.getState().setCredentials(new AuthScope(host, AuthScope.ANY_PORT), creds);
            client.getParams().setAuthenticationPreemptive(true);
        }

        if (proxy.isHostProxyable(host)) {
            client.getHostConfiguration().setProxy(proxy.getProxyHost(), proxy.getProxyPort());
            if (proxy.hasValidCredentials()) {
                client.getState().setProxyCredentials(
                        new AuthScope(proxy.getProxyHost(), proxy.getProxyPort(), null),
                        new UsernamePasswordCredentials(proxy.getProxyUser(), proxy.getProxyPassword()));
            }
        }
        return client;
    }

    public HttpInputStream get(String url, boolean failIfNotOK) throws IOException {
        return get(url, failIfNotOK, null);
    }

    public HttpInputStream get(String url, boolean failIfNotOK, String user, String pass) throws IOException {
        UsernamePasswordCredentials creds = null;
        if (user != null && !user.equals("") && pass != null && !pass.equals(""))
            creds = new UsernamePasswordCredentials(user, pass);
        return get(url, failIfNotOK, creds);
    }

    /**
     * Get an HTTP resource with the response as an InputStream, given a URL. If
     * FOLLOW_REDIRECTS is true, up to MAX_REDIRECTS redirects will be followed.
     * Note that if credentials are provided, for security reasons they will
     * only be provided to the FIRST url in a chain of redirects. Note that if
     * the HTTP response has no body, the InputStream will be empty. The success
     * of a request can be checked with getResponseCode(). Usually you'll want
     * to see a 200. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
     * for other codes.
     * 
     * @param url
     *        A URL that we want to do an HTTP GET upon
     * @param failIfNotOK
     *        boolean value indicating if an exception should be thrown if we do
     *        NOT receive an HTTP 200 response (OK)
     * @return HttpInputStream the HTTP response
     * @throws IOException
     */
    public HttpInputStream get(String url, boolean failIfNotOK, UsernamePasswordCredentials creds)
            throws IOException {

        HttpClient client;
        GetMethod getMethod = new GetMethod(url);
        if (USER_AGENT != null) {
            getMethod.setRequestHeader("User-Agent", USER_AGENT);
        }
        if (creds != null && creds.getUserName() != null && creds.getUserName().length() > 0) {
            client = getHttpClient(url, creds);
            getMethod.setDoAuthentication(true);
        } else {
            client = getHttpClient(url);
        }

        HttpInputStream in = new HttpInputStream(client, getMethod, url);
        int status = in.getStatusCode();
        if (failIfNotOK) {
            if (status != 200) {
                //if (followRedirects && in.getStatusCode() == 302){
                if (FOLLOW_REDIRECTS && 300 <= status && status <= 399) {
                    int count = 1;
                    while (300 <= status && status <= 399 && count <= MAX_REDIRECTS) {
                        if (in.getResponseHeader("location") == null) {
                            throw new IOException("Redirect HTTP response provided no location header.");
                        }
                        url = in.getResponseHeader("location").getValue();
                        in.close();
                        getMethod = new GetMethod(url);
                        if (USER_AGENT != null) {
                            getMethod.setRequestHeader("User-Agent", USER_AGENT);
                        }
                        in = new HttpInputStream(client, getMethod, url);
                        status = in.getStatusCode();
                        count++;
                    }
                    if (300 <= status && status <= 399) {
                        in.close();
                        throw new IOException("Too many redirects");
                    } else if (status != 200) {
                        in.close();
                        throw new IOException(
                                "Request failed [" + in.getStatusCode() + " " + in.getStatusText() + "]");
                    }
                    // redirect was successful!
                } else {
                    try {
                        throw new IOException(
                                "Request failed [" + in.getStatusCode() + " " + in.getStatusText() + "]");
                    } finally {
                        try {
                            in.close();
                        } catch (Exception e) {
                            System.err.println("Can't close InputStream: " + e.getMessage());
                        }
                    }
                }
            }
        }
        return in;
    }

    public String getResponseAsString(String url, boolean failIfNotOK) throws IOException {
        return getResponseAsString(url, failIfNotOK, null);
    }

    public String getResponseAsString(String url, boolean failIfNotOK, UsernamePasswordCredentials creds)
            throws IOException {

        InputStream in = get(url, failIfNotOK, creds);

        // Convert the response into a String.
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            StringBuffer buffer = new StringBuffer();
            String line = reader.readLine();
            while (line != null) {
                buffer.append(line + "\n");
                line = reader.readLine();
            }
            return buffer.toString();
        } finally {
            try {
                in.close();
            } catch (Exception e) {
                System.err.println("Can't close InputStream: " + e.getMessage());
            }
        }
    }

}