com.comcast.cns.tools.CQSHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.comcast.cns.tools.CQSHandler.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.tools;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.conn.HttpHostConnectException;
import org.apache.log4j.Logger;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.sqs.AmazonSQSClient;
import com.amazonaws.services.sqs.model.ChangeMessageVisibilityRequest;
import com.amazonaws.services.sqs.model.CreateQueueRequest;
import com.amazonaws.services.sqs.model.CreateQueueResult;
import com.amazonaws.services.sqs.model.DeleteMessageRequest;
import com.amazonaws.services.sqs.model.GetQueueUrlRequest;
import com.amazonaws.services.sqs.model.Message;
import com.amazonaws.services.sqs.model.MessageAttributeValue;
import com.amazonaws.services.sqs.model.ReceiveMessageRequest;
import com.amazonaws.services.sqs.model.ReceiveMessageResult;
import com.amazonaws.services.sqs.model.SendMessageRequest;
import com.amazonaws.services.sqs.model.SendMessageResult;
import com.comcast.cmb.common.controller.CMBControllerServlet;
import com.comcast.cmb.common.model.User;
import com.comcast.cmb.common.persistence.IUserPersistence;
import com.comcast.cmb.common.persistence.PersistenceFactory;
import com.comcast.cmb.common.util.CMBException;
import com.comcast.cmb.common.util.CMBProperties;
import com.comcast.cmb.common.util.PersistenceException;
import com.comcast.cmb.common.util.ValueAccumulator.AccumulatorName;
import com.comcast.cqs.api.CQSAPI;
import com.comcast.cqs.controller.CQSCache;
import com.comcast.cqs.model.CQSMessage;
import com.comcast.cqs.model.CQSMessageAttribute;
import com.comcast.cqs.model.CQSQueue;
import com.comcast.cqs.util.Util;

public class CQSHandler {

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

    private static volatile boolean initialized = false;
    private static volatile BasicAWSCredentials awsCredentials = null;
    private static volatile AmazonSQSClient sqs = null;
    private static User cnsInternal = null;
    private static boolean useInlineApiCalls = false;

    static {
        try {
            initialize();
        } catch (PersistenceException ex) {
            logger.error("event=initialization_failure", ex);
        }
    }

    private static synchronized void initialize() throws PersistenceException {

        if (initialized) {
            return;
        }

        IUserPersistence userHandler = PersistenceFactory.getUserPersistence();

        if (CMBProperties.getInstance().getCNSUserAccessKey() != null
                && CMBProperties.getInstance().getCNSUserAccessSecret() != null) {

            //TODO: should add user id to cmb properties file

            awsCredentials = new BasicAWSCredentials(CMBProperties.getInstance().getCNSUserAccessKey(),
                    CMBProperties.getInstance().getCNSUserAccessSecret());
            cnsInternal = userHandler.getUserByAccessKey(awsCredentials.getAWSAccessKeyId());

        } else {

            cnsInternal = userHandler.getUserByName(CMBProperties.getInstance().getCNSUserName());

            if (cnsInternal == null) {
                cnsInternal = userHandler.createDefaultUser();
            }

            awsCredentials = new BasicAWSCredentials(cnsInternal.getAccessKey(), cnsInternal.getAccessSecret());
        }

        sqs = new AmazonSQSClient(awsCredentials);
        sqs.setEndpoint(CMBProperties.getInstance().getCQSServiceUrl());

        useInlineApiCalls = CMBProperties.getInstance().useInlineApiCalls()
                && CMBProperties.getInstance().getCQSServiceEnabled();

        initialized = true;
    }

    public static void changeMessageVisibility(String relativeQueueUrl, String receiptHandle, int visibilityTimeout)
            throws Exception {

        long ts1 = System.currentTimeMillis();

        if (useInlineApiCalls) {
            CQSAPI.changeMessageVisibility(cnsInternal.getUserId(), relativeQueueUrl, receiptHandle,
                    visibilityTimeout);
        } else {
            String absoluteQueueUrl = Util.getAbsoluteQueueUrlForRelativeUrl(relativeQueueUrl);
            sqs.changeMessageVisibility(
                    new ChangeMessageVisibilityRequest(absoluteQueueUrl, receiptHandle, visibilityTimeout));
        }

        long ts2 = System.currentTimeMillis();

        CMBControllerServlet.valueAccumulator.addToCounter(AccumulatorName.CNSCQSTime, ts2 - ts1);
        logger.debug(
                "event=change_message_visibility receipt_handle=" + receiptHandle + " vto=" + visibilityTimeout);
    }

    public static List<CQSMessage> receiveMessage(String relativeQueueUrl, int waitTimeSeconds,
            int maxNumberOfMessages) throws Exception {

        //TODO: inline calling for long polled receive not supported yet

        List<CQSMessage> messages = new ArrayList<CQSMessage>();
        long ts1 = System.currentTimeMillis();

        if (useInlineApiCalls && waitTimeSeconds == 0) {

            messages = CQSAPI.receiveMessages(cnsInternal.getUserId(), relativeQueueUrl, maxNumberOfMessages, null);

        } else {

            String absoluteQueueUrl = Util.getAbsoluteQueueUrlForRelativeUrl(relativeQueueUrl);
            ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(absoluteQueueUrl);
            receiveMessageRequest.setMaxNumberOfMessages(maxNumberOfMessages);
            receiveMessageRequest.setMessageAttributeNames(new ArrayList<String>(Arrays.asList("All")));
            //receiveMessageRequest.setVisibilityTimeout(CMBProperties.getInstance().getCNSPublishJobVisibilityTimeout());

            if (waitTimeSeconds > 0) {
                receiveMessageRequest.setWaitTimeSeconds(waitTimeSeconds);
            }

            ReceiveMessageResult receiveMessageResult = sqs.receiveMessage(receiveMessageRequest);
            List<Message> msgs = receiveMessageResult.getMessages();

            for (Message m : msgs) {
                messages.add(new CQSMessage(m));
            }
        }

        long ts2 = System.currentTimeMillis();
        CMBControllerServlet.valueAccumulator.addToCounter(AccumulatorName.CNSCQSTime, ts2 - ts1);

        return messages;
    }

    public static String getQueueUrl(String queueName) throws Exception {

        String queueUrl = null;

        long ts1 = System.currentTimeMillis();

        CQSQueue queue = CQSCache
                .getCachedQueue(Util.getRelativeQueueUrlForName(queueName, cnsInternal.getUserId()));

        if (queue != null) {
            queueUrl = queue.getAbsoluteUrl();
        }

        long ts2 = System.currentTimeMillis();

        CMBControllerServlet.valueAccumulator.addToCounter(AccumulatorName.CNSCQSTime, ts2 - ts1);

        return queueUrl;
    }

    public static String sendMessage(String relativeQueueUrl, String message,
            Map<String, CQSMessageAttribute> messageAttributes) throws Exception {

        long ts1 = System.currentTimeMillis();
        String receiptHandle = null;

        if (useInlineApiCalls) {
            receiptHandle = CQSAPI.sendMessage(cnsInternal.getUserId(), relativeQueueUrl, message, null,
                    messageAttributes);
        } else {
            String absoluteQueueUrl = Util.getAbsoluteQueueUrlForRelativeUrl(relativeQueueUrl);

            SendMessageRequest sendMessageRequest = new SendMessageRequest(absoluteQueueUrl, message);

            if (messageAttributes != null) {
                for (String messageAttributeName : messageAttributes.keySet()) {
                    MessageAttributeValue value = new MessageAttributeValue();
                    value.setDataType(messageAttributes.get(messageAttributeName).getDataType());
                    value.setStringValue(messageAttributes.get(messageAttributeName).getStringValue());
                    sendMessageRequest.addMessageAttributesEntry(messageAttributeName, value);
                }
            }

            SendMessageResult sendMessageResult = sqs.sendMessage(sendMessageRequest);
            receiptHandle = sendMessageResult.getMessageId();
        }

        long ts2 = System.currentTimeMillis();

        CMBControllerServlet.valueAccumulator.addToCounter(AccumulatorName.CNSCQSTime, ts2 - ts1);
        logger.debug("event=send_message message_id=" + receiptHandle);

        return receiptHandle;
    }

    public static void deleteMessage(String relativeQueueUrl, String receiptHandle) throws Exception {

        long ts1 = System.currentTimeMillis();

        if (useInlineApiCalls) {
            CQSAPI.deleteMessage(cnsInternal.getUserId(), relativeQueueUrl, receiptHandle);
        } else {
            String absoluteQueueUrl = Util.getAbsoluteQueueUrlForRelativeUrl(relativeQueueUrl);
            sqs.deleteMessage(new DeleteMessageRequest(absoluteQueueUrl, receiptHandle));
        }

        long ts2 = System.currentTimeMillis();

        CMBControllerServlet.valueAccumulator.addToCounter(AccumulatorName.CNSCQSTime, ts2 - ts1);
        logger.debug("event=delete_message receipt_handle=" + receiptHandle);
    }

    public static synchronized void ensureQueuesExist(String queueNamePrefix, int numShards) {

        for (int i = 0; i < numShards; i++) {

            GetQueueUrlRequest getQueueUrlRequest = new GetQueueUrlRequest(queueNamePrefix + i);

            try {
                sqs.getQueueUrl(getQueueUrlRequest);
            } catch (AmazonServiceException ex) {

                if (ex.getStatusCode() == 400) {

                    CreateQueueRequest createQueueRequest = new CreateQueueRequest(queueNamePrefix + i);
                    Map<String, String> attributes = new HashMap<String, String>();

                    if (queueNamePrefix
                            .startsWith(CMBProperties.getInstance().getCNSEndpointPublishQueueNamePrefix())) {
                        attributes.put("VisibilityTimeout",
                                CMBProperties.getInstance().getCNSEndpointPublishJobVisibilityTimeout() + "");
                    } else {
                        attributes.put("VisibilityTimeout",
                                CMBProperties.getInstance().getCNSPublishJobVisibilityTimeout() + "");
                    }

                    createQueueRequest.setAttributes(attributes);
                    CreateQueueResult createQueueResponse = sqs.createQueue(createQueueRequest);

                    if (createQueueResponse.getQueueUrl() == null) {
                        throw new IllegalStateException("Could not create queue with name " + queueNamePrefix + i);
                    }

                    logger.info("event=created_missing_queue name=" + queueNamePrefix + i + " url="
                            + createQueueResponse.getQueueUrl());

                } else {
                    throw ex;
                }
            }
        }
    }

    public static boolean doesQueueNotExist(Exception ex) {

        boolean doesNotExist = false;

        if (ex instanceof AmazonServiceException && ((AmazonServiceException) ex).getStatusCode() == 400) {
            doesNotExist = true;
        } else if (ex instanceof AmazonServiceException
                && ((AmazonServiceException) ex).getErrorCode().equals("NonExistentQueue")) {
            doesNotExist = true;
        } else if (ex.getCause() instanceof HttpHostConnectException) {
            doesNotExist = false;
        } else if (ex instanceof CMBException) {
            doesNotExist = false;
        }

        return doesNotExist;
    }

    public static String getRelativeCnsInternalQueueUrl(String queueName) {
        String localQueueUrl = Util.getRelativeQueueUrlForName(queueName, cnsInternal.getUserId());
        return localQueueUrl;
    }
}