com.legstar.test.cixs.AbstractHttpClientTester.java Source code

Java tutorial

Introduction

Here is the source code for com.legstar.test.cixs.AbstractHttpClientTester.java

Source

/*******************************************************************************
 * Copyright (c) 2010 LegSem.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     LegSem - initial API and implementation
 ******************************************************************************/
package com.legstar.test.cixs;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Properties;

import junit.framework.TestCase;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.io.FileUtils;
import org.codehaus.cargo.container.InstalledLocalContainer;
import org.codehaus.cargo.container.deployable.WAR;
import org.codehaus.cargo.container.tomcat.Tomcat6xInstalledLocalContainer;
import org.codehaus.cargo.container.tomcat.Tomcat6xStandaloneLocalConfiguration;

/**
 * Tests a using a raw HTTP Client to call a Web Service (either proxy or
 * Adapter).
 * 
 */
public abstract class AbstractHttpClientTester extends TestCase {

    /** A multi-thread client used throughout the test. */
    private static final HttpClient HTTPCLIENT = createHttpClient();

    /** Maximum number of connections allowed overall. */
    public static final int MAX_TOTAL_CONNECTIONS = 25;

    /** Default maximum number of connections allowed for a given host config. */
    public static final int DEFAULT_MAX_CONNECTIONS_PER_HOST = 5;

    /**
     * Timeout until a connection is established. A value of zero means the
     * timeout is not used. The default value is zero.
     */
    public static final int CONNECT_TIMEOUT = 5000;

    /**
     * Socket timeout (<tt>SO_TIMEOUT</tt>) in milliseconds which is the timeout
     * for waiting for data.
     */
    public static final int SOCKET_TIMEOUT = 5000;

    /** Disable Nagle's algorithm (that is enable TCP_NODELAY). */
    public static final boolean TCP_NO_DELAY = true;

    /** Close connections which are idle for longer than this. */
    public static final int IDLE_CONNECTION_TIMEOUT = 1000;

    /** A Tomcat instance. */
    private InstalledLocalContainer _webapp;

    /**
     * Setup Tomcat.
     */
    public AbstractHttpClientTester() {
    }

    /**
     * Start a Tomcat instance.
     * */
    public void setUp() throws Exception {
        _webapp = getContainer();
        _webapp.start();
    }

    /**
     * Stop the Tomcat instance.
     * */
    public void tearDown() throws Exception {
        _webapp.stop();
    }

    /**
     * Setup the static http connection pool.
     * 
     * @return an http client instance
     */
    protected static HttpClient createHttpClient() {

        HttpConnectionManagerParams connectionManagerParams = new HttpConnectionManagerParams();

        connectionManagerParams.setMaxTotalConnections(MAX_TOTAL_CONNECTIONS);
        connectionManagerParams.setDefaultMaxConnectionsPerHost(DEFAULT_MAX_CONNECTIONS_PER_HOST);
        connectionManagerParams.setTcpNoDelay(TCP_NO_DELAY);
        connectionManagerParams.setSoTimeout(SOCKET_TIMEOUT);
        connectionManagerParams.setConnectionTimeout(CONNECT_TIMEOUT);

        HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
        connectionManager.setParams(connectionManagerParams);
        connectionManager.closeIdleConnections(IDLE_CONNECTION_TIMEOUT);
        return new HttpClient(connectionManager);
    }

    /**
     * Perform a request/reply using text/xml as payload.
     * 
     * @param url the target url
     * @param xmlRequest the XML request
     * @param soapAction the soap action
     * @return the XML reply
     * @throws Exception if something goes wrong
     */
    public String postXml(final String url, final String xmlRequest, final String soapAction) throws Exception {
        PostMethod postMethod = new PostMethod(url);
        if (soapAction != null && soapAction.length() > 0) {
            postMethod.setRequestHeader("SOAPAction", soapAction);
        }
        StringRequestEntity requestEntity = new StringRequestEntity(xmlRequest, "text/xml", "utf-8");
        postMethod.setRequestEntity(requestEntity);
        int rc = HTTPCLIENT.executeMethod(postMethod);
        String xmlReply = getResponseBodyAsString(postMethod.getResponseBodyAsStream(),
                postMethod.getResponseCharSet());
        postMethod.releaseConnection();
        assertEquals(postMethod.getStatusText() + " " + xmlReply, 200, rc);
        return xmlReply;
    }

