Package com.betfair.cougar.client

Source Code of com.betfair.cougar.client.HttpClientExecutable

/*
* Copyright 2013, The Sporting Exchange Limited
*
* 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.betfair.cougar.client;

import com.betfair.cougar.client.api.GeoLocationSerializer;
import com.betfair.cougar.core.api.client.TransportMetrics;
import com.betfair.cougar.core.api.ev.ExecutionObserver;
import com.betfair.cougar.core.api.ev.OperationDefinition;
import com.betfair.cougar.transport.api.protocol.http.HttpServiceBindingDescriptor;
import com.betfair.cougar.util.KeyStoreManagement;
import com.betfair.cougar.util.jmx.JMXControl;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.UserTokenHandler;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.jmx.export.annotation.ManagedResource;

import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;

/**
* Implementation of client executable using synchronous implementation of HTTP ReScript protocol.
*/
@ManagedResource
public class HttpClientExecutable extends AbstractHttpExecutable<HttpUriRequest> implements BeanNameAware {
    private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientExecutable.class);

    private HttpClient client;
    private HttpRequestRetryHandler retryHandler;
    private CougarClientConnManager clientConnectionManager;
    private String beanName;
    private JMXControl jmxControl;
    private UserTokenHandler userTokenHandler;

    private HttpClientTransportMetrics metrics;


    public HttpClientExecutable(final HttpServiceBindingDescriptor bindingDescriptor, GeoLocationSerializer serializer) {
        this(bindingDescriptor, serializer, DEFAULT_REQUEST_UUID_HEADER);
    }

    public HttpClientExecutable(final HttpServiceBindingDescriptor bindingDescriptor,
                                final GeoLocationSerializer serializer,
                                final String requestUUIDHeader) {
        this(bindingDescriptor, serializer, requestUUIDHeader, new CougarClientConnManager());
    }


    public HttpClientExecutable(final HttpServiceBindingDescriptor bindingDescriptor, GeoLocationSerializer serializer,
                                String requestUUIDHeader, CougarClientConnManager clientConnectionManager) {
        super(bindingDescriptor, new HttpClientCougarRequestFactory(serializer, requestUUIDHeader));
        this.clientConnectionManager = clientConnectionManager;
    }

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }

    public void init() throws Exception {
        super.init();

        // create client if not been set externally (e.g for testing)
        if (client == null) {
            client = new DefaultHttpClient(clientConnectionManager);
            ((DefaultHttpClient)client).setUserTokenHandler(userTokenHandler);
        }

        // configure retryhandler if set
        if (retryHandler != null) {
            ((AbstractHttpClient) client).setHttpRequestRetryHandler(retryHandler);
        }

        // configure timeout if set
        if (connectTimeout != -1) {
            HttpParams params = client.getParams();
            HttpConnectionParams.setConnectionTimeout(params, connectTimeout);
            HttpConnectionParams.setSoTimeout(params, connectTimeout);
        }

        //Configure SSL - if relevant
        if (transportSSLEnabled) {
            KeyStoreManagement keyStore = KeyStoreManagement.getKeyStoreManagement(httpsKeystoreType, httpsKeystore, httpsKeyPassword);
            if (jmxControl != null && keyStore != null) {
                jmxControl.registerMBean("CoUGAR:name=HttpClientKeyStore,beanName="+beanName, keyStore);
            }
            KeyStoreManagement trustStore = KeyStoreManagement.getKeyStoreManagement(httpsTruststoreType, httpsTruststore, httpsTrustPassword);
            if (jmxControl != null) {
                jmxControl.registerMBean("CoUGAR:name=HttpClientTrustStore,beanName="+beanName, trustStore);
            }
            SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore != null ? keyStore.getKeyStore() : null, keyStore != null ? httpsKeyPassword : null, trustStore.getKeyStore());
            if (hostnameVerificationDisabled) {
                socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
                LOGGER.warn("CRITICAL SECURITY CHECKS ARE DISABLED: server SSL certificate hostname " +
                        "verification is turned off.");
            }
            Scheme sch = new Scheme("https", extractPortFromAddress(), socketFactory);
            client.getConnectionManager().getSchemeRegistry().register(sch);
        }

        metrics = new HttpClientTransportMetrics();

        if (jmxControl != null) {
            jmxControl.registerMBean("CoUGAR:name=HttpClientExecutable,beanName="+beanName, this);
        }
    }


    @Override
    protected void sendRequest(HttpUriRequest httpMethod, ExecutionObserver obs,
                               OperationDefinition operationDefinition) {
        try {
            final HttpResponse response = client.execute(httpMethod);
            if (LOGGER.isDebugEnabled()) {
                final int statusCode = response.getStatusLine().getStatusCode();
                LOGGER.debug("Received http response code of " + statusCode +
                        " in reply to request to " + httpMethod.getURI());
            }
            processResponse(new CougarHttpResponse(response), obs, operationDefinition);
        } catch (Exception e) {
            processException(obs, e, httpMethod.getURI().toString());
        }


    }

    public void setRetryHandler(final HttpRequestRetryHandler retryHandler) {
        this.retryHandler = retryHandler;
    }

    public void setClient(final HttpClient client) {
        this.client = client;
    }

    public void setJmxControl(JMXControl jmxControl) {
        this.jmxControl = jmxControl;
    }

    public void setUserTokenHandler(UserTokenHandler userTokenHandler) {
        this.userTokenHandler = userTokenHandler;
    }

    private static final class CougarHttpResponse implements AbstractHttpExecutable.CougarHttpResponse {
        private final HttpResponse delegate;

        private CougarHttpResponse(HttpResponse delegate) {
            this.delegate = delegate;
        }

        @Override
        public InputStream getEntity() throws IOException {
            return delegate.getEntity() == null ? null : delegate.getEntity().getContent();
        }

        @Override
        public List<String> getContentEncoding() {
            List<String> codecList = new LinkedList<String>();
            Header ceheader = delegate.getEntity().getContentEncoding();
            if (ceheader != null) {
                HeaderElement[] codecs = ceheader.getElements();
                for (HeaderElement codec : codecs) {
                    codecList.add(codec.getName().toLowerCase(Locale.US));
                }
            }
            return codecList;
        }

        @Override
        public int getResponseStatus() {
            return delegate.getStatusLine().getStatusCode();
        }

        @Override
        public String getServerIdentity() {
            if (delegate.containsHeader("Server")) {
                return "" + delegate.getFirstHeader("Server").getValue();
            }
            return null;
        }

        @Override
        public long getResponseSize() {
            if (delegate.getEntity() != null) {
                return delegate.getEntity().getContentLength();
            }
            return 0;
        }
    }

    @Override
    public TransportMetrics getTransportMetrics() {
        return metrics;
    }

    public void setMaxTotalConnections(int maxTotalConnections) {
        clientConnectionManager.setMaxTotal(maxTotalConnections);
    }

    public void setMaxPerRouteConnections(int maxPerRouteConnections) {
        clientConnectionManager.setDefaultMaxPerRoute(maxPerRouteConnections);
    }


    final class HttpClientTransportMetrics implements TransportMetrics {

        @Override
        public int getOpenConnections() {
            return clientConnectionManager.getConnectionsInPool();
        }

        @Override
        public int getMaximumConnections() {
            return clientConnectionManager.getDefaultMaxPerRoute();
        }

        @Override
        public int getFreeConnections() {
            return clientConnectionManager.getFreeConnections();
        }

        @Override
        public int getCurrentLoad() {
            return (getOpenConnections() - getFreeConnections()) * 100 / getMaximumConnections();
        }
    }

}
TOP

Related Classes of com.betfair.cougar.client.HttpClientExecutable

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.