All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.cybersource.ws.client.HttpClientConnection Maven / Gradle / Ivy

The newest version!
/*
* Copyright 2003-2014 CyberSource Corporation
*
* THE SOFTWARE AND THE DOCUMENTATION ARE PROVIDED ON AN "AS IS" AND "AS
* AVAILABLE" BASIS WITH NO WARRANTY.  YOU AGREE THAT YOUR USE OF THE SOFTWARE AND THE
* DOCUMENTATION IS AT YOUR SOLE RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR
* COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE. TO THE FULLEST
* EXTENT PERMISSIBLE UNDER APPLICABLE LAW, CYBERSOURCE AND ITS AFFILIATES EXPRESSLY DISCLAIM ALL
* WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, WITH RESPECT TO THE SOFTWARE AND THE
* DOCUMENTATION, INCLUDING ALL WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
* SATISFACTORY QUALITY, ACCURACY, TITLE AND NON-INFRINGEMENT, AND ANY WARRANTIES THAT MAY ARISE
* OUT OF COURSE OF PERFORMANCE, COURSE OF DEALING OR USAGE OF TRADE.  NEITHER CYBERSOURCE NOR
* ITS AFFILIATES WARRANT THAT THE FUNCTIONS OR INFORMATION CONTAINED IN THE SOFTWARE OR THE
* DOCUMENTATION WILL MEET ANY REQUIREMENTS OR NEEDS YOU MAY HAVE, OR THAT THE SOFTWARE OR
* DOCUMENTATION WILL OPERATE ERROR FREE, OR THAT THE SOFTWARE OR DOCUMENTATION IS COMPATIBLE
* WITH ANY PARTICULAR OPERATING SYSTEM.
*/

package com.cybersource.ws.client;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.*;
import org.apache.http.protocol.HttpContext;
import org.w3c.dom.Document;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;

import static com.cybersource.ws.client.Utility.*;

/**
 * Helps in posting the Request document for the Transaction using HttpClient.
 * Converts the document to String format and also helps in setting up the Proxy connections.
 *
 */
public class HttpClientConnection extends Connection {
    private HttpPost httpPost = null;
    private HttpClientContext httpContext = null;
    private CloseableHttpClient httpClient = null;
    private CloseableHttpResponse httpResponse = null;

    /**
     * @param mc
     * @param builder
     * @param logger
     */
    HttpClientConnection(
            MerchantConfig mc, DocumentBuilder builder, LoggerWrapper logger) {
        super(mc, builder, logger);
        initHttpClient(mc);
        logger.log(Logger.LT_INFO, "Using HttpClient for connections.");
    }

