org.switchyard.component.test.mixins.http.HTTPMixIn.java Source code

Java tutorial

Introduction

Here is the source code for org.switchyard.component.test.mixins.http.HTTPMixIn.java

Source

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the @authors tag. All rights reserved.
 * See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU Lesser General Public License, v. 2.1.
 * This program is distributed in the hope that it will be useful, but WITHOUT A
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License,
 * v.2.1 along with this distribution; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 */

package org.switchyard.component.test.mixins.http;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.FileRequestEntity;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.HeadMethod;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.OptionsMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.log4j.Logger;
import org.junit.Assert;
import org.switchyard.test.SwitchYardTestKit;
import org.switchyard.test.mixins.AbstractTestMixIn;

/**
 * HTTP Test Mix In.
 *
 * @author <a href="mailto:tom.fennelly@gmail.com">tom.fennelly@gmail.com</a>
 */
public class HTTPMixIn extends AbstractTestMixIn {
    private static Logger _logger = Logger.getLogger(HTTPMixIn.class);

    /**
     * Constant representing HTTP DELETE method.
     */
    public static final String HTTP_DELETE = "DELETE";

    /**
     * Constant representing HTTP GET method.
     */
    public static final String HTTP_GET = "GET";

    /**
     * Constant representing HTTP HEAD method.
     */
    public static final String HTTP_HEAD = "HEAD";

    /**
     * Constant representing HTTP POST method.
     */
    public static final String HTTP_POST = "POST";

    /**
     * Constant representing HTTP PUT method.
     */
    public static final String HTTP_PUT = "PUT";

    /**
     * Constant representing HTTP OPTIONS method.
     */
    public static final String HTTP_OPTIONS = "OPTIONS";

    private HttpClient _httpClient;
    private String _contentType = "text/xml;charset=UTF-8";
    private HashMap<String, String> _requestHeaders = new HashMap<String, String>();
    private HashMap<String, String> _expectedHeaders = new HashMap<String, String>();
    private boolean _dumpMessages = false;

    /**
     * Set the content type.
     * <p/>
     * Default content type is "text/xml".
     *
     * @param contentType The content type.
     * @return This HTTPMixIn instance.
     */
    public HTTPMixIn setContentType(String contentType) {
        this._contentType = contentType;
        return this;
    }

    @Override
    public void initialize() {
        _httpClient = new HttpClient();
    }

    /**
     * Send the specified request payload to the specified HTTP endpoint using the method specified.
     * @param endpointURL The HTTP endpoint URL.
     * @param request The request payload.
     * @param method The request method.
     * @return The HTTP response code.
     */
    public int sendStringAndGetStatus(String endpointURL, String request, String method) {
        HttpMethod httpMethod = sendStringAndGetMethod(endpointURL, request, method);
        int status = httpMethod.getStatusCode();
        httpMethod.releaseConnection();
        return status;
    }

    /**
     * Send the specified request payload to the specified HTTP endpoint using the method specified.
     * @param endpointURL The HTTP endpoint URL.
     * @param request The request payload.
     * @param method The request method.
     * @return The HTTP response payload.
     */
    public String sendString(String endpointURL, String request, String method) {
        String response = null;
        try {
            HttpMethod httpMethod = sendStringAndGetMethod(endpointURL, request, method);
            response = httpMethod.getResponseBodyAsString();
            httpMethod.releaseConnection();
        } catch (IOException ioe) {
            _logger.error("Unable to get response", ioe);
        }
        return response;
    }

    /**
     * Send the specified request payload to the specified HTTP endpoint using the method specified.
     * @param endpointURL The HTTP endpoint URL.
     * @param request The request payload.
     * @param method The request method.
     * @return The HttpMethod object.
     */
    public HttpMethod sendStringAndGetMethod(String endpointURL, String request, String method) {
        if (_dumpMessages) {
            _logger.info("Sending a " + method + " request to [" + endpointURL + "]");
            _logger.info("Request body:[" + request + "]");
        }
        HttpMethod httpMethod = null;
        try {
            if (method.equals(HTTP_PUT)) {
                httpMethod = new PutMethod(endpointURL);
                ((PutMethod) httpMethod).setRequestEntity(new StringRequestEntity(request, _contentType, "UTF-8"));
            } else if (method.equals(HTTP_POST)) {
                httpMethod = new PostMethod(endpointURL);
                ((PostMethod) httpMethod).setRequestEntity(new StringRequestEntity(request, _contentType, "UTF-8"));
            } else if (method.equals(HTTP_DELETE)) {
                httpMethod = new DeleteMethod(endpointURL);
            } else if (method.equals(HTTP_OPTIONS)) {
                httpMethod = new OptionsMethod(endpointURL);
            } else if (method.equals(HTTP_HEAD)) {
                httpMethod = new HeadMethod(endpointURL);
            } else {
                httpMethod = new GetMethod(endpointURL);
            }
            execute(httpMethod);
        } catch (UnsupportedEncodingException e) {
            _logger.error("Unable to set request entity", e);
        }
        return httpMethod;
    }