    /**
     * Perform a request/reply using byte[] application/octet-stream as payload.
     * 
     * @param url the target url
     * @param bytesRequest the bytes request
     * @return the bytes reply
     * @throws Exception if something goes wrong
     */
    public byte[] postBytes(final String url, final byte[] bytesRequest) throws Exception {
        PostMethod postMethod = new PostMethod(url);
        ByteArrayRequestEntity requestEntity = new ByteArrayRequestEntity(bytesRequest, "application/octet-stream");
        postMethod.setRequestEntity(requestEntity);
        int rc = HTTPCLIENT.executeMethod(postMethod);
        assertEquals(postMethod.getStatusText(), 200, rc);
        byte[] bytesReply = postMethod.getResponseBody();
        postMethod.releaseConnection();
        return bytesReply;
    }

    /**
     * @return the J2EE server host.
     */
    public String getJ2EEHost() {
        return findJ2EEHost();
    }

    /**
     * 
     * @return the J2EE server host name. This can come from a properties file
     *         or will default to the local machine ip address.
     */
    protected static String findJ2EEHost() {
        String defaultJ2EEHost = getLocalIPAddress();
        InputStream stream = AbstractHttpClientTester.class.getResourceAsStream("/devenv.properties");
        if (stream != null) {
            Properties props = new Properties();
            try {
                props.load(stream);
                return props.getProperty("legstar-dev-tomcat-host", defaultJ2EEHost);
            } catch (IOException e) {
                return defaultJ2EEHost;
            }
        } else {
            return defaultJ2EEHost;
        }

    }

    /**
     * Assuming the local machine is running JBoss ESB.
     * 
     * @return the local machine IP address
     */
    protected static String getLocalIPAddress() {
        try {
            InetAddress addr = InetAddress.getLocalHost();
            byte[] ipAddr = addr.getAddress();
            String ipAddrStr = "";
            for (int i = 0; i < ipAddr.length; i++) {
                if (i > 0) {
                    ipAddrStr += ".";
                }
                ipAddrStr += ipAddr[i] & 0xFF;
            }
            return ipAddrStr;
        } catch (UnknownHostException e) {
            return "";
        }

    }

    /**
     * The HttpClient getResponseBodyAsString returns a systematic warning when
     * the response has no content-length.
     * 
     * @param is the http response as a stream
     * @param charset the response character set
     * @return the result string
     */
    protected String getResponseBodyAsString(final InputStream is, final String charset) {
        try {
            Reader reader = new BufferedReader(new InputStreamReader(is, charset));
            StringBuilder sb = new StringBuilder();
            int ch;
            while ((ch = reader.read()) > -1) {
                sb.append((char) ch);
            }
            is.close();
            return sb.toString();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Start the web container call the web service, check then stop the web
     * container.
     */
    public void performRoundTrip() {
        try {
            callServiceAndCheck();
        } catch (Exception e) {
            e.printStackTrace();
            fail(e.toString());
        }
    }

    /**
     * Call the Web service and check results.
     */
    public abstract void callServiceAndCheck() throws Exception;

    /**
     * Create a Cargo web container deploying a war in it. All dependencies go
     * to shared library.
     * 
     * @return a container ready to start
     */
    @SuppressWarnings("unchecked")
    public InstalledLocalContainer getContainer() {
        Tomcat6xStandaloneLocalConfiguration configuration = new Tomcat6xStandaloneLocalConfiguration(
                "target/tomcat6x");
        configuration.addDeployable(new WAR("target/war/legstar-engine.war"));
        for (String deployable : getDeployables()) {
            configuration.addDeployable(new WAR(deployable));
        }
        Tomcat6xInstalledLocalContainer webapp = new Tomcat6xInstalledLocalContainer(configuration);
        Collection<File> jarFiles = FileUtils.listFiles(new File("target/dependency/lib"), new String[] { "jar" },
                false);
        for (File jarFile : jarFiles) {
            webapp.addSharedClasspath(jarFile.getAbsolutePath());
        }
        webapp.addSharedClasspath(new File("src/test/resources").getAbsolutePath());
        webapp.setHome(System.getenv("CATALINA_HOME"));
        webapp.setOutput("target/cargo" + getClass().getSimpleName() + getName() + ".log");
        return webapp;
    }

    /**
     * Get the war archives that needs to be deployed for an integration test.
     * Order is important to avoid class loading issues.
     * 
     * @return
     */
    public abstract String[] getDeployables();
}