com.exalead.io.failover.FailoverHttpClient.java Source code

Java tutorial

Introduction

Here is the source code for com.exalead.io.failover.FailoverHttpClient.java

Source

/* Copyright 2010 Exalead S.A.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
 * implied. See the License for the specific language governing
 * permissions and limitations under the License. 
 */

package com.exalead.io.failover;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.log4j.Logger;

public class FailoverHttpClient {
    protected MonitoredHttpConnectionManager manager;
    protected HttpClient client;
    protected List<PoolMonitoringThread> threads = new ArrayList<PoolMonitoringThread>();

    public FailoverHttpClient() {
        manager = new MonitoredHttpConnectionManager();
        client = new HttpClient(manager);

        client.setParams(new HttpClientParams());
        manager.getParams().setStaleCheckingEnabled(false);
    }

    public void setCredentials(String login, String password) {
        manager.setCredentials(new UsernamePasswordCredentials(login, password));
    }

    /** 
     * Maximum number of tries to acquire a connection if all
     * hosts are down
     */
    public void setConnectionAcquireFailMaxTries(int tries) {
        manager.failMaxTries = tries;
    }

    /** 
     * Maximum time to acquire a connection if all hosts are down
     */
    public void setConnectionAcquireFailTimeout(long timeout) {
        manager.failTimeout = timeout;
    }

    /** 
     * Set the path on which the "isAlive" service is mounted.
     * isAlive must reply < 400 if host is alive, > 500 if host is down
     */
    public void setIsAlivePath(String isAlivePath) {
        manager.isAlivePath = isAlivePath;
    }

    /**
     * Set the timeout for establishing connection
     * @param timeout timeout in milliseconds
     */
    public void setConnectTimeout(int timeout) {
        manager.connectionTimeout = timeout;
    }

    /**
     * Set the timeout for the isAlive service to answer
     * @param timeout timeout in milliseconds
     */
    public void setIsAliveTimeout(int timeout) {
        manager.isAliveTimeout = timeout;
    }

    public MonitoredHttpConnectionManager getConnectionManager() {
        return manager;
    }

    //    /** Maximum time to wait for a connection to become available
    //     * (if all hosts are not down and max number of connections
    //     * is exceeded)
    //     */
    //    public void setConnectionAcquireTimeout(long timeout) {
    //        client.getParams().setConnectionManagerTimeout(timeout);
    //    }

    public void startMonitoring(int nthreads) {
        int delay = 1000 / manager.hosts.size() * nthreads;
        for (int i = 0; i < nthreads; i++) {
            PoolMonitoringThread pmt = new PoolMonitoringThread();
            pmt.loopDelay = delay;
            pmt.pool = manager;
            pmt.start();
            threads.add(pmt);
        }
    }

    public void shutdown() {
        for (PoolMonitoringThread pmt : threads) {
            try {
                pmt.join();
            } catch (InterruptedException e) {
            }
        }
        manager.shutdown();
    }

    public void addHost(URI uri, int power) {
        manager.addHost(uri, power);
    }

    public void addHost(String host, int port, int power) {
        manager.addHost(host, port, power);
    }

    public int executeMethod(HttpMethod method) throws HttpException, IOException {
        return executeMethod(method, 0, 1);
    }

    public int executeMethod(HttpMethod method, int timeout) throws HttpException, IOException {
        return executeMethod(method, timeout, 1);
    }

    public int executeMethod(HttpMethod method, int timeout, int retries) throws HttpException, IOException {
        if (manager.hosts.size() == 0) {
            logger.error("Could not execute method without any host.");
            throw new HttpException("Trying to execute methods without host");
        }
        // Fake config, the underlying manager manages all
        HostConfiguration config = new HostConfiguration();

        /* Set method parameters */
        method.getParams().setSoTimeout(timeout);
        /* DO NOT retry magically the method */
        method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                new DefaultHttpMethodRetryHandler(0, false));

        if (manager.getCredentials() != null) {
            client.getParams().setAuthenticationPreemptive(true);
            client.getState().setCredentials(new AuthScope(AuthScope.ANY), manager.getCredentials());
        }

        IOException fail = null;
        for (int i = 1; i <= retries; ++i) {
            try {
                return client.executeMethod(config, method);
            } catch (IOException e) {
                logger.warn("Failed to execute method - try " + i + "/" + retries);
                fail = e;
                continue;
            }
        }
        logger.warn("exception in executeMethod: " + fail.getMessage());
        throw fail;
    }

    private static Logger logger = Logger.getLogger("httpclient.failover");
}