com.comcast.cns.io.HTTPEndpointSyncPublisher.java Source code

Java tutorial

Introduction

Here is the source code for com.comcast.cns.io.HTTPEndpointSyncPublisher.java

Source

/**
 * Copyright 2012 Comcast Corporation
 * 
 * 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.comcast.cns.io;

import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import com.comcast.cmb.common.util.CMBErrorCodes;
import com.comcast.cmb.common.util.CMBException;
import com.comcast.cmb.common.util.CMBProperties;
import com.comcast.cns.model.CNSMessage.CNSMessageStructure;
import com.comcast.cns.model.CNSMessage.CNSMessageType;
import com.comcast.cns.model.CNSSubscription.CnsSubscriptionProtocol;

/**
 * Following class uses the HttpClient library version 4.2.1 
 * @author aseem, bwolf
 */
public class HTTPEndpointSyncPublisher extends AbstractEndpointPublisher {

    private final static SchemeRegistry schemeRegistry = new SchemeRegistry();
    private final static PoolingClientConnectionManager cm;
    private final static HttpClient httpClient;

    static {

        int timeoutMillis = CMBProperties.getInstance().getCNSPublisherHttpTimeoutSeconds() * 1000;

        HttpParams params = new BasicHttpParams();

        if (CMBProperties.getInstance().getCNSHttpProxy() != null
                && !CMBProperties.getInstance().getCNSHttpProxy().equals("")) {
            String p[] = CMBProperties.getInstance().getCNSHttpProxy().split(":");
            if (p.length == 2) {
                HttpHost proxy = new HttpHost(p[0], Integer.parseInt(p[1]), "http");
                params.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
            }
        }

        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);

        schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
        schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));

        HttpConnectionParams.setConnectionTimeout(params, timeoutMillis);
        HttpConnectionParams.setSoTimeout(params, timeoutMillis);

        cm = new PoolingClientConnectionManager(schemeRegistry);
        // increase max total connection to 250
        cm.setMaxTotal(CMBProperties.getInstance().getCNSPublisherHttpEndpointConnectionPoolSize());
        // increase default max connection per route to 20
        cm.setDefaultMaxPerRoute(CMBProperties.getInstance().getCNSPublisherHttpEndpointConnectionsPerRouteSize());

        httpClient = new DefaultHttpClient(cm, params);
    }

    private static Logger logger = Logger.getLogger(HTTPEndpointSyncPublisher.class);

    public static int getNumConnectionsInPool() {
        return cm.getTotalStats().getAvailable();
    }

    @Override
    public void send() throws Exception {

        if ((message == null) || (endpoint == null)) {
            logger.debug("event=send_http_request error_code=MissingParameters endpoint=" + endpoint
                    + "\" message=\"" + message + "\"");
            throw new Exception("Message and Endpoint must both be set");
        }

        HttpPost httpPost = new HttpPost(endpoint);

        String msg = null;

        if (message.getMessageStructure() == CNSMessageStructure.json) {
            msg = message.getProtocolSpecificMessage(CnsSubscriptionProtocol.http);
        } else {
            msg = message.getMessage();
        }

        if (!rawMessageDelivery && message.getMessageType() == CNSMessageType.Notification) {
            msg = com.comcast.cns.util.Util.generateMessageJson(message, CnsSubscriptionProtocol.http);
        }

        logger.debug("event=send_sync_http_request endpoint=" + endpoint + "\" message=\"" + msg + "\"");

        StringEntity stringEntity = new StringEntity(msg);
        httpPost.setEntity(stringEntity);
        composeHeader(httpPost);

        HttpResponse response = httpClient.execute(httpPost);
        int statusCode = response.getStatusLine().getStatusCode();

        HttpEntity entity = response.getEntity();

        // accept all 2xx status codes

        if (statusCode > 200 || statusCode >= 300) {

            if (entity != null) {

                InputStream instream = entity.getContent();
                InputStreamReader responseReader = new InputStreamReader(instream);
                StringBuffer buffer = new StringBuffer();

                char[] arr = new char[1024];
                int size = 0;

                while ((size = responseReader.read(arr, 0, arr.length)) != -1) {
                    buffer.append(arr, 0, size);
                }

                instream.close();
            }

            logger.debug("event=http_post_error endpoint=" + endpoint + " error_code=" + statusCode);
            throw new CMBException(new CMBErrorCodes(statusCode, "HttpError"),
                    "Unreachable endpoint " + endpoint + " returns status code " + statusCode);

        } else {

            if (entity != null) {
                EntityUtils.consume(entity);
            }
        }
    }

    private void composeHeader(HttpRequestBase httpRequest) {

        httpRequest.setHeader("x-amz-sns-message-type", this.getMessageType());
        httpRequest.setHeader("x-amz-sns-message-id", this.getMessageId());
        httpRequest.setHeader("x-amz-sns-topic-arn", this.getTopicArn());
        httpRequest.setHeader("x-amz-sns-subscription-arn", this.getSubscriptionArn());
        httpRequest.setHeader("User-Agent", "Cloud Notification Service Agent");

        if (this.getRawMessageDelivery()) {
            httpRequest.addHeader("x-amz-raw-message", "true");
        }
    }
}