    /**
     * Post request by httpclient connection
     * @param request
     * @param startTime
     * @throws IOException
     * @throws TransformerException
     */
    /* (non-Javadoc)
     * @see com.cybersource.ws.client.Connection#postDocument(org.w3c.dom.Document)
     */
    void postDocument(Document request, long startTime)
            throws IOException, TransformerException {

        String serverURL = mc.getEffectiveServerURL();
        httpPost = new HttpPost(serverURL);
        String requestString = documentToString(request);
        StringEntity stringEntity = new StringEntity(requestString, "UTF-8");
        httpPost.setEntity(stringEntity);
        httpPost.setHeader(Utility.SDK_ELAPSED_TIMESTAMP, String.valueOf(System.currentTimeMillis() - startTime));
        httpPost.setHeader(Utility.ORIGIN_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
        logRequestHeaders();
        httpContext = HttpClientContext.create();
        logger.log(Logger.LT_INFO,
                "Sending " + requestString.length() + " bytes to " + serverURL);
        httpResponse = httpClient.execute(httpPost, httpContext);
    }

    /**
     * To check is request sent or not
     * @return boolean
     */
    /* (non-Javadoc)
     * @see com.cybersource.ws.client.Connection#isRequestSent()
     */
    public boolean isRequestSent() {
        return httpContext != null && httpContext.isRequestSent();
    }
    /**
     * To release the http connections
     */
    /* (non-Javadoc)
     * @see com.cybersource.ws.client.Connection#release()
     */
    public void release() {
        if (httpPost != null) {
            httpPost.releaseConnection();
            httpPost = null;
        }
    }

    /**
     * To get http response code
     * @return int
     */
    /* (non-Javadoc)
     * @see com.cybersource.ws.client.Connection#getHttpResponseCode()
     */
    int getHttpResponseCode() {
        return httpResponse != null ? httpResponse.getStatusLine().getStatusCode() : -1;
    }

    /**
     * To get response stream
     * @return InputStream
     * @throws IOException
     */
    /* (non-Javadoc)
     * @see com.cybersource.ws.client.Connection#getResponseStream()
     */
    InputStream getResponseStream()
            throws IOException {
        return httpResponse != null ? httpResponse.getEntity().getContent() : null;
    }

    /**
     * To get response error stream
     * @return InputStream
     * @throws IOException
     */
    /* (non-Javadoc)
     * @see com.cybersource.ws.client.Connection#getResponseErrorStream()
     */
    InputStream getResponseErrorStream()
            throws IOException {
        return getResponseStream();
    }



    /**
     * To initialize HttpClient and set proxy
     * @param mc
     */
    protected void initHttpClient(MerchantConfig mc) {
        RequestConfig.Builder requestConfigBuilder = RequestConfig.custom()
                .setSocketTimeout(mc.getSocketTimeoutMs())
                .setConnectTimeout(mc.getConnectionTimeoutMs());

        HttpClientBuilder httpClientBuilder = HttpClients.custom();

        if(mc.isAllowRetry()){
            httpClientBuilder.setRetryHandler(new MyRetryHandler());
        }

        ConnectionHelper.setProxy(httpClientBuilder, requestConfigBuilder, mc);

        httpClient = httpClientBuilder
                .setDefaultRequestConfig(requestConfigBuilder.build())
                .build();
    }

    /**
     * Converts Document to String using java.xml package library.
     * @param doc - Document object
     * @return - String object
     * @throws TransformerConfigurationException
     * @throws TransformerException
     * @throws IOException
     */
    private static String documentToString(Document doc)
            throws TransformerConfigurationException, TransformerException,
            IOException {
        ByteArrayOutputStream baos = null;
        try {
            baos = makeStream(doc);
            return baos.toString("utf-8");
        } finally {
            if (baos != null) {
                baos.close();
            }
        }
    }

    /**
     *  We had to override the default retryMethod as it also
     *  retries if there is no response from the server.
     *  We don't want to take any chances.
     *
     */
    private class MyRetryHandler implements HttpRequestRetryHandler {

        long retryWaitInterval=mc.getRetryInterval();
        int maxRetries= mc.getNumberOfRetries();

        // I copied this code from
        // http://jakarta.apache.org/commons/httpclient/exception-handling.html#HTTP%20transport%20safety
        // and changed the NoHttpResponseException case to
        // return false.
        @Override
        public boolean retryRequest(IOException exception, int executionCount, HttpContext httpContext) {
            if (executionCount > maxRetries) {
                // Do not retry if over max retry count
                return false;
            }if (exception instanceof org.apache.http.NoHttpResponseException) {
                // Retry if the server dropped connection on us
                // return true; <-- this was the original behavior.
                return false;
            }
            HttpClientContext httpClientContext = HttpClientContext.adapt(httpContext);
            if (!httpClientContext.isRequestSent()) {
                // Retry if the request has not been sent fully or
                // if it's OK to retry methods that have been sent
                try {
                    Thread.sleep(retryWaitInterval);
                    logger.log( Logger.LT_INFO, " Retrying Request -- "+logger.getUniqueKey()+ " Retry Count -- "+executionCount);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return true;
            }
            // otherwise do not retry
            return false;
        }
    }

    @Override
    public void logRequestHeaders() {
        if(mc.getEnableLog() && httpPost != null) {
            List
reqheaders = Arrays.asList(httpPost.getAllHeaders()); logger.log(Logger.LT_INFO, "Request Headers: " + reqheaders); } } @Override public void logResponseHeaders() { if(mc.getEnableLog() && httpResponse != null) { Header responseTimeHeader = httpResponse.getFirstHeader(RESPONSE_TIME_REPLY); if (responseTimeHeader != null && StringUtils.isNotBlank(responseTimeHeader.getValue())) { long resIAT = getResponseIssuedAtTime(responseTimeHeader.getValue()); if (resIAT > 0) { logger.log(Logger.LT_INFO, "responseTransitTimeSec : " + getResponseTransitTime(resIAT)); } } List
respheaders = Arrays.asList(httpResponse.getAllHeaders()); logger.log(Logger.LT_INFO, "Response Headers" + respheaders); } } } /* Copyright 2006 CyberSource Corporation */




© 2015 - 2024 Weber Informatics LLC | Privacy Policy