Amazon 亚马逊平台 AWS数据智慧仓库 源码-立哥开发

/*
 * 
 * Copyright 2021 Jacky  Zong. All rights reserved.
 * 
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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.amazon.sqs.javamessaging;

import java.util.HashSet;
import java.util.Set;

import javax.jms.InvalidDestinationException;
import javax.jms.JMSException;
import javax.jms.JMSSecurityException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.AmazonWebServiceRequest;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.regions.Region;
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.model.ChangeMessageVisibilityBatchRequest;
import com.amazonaws.services.sqs.model.ChangeMessageVisibilityBatchResult;
import com.amazonaws.services.sqs.model.ChangeMessageVisibilityRequest;
import com.amazonaws.services.sqs.model.CreateQueueResult;
import com.amazonaws.services.sqs.model.DeleteMessageBatchRequest;
import com.amazonaws.services.sqs.model.DeleteMessageBatchResult;
import com.amazonaws.services.sqs.model.DeleteMessageRequest;
import com.amazonaws.services.sqs.model.CreateQueueRequest;
import com.amazonaws.services.sqs.model.GetQueueUrlRequest;
import com.amazonaws.services.sqs.model.GetQueueUrlResult;
import com.amazonaws.services.sqs.model.QueueDoesNotExistException;
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;

/**
 * This is a JMS Wrapper of <code>AmazonSQSClient</code>. This class changes all
 * <code>AmazonServiceException</code> and <code>AmazonClientException</code> into
 * JMSException/JMSSecurityException.
 */
public class AmazonSQSMessagingClientWrapper {
    private static final Log LOG = LogFactory.getLog(AmazonSQSMessagingClientWrapper.class);
    
    private static final Set<String> SECURITY_EXCEPTION_ERROR_CODES;
    static {
     
        SECURITY_EXCEPTION_ERROR_CODES = new HashSet<String>();
        SECURITY_EXCEPTION_ERROR_CODES.add("MissingClientTokenId");
        SECURITY_EXCEPTION_ERROR_CODES.add("InvalidClientTokenId");
        SECURITY_EXCEPTION_ERROR_CODES.add("MissingAuthenticationToken");
        SECURITY_EXCEPTION_ERROR_CODES.add("AccessDenied");
    }

    private final AmazonSQS amazonSQSClient;
    private final AWSCredentialsProvider credentialsProvider;
    
    
    public AmazonSQSMessagingClientWrapper(AmazonSQS amazonSQSClient) throws JMSException {
        this(amazonSQSClient, null);
    }
    
    /**
     * @param amazonSQSClient
     *            The AWS SDK Client for SQS.
     * @throws JMSException
     *            if the client is null
     */
    public AmazonSQSMessagingClientWrapper(AmazonSQS amazonSQSClient, AWSCredentialsProvider credentialsProvider) throws JMSException {
        if (amazonSQSClient == null) {
            throw new JMSException("Amazon SQS client cannot be null");
        }
        this.amazonSQSClient = amazonSQSClient;
        this.credentialsProvider = credentialsProvider;
    }
    
  
    public AmazonSQS getAmazonSQSClient() {
        return amazonSQSClient;
    }

    /**
     * Sets SQS endpoint and wraps IllegalArgumentException. 
     * Deprecated. Instead of manipulating settings of existing AmazonSQS client, provide correct configuration when creating it through SQSConnectionFactory constructors.
     * 
     * @param endpoint
     *            The endpoint (ex: "sqs.us-east-1.amazonaws.com") of the region
     *            specific AWS endpoint this client will communicate with.
     * @throws JMSException
     */
    @Deprecated
    public void setEndpoint(String endpoint) throws JMSException {
        try {
            amazonSQSClient.setEndpoint(endpoint);
        } catch (IllegalArgumentException ase) {
            JMSException jmsException = new JMSException(ase.getMessage());
            throw (JMSException) jmsException.initCause(ase);
        }
    }
    

    
 
    public void deleteMessage(DeleteMessageRequest deleteMessageRequest) throws JMSException {
        try {
            prepareRequest(deleteMessageRequest);
            amazonSQSClient.deleteMessage(deleteMessageRequest);
        } catch (AmazonClientException e) {
            throw handleException(e, "deleteMessage");
        }
    }
    
   
    public DeleteMessageBatchResult deleteMessageBatch(DeleteMessageBatchRequest deleteMessageBatchRequest) throws JMSException {
        try {
            prepareRequest(deleteMessageBatchRequest);
            return amazonSQSClient.deleteMessageBatch(deleteMessageBatchRequest);
        } catch (AmazonClientException e) {
            throw handleException(e, "deleteMessageBatch");
        }    
    }
    