    /**
     * POST the specified request payload to the specified HTTP endpoint.
     * @param endpointURL The HTTP endpoint URL.
     * @param request The request payload.
     * @return The HTTP response payload.
     */
    public String postString(String endpointURL, String request) {
        if (_dumpMessages) {
            _logger.info("Sending a POST request to [" + endpointURL + "]");
            _logger.info("Request body:[" + request + "]");
        }

        PostMethod postMethod = new PostMethod(endpointURL);
        try {
            postMethod.setRequestEntity(new StringRequestEntity(request, _contentType, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            _logger.error("Unable to set request entity", e);
        }
        try {
            return execute(postMethod);
        } finally {
            postMethod.releaseConnection();
        }
    }

    /**
     * POST the specified request payload to the specified HTTP endpoint.
     * @param endpointURL The HTTP endpoint URL.
     * @param request The file resource containing the request payload.
     * @return The HTTP response payload.
     */
    public String postFile(String endpointURL, String request) {

        FileRequestEntity requestEntity = new FileRequestEntity(new File(request), "text/xml; charset=utf-8");

        if (_dumpMessages) {
            _logger.info("Sending a POST request to [" + endpointURL + "]");
            ByteArrayOutputStream target = new ByteArrayOutputStream();
            try {
                requestEntity.writeRequest(target);
                _logger.info("Request body:[" + target.toString() + "]");
            } catch (IOException e) {
                _logger.error("Unable to write FileRequestEntity to stream", e);
            }
        }

        PostMethod postMethod = new PostMethod(endpointURL);
        postMethod.setRequestEntity(requestEntity);
        try {
            return execute(postMethod);
        } finally {
            postMethod.releaseConnection();
        }
    }

    /**
     * POST the specified String request to the specified HTTP endpoint and perform an XML compare
     * between the HTTP response and the specified expected response String.
     * @param endpointURL The HTTP endpoint URL.
     * @param request The classpath resource to be posted to the endpoint.
     * @param expectedResponse The String to use to perform the XML test on the response.
     * @return The HTTP response payload.
     */
    public String postStringAndTestXML(String endpointURL, String request, String expectedResponse) {
        String response = postString(endpointURL, request);
        SwitchYardTestKit.compareXMLToString(response, expectedResponse);
        return response;
    }

    /**
     * POST the specified classpath resource to the specified HTTP endpoint.
     * @param endpointURL The HTTP endpoint URL.
     * @param requestResource The classpath resource to be posted to the endpoint.
     * @return The HTTP method.
     */
    public HttpMethod postResourceAndGetMethod(String endpointURL, String requestResource) {
        if (_dumpMessages) {
            _logger.info("Sending a POST request to [" + endpointURL + "]");
            InputStream input = getTestKit().getResourceAsStream(requestResource);
            ByteArrayOutputStream tmp = new ByteArrayOutputStream();
            byte[] data = new byte[4096];
            int l = 0;
            try {
                while ((l = input.read(data)) >= 0) {
                    tmp.write(data, 0, l);
                }
                _logger.info("Request body:[" + new String(tmp.toByteArray()) + "]");
            } catch (IOException e) {
                _logger.error("Unexpected Exception while reading request resource", e);
            }
        }

        PostMethod postMethod = new PostMethod(endpointURL);
        InputStream requestStream = getTestKit().getResourceAsStream(requestResource);

        try {
            postMethod.setRequestEntity(
                    new InputStreamRequestEntity(requestStream, _contentType + "; charset=utf-8"));
            execute(postMethod);
        } finally {
            try {
                requestStream.close();
            } catch (IOException e) {
                Assert.fail("Unexpected exception closing HTTP request resource stream.");
            }
        }
        return postMethod;
    }

    /**
     * POST the specified classpath resource to the specified HTTP endpoint.
     * @param endpointURL The HTTP endpoint URL.
     * @param requestResource The classpath resource to be posted to the endpoint.
     * @return The HTTP response payload.
     */
    public String postResource(String endpointURL, String requestResource) {
        String response = null;
        try {
            HttpMethod httpMethod = postResourceAndGetMethod(endpointURL, requestResource);
            response = httpMethod.getResponseBodyAsString();
            httpMethod.releaseConnection();
        } catch (IOException ioe) {
            _logger.error("Unable to get response", ioe);
        }
        return response;
    }

    /**
     * POST the specified classpath resource to the specified HTTP endpoint and perform an XML compare
     * between the HTTP response and the specified expected classpath response resource.
     * @param endpointURL The HTTP endpoint URL.
     * @param requestResource The classpath resource to be posted to the endpoint.
     * @param expectedResponseResource The classpath resource to use to perform the XML test on the response.
     * @return The HTTP response payload.
     */
    public String postResourceAndTestXML(String endpointURL, String requestResource,
            String expectedResponseResource) {
        String response = postResource(endpointURL, requestResource);
        getTestKit().compareXMLToResource(response, expectedResponseResource);
        return response;
    }

    /**
     * POST the specified classpath resource to the specified HTTP endpoint.
     * @param endpointURL The HTTP endpoint URL.
     * @param requestResource The classpath resource to be posted to the endpoint.
     * @return The HTTP status code.
     */
    public int postResourceAndGetStatus(String endpointURL, String requestResource) {
        HttpMethod httpMethod = postResourceAndGetMethod(endpointURL, requestResource);
        int status = httpMethod.getStatusCode();
        httpMethod.releaseConnection();
        return status;
    }

    /**
     * Execute the supplied HTTP Method.
     * <p/>
     * Does not release the {@link org.apache.commons.httpclient.HttpMethod#releaseConnection() HttpMethod connection}.
     *
     * @param method The HTTP Method.
     * @return The HTTP Response.
     */
    public String execute(HttpMethod method) {
        if (_httpClient == null) {
            Assert.fail(
                    "HTTPMixIn not initialized.  You must call the initialize() method before using this MixIn");
        }

        for (String key : _requestHeaders.keySet()) {
            method.setRequestHeader(key, _requestHeaders.get(key));
        }

        if (_dumpMessages) {
            for (Header header : method.getRequestHeaders()) {
                _logger.info("Request header:[" + header.getName() + "=" + header.getValue() + "]");
            }
        }

        String response = null;
        try {
            _httpClient.executeMethod(method);
            response = method.getResponseBodyAsString();
        } catch (Exception e) {
            try {
                Assert.fail("Exception invoking HTTP endpoint '" + method.getURI() + "': " + e.getMessage());
            } catch (URIException e1) {
                _logger.error("Unexpected error", e1);
                return null;
            }
        }

        if (_dumpMessages) {
            for (Header header : method.getResponseHeaders()) {
                _logger.info("Received response header:[" + header.getName() + "=" + header.getValue() + "]");
            }
            _logger.info("Received response body:[" + response + "]");
        }

        for (String key : _expectedHeaders.keySet()) {
            Header actual = method.getResponseHeader(key);
            Assert.assertNotNull("Checking response header:[" + key + "]", actual);
            Assert.assertEquals("Checking response header:[" + key + "]", _expectedHeaders.get(key),
                    actual.getValue());
        }

        return response;
    }

    /**
     * Set a request header.
     * @param name header name
     * @param value header value
     * @return this instance
     */
    public HTTPMixIn setRequestHeader(String name, String value) {
        _requestHeaders.put(name, value);
        return this;
    }

    /**
     * Set the list of request headers.
     * @param headers request headers in HashMap
     * @return this instance
     */
    public HTTPMixIn setRequestHeaders(Map<String, String> headers) {
        _requestHeaders.clear();
        _requestHeaders.putAll(headers);
        return this;
    }

    /**
     * Set a expected response header.
     * @param name header name
     * @param value header value
     * @return this instance
     */
    public HTTPMixIn setExpectedHeader(String name, String value) {
        _expectedHeaders.put(name, value);
        return this;
    }

    /**
     * Set the list of expected response headers.
     * @param headers expected response headers in HashMap
     * @return this instance
     */
    public HTTPMixIn setExpectedHeaders(Map<String, String> headers) {
        _expectedHeaders.clear();
        _expectedHeaders.putAll(headers);
        return this;
    }

    /**
     * Whether to dump the request/response message into log or not.
     * @param dumpMessages Whether to dump the request/response message into log or not
     * @return this instance
     */
    public HTTPMixIn setDumpMessages(boolean dumpMessages) {
        _dumpMessages = dumpMessages;
        return this;
    }

    @Override
    public void uninitialize() {
        if (_httpClient != null) {
            final HttpConnectionManager connectionManager = _httpClient.getHttpConnectionManager();
            if (connectionManager instanceof MultiThreadedHttpConnectionManager) {
                final MultiThreadedHttpConnectionManager multiThreadedHttpConnectionManager = (MultiThreadedHttpConnectionManager) connectionManager;
                multiThreadedHttpConnectionManager.shutdown();
            }
            connectionManager.closeIdleConnections(0);
        }
    }
}