    /**
     * Calls <code>sendMessage</code> and wraps
     * <code>AmazonClientException</code>.
     * 
     * @param sendMessageRequest
     *            Container for the necessary parameters to execute the
     *            sendMessage service method on AmazonSQS.
     * @return The response from the sendMessage service method, as returned by
     *         AmazonSQS
     * @throws JMSException
     */
    public SendMessageResult sendMessage(SendMessageRequest sendMessageRequest) throws JMSException {
        try {
            prepareRequest(sendMessageRequest);
            return amazonSQSClient.sendMessage(sendMessageRequest);
        } catch (AmazonClientException e) {
            throw handleException(e, "sendMessage");
        }    
    }
 
    public boolean queueExists(String queueName) throws JMSException {
        try {
            amazonSQSClient.getQueueUrl(prepareRequest(new GetQueueUrlRequest(queueName)));
            return true;
        } catch (QueueDoesNotExistException e) {
            return false;
        } catch (AmazonClientException e) {
            throw handleException(e, "getQueueUrl");  
        } 
    }
    
    /**
     * Check if the requested queue exists. This function calls
     * <code>GetQueueUrl</code> for the given queue name with the given owner
     * accountId, returning true on success, false if it gets
     * <code>QueueDoesNotExistException</code>.
     * 
     * @param queueName
     *            the queue to check
     * @param queueOwnerAccountId
     *            The AWS accountId of the account that created the queue
     * @return true if the queue exists, false if it doesn't.
     * @throws JMSException
     */
    public boolean queueExists(String queueName, String queueOwnerAccountId) throws JMSException {
        try {
            GetQueueUrlRequest getQueueUrlRequest = new GetQueueUrlRequest(queueName);
            getQueueUrlRequest.setQueueOwnerAWSAccountId(queueOwnerAccountId);
            prepareRequest(getQueueUrlRequest);
            amazonSQSClient.getQueueUrl(getQueueUrlRequest);
            return true;
        } catch (QueueDoesNotExistException e) {
            return false;
        } catch (AmazonClientException e) {
            throw handleException(e, "getQueueUrl");
        }
    }
    
    /**
     * Gets the queueUrl of a queue given a queue name.
     * 
     * @param queueName
     * @return The response from the GetQueueUrl service method, as returned by
     *         AmazonSQS, which will include queue`s URL
     * @throws JMSException
     */
    public GetQueueUrlResult getQueueUrl(String queueName) throws JMSException {
        return getQueueUrl(new GetQueueUrlRequest(queueName));
    }
    
    /**
     * Gets the queueUrl of a queue given a queue name owned by the provided accountId.
     * 
     * @param queueName
     * @param queueOwnerAccountId The AWS accountId of the account that created the queue
     * @return The response from the GetQueueUrl service method, as returned by
     *         AmazonSQS, which will include queue`s URL
     * @throws JMSException
     */
    public GetQueueUrlResult getQueueUrl(String queueName, String queueOwnerAccountId) throws JMSException {
        return getQueueUrl(new GetQueueUrlRequest(queueName).withQueueOwnerAWSAccountId(queueOwnerAccountId));
    }
     
    /**
     * Calls <code>getQueueUrl</code> and wraps <code>AmazonClientException</code>
     * 
     * @param getQueueUrlRequest
     *            Container for the necessary parameters to execute the
     *            getQueueUrl service method on AmazonSQS.
     * @return The response from the GetQueueUrl service method, as returned by
     *         AmazonSQS, which will include queue`s URL
     * @throws JMSException
     */
    public GetQueueUrlResult getQueueUrl(GetQueueUrlRequest getQueueUrlRequest) throws JMSException {
        try {
            prepareRequest(getQueueUrlRequest);
            return amazonSQSClient.getQueueUrl(getQueueUrlRequest);
        } catch (AmazonClientException e) {
            throw handleException(e, "getQueueUrl");  
        }    
    }
    
    /**
     * Calls <code>createQueue</code> to create the queue with the default queue attributes,
     * and wraps <code>AmazonClientException</code>
     * 
     * @param queueName
     * @return The response from the createQueue service method, as returned by
     *         AmazonSQS. This call creates a new queue, or returns the URL of
     *         an existing one.
     * @throws JMSException
     */
    public CreateQueueResult createQueue(String queueName) throws JMSException {
        return createQueue(new CreateQueueRequest(queueName));
    }
    
    /**
     * Calls <code>createQueue</code> to create the queue with the provided queue attributes
     * if any, and wraps <code>AmazonClientException</code>
     * 
     * @param createQueueRequest
     *            Container for the necessary parameters to execute the
     *            createQueue service method on AmazonSQS.
     * @return The response from the createQueue service method, as returned by
     *         AmazonSQS. This call creates a new queue, or returns the URL of
     *         an existing one.
     * @throws JMSException
     */
    public CreateQueueResult createQueue(CreateQueueRequest createQueueRequest) throws JMSException {
        try {
            prepareRequest(createQueueRequest);
            return amazonSQSClient.createQueue(createQueueRequest);
        } catch (AmazonClientException e) {
            throw handleException(e, "createQueue");   
        }    
    }
    
    /**
     * Calls <code>receiveMessage</code> and wraps <code>AmazonClientException</code>. Used by
     * {@link SQSMessageConsumerPrefetch} to receive up to minimum of
     * (<code>numberOfMessagesToPrefetch</code>,10) messages from SQS queue into consumer
     * prefetch buffers.
     * 
     * @param receiveMessageRequest
     *            Container for the necessary parameters to execute the
     *            receiveMessage service method on AmazonSQS.
     * @return The response from the ReceiveMessage service method, as returned
     *         by AmazonSQS.
     * @throws JMSException
     */    
    public ReceiveMessageResult receiveMessage(ReceiveMessageRequest receiveMessageRequest) throws JMSException {
        try {
            prepareRequest(receiveMessageRequest);
            return amazonSQSClient.receiveMessage(receiveMessageRequest);
        } catch (AmazonClientException e) {
            throw handleException(e, "receiveMessage");
        }
    }
    
    /**
     * Calls <code>changeMessageVisibility</code> and wraps <code>AmazonClientException</code>. This is 
     * used to for negative acknowledge of a single message, so that messages can be received again without any delay.
     * 
     * @param changeMessageVisibilityRequest
     *            Container for the necessary parameters to execute the
     *            changeMessageVisibility service method on AmazonSQS.
     * @throws JMSException
     */
    public void changeMessageVisibility(ChangeMessageVisibilityRequest changeMessageVisibilityRequest) throws JMSException {
        try {
            prepareRequest(changeMessageVisibilityRequest);
            amazonSQSClient.changeMessageVisibility(changeMessageVisibilityRequest);
        } catch (AmazonClientException e) {
            throw handleException(e, "changeMessageVisibility");
        }    
    }
    
    /**
     * Calls <code>changeMessageVisibilityBatch</code> and wraps <code>AmazonClientException</code>. This is
     * used to for negative acknowledge of messages in batch, so that messages
     * can be received again without any delay.
     * 
     * @param changeMessageVisibilityBatchRequest
     *            Container for the necessary parameters to execute the
     *            changeMessageVisibilityBatch service method on AmazonSQS.
     * @return The response from the changeMessageVisibilityBatch service
     *         method, as returned by AmazonSQS.
     * @throws JMSException
     */
    public ChangeMessageVisibilityBatchResult changeMessageVisibilityBatch(ChangeMessageVisibilityBatchRequest changeMessageVisibilityBatchRequest)
            throws JMSException {
        try {
            prepareRequest(changeMessageVisibilityBatchRequest);
            return amazonSQSClient.changeMessageVisibilityBatch(changeMessageVisibilityBatchRequest);
        } catch (AmazonClientException e) {
            throw handleException(e, "changeMessageVisibilityBatch");
        }
    }

    /**
     * Create generic error message for <code>AmazonServiceException</code>. Message include
     * Action, RequestId, HTTPStatusCode, and AmazonErrorCode.
     */
    private String logAndGetAmazonServiceException(AmazonServiceException ase, String action) {
        String errorMessage = "AmazonServiceException: " + action + ". RequestId: " + ase.getRequestId() +
                              "\nHTTPStatusCode: " + ase.getStatusCode() + " AmazonErrorCode: " +
                              ase.getErrorCode();
        LOG.error(errorMessage, ase);
        return errorMessage;
    }

    /**
     * Create generic error message for <code>AmazonClientException</code>. Message include
     * Action.
     */
    private String logAndGetAmazonClientException(AmazonClientException ace, String action) {
        String errorMessage = "AmazonClientException: " + action + ".";
        LOG.error(errorMessage, ace);
        return errorMessage;
    }
    
    private JMSException handleException(AmazonClientException e, String operationName) throws JMSException {
        JMSException jmsException;
        if (e instanceof AmazonServiceException) {
            AmazonServiceException se = ( AmazonServiceException ) e;
            
            if (e instanceof QueueDoesNotExistException) {
                jmsException = new InvalidDestinationException(
                        logAndGetAmazonServiceException(se, operationName), se.getErrorCode());
            } else if (isJMSSecurityException(se)) {
                jmsException = new JMSSecurityException(
                        logAndGetAmazonServiceException(se, operationName), se.getErrorCode());
            } else {
                jmsException = new JMSException(
                        logAndGetAmazonServiceException(se, operationName), se.getErrorCode());
            }

        } else {
            jmsException = new JMSException(logAndGetAmazonClientException(e, operationName));
        }
        jmsException.initCause(e);
        return jmsException;
    }
    
    private boolean isJMSSecurityException(AmazonServiceException e) {
        return SECURITY_EXCEPTION_ERROR_CODES.contains(e.getErrorCode()) ;
    }
    
    private <T extends AmazonWebServiceRequest> T prepareRequest(T request) {
        request.getRequestClientOptions().appendUserAgent(SQSMessagingClientConstants.APPENDED_USER_AGENT_HEADER_VERSION);
        if (credentialsProvider != null) {
            request.setRequestCredentialsProvider(credentialsProvider);
        }
        return request;
    }
    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值