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

com.xerox.amazonws.sqs2.MessageQueue Maven / Gradle / Ivy

//
// typica - A client library for Amazon Web Services
// Copyright (C) 2007 Xerox 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.xerox.amazonws.sqs2;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBException;
import org.xml.sax.SAXException;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.client.HttpClient;
import org.apache.http.HttpException;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;

import com.xerox.amazonws.common.AWSException;
import com.xerox.amazonws.common.AWSQueryConnection;
import com.xerox.amazonws.typica.sqs2.jaxb.AddPermissionResponse;
import com.xerox.amazonws.typica.sqs2.jaxb.Attribute;
import com.xerox.amazonws.typica.sqs2.jaxb.ChangeMessageVisibilityResponse;
import com.xerox.amazonws.typica.sqs2.jaxb.DeleteMessageResponse;
import com.xerox.amazonws.typica.sqs2.jaxb.DeleteQueueResponse;
import com.xerox.amazonws.typica.sqs2.jaxb.GetQueueAttributesResponse;
import com.xerox.amazonws.typica.sqs2.jaxb.ReceiveMessageResponse;
import com.xerox.amazonws.typica.sqs2.jaxb.RemovePermissionResponse;
import com.xerox.amazonws.typica.sqs2.jaxb.SendMessageResponse;
import com.xerox.amazonws.typica.sqs2.jaxb.SetQueueAttributesResponse;

/**
 * This class provides an interface with the Amazon SQS message queue. It provides methods
 * for sending / receiving messages and deleting queues and messsages on queues.
 *
 * @author D. Kavanagh
 * @author [email protected]
 */
public class MessageQueue extends AWSQueryConnection {
    public static final int MAX_MESSAGES = 600;

	protected String queueId;
	private boolean enableEncoding = true;

    protected MessageQueue(String queueUrl, String awsAccessId,
							String awsSecretKey, boolean isSecure, int port,
							String server) throws SQSException {
        super(awsAccessId, awsSecretKey, isSecure, server, port);
		if (queueUrl.startsWith("http")) {
			queueId = queueUrl.substring(queueUrl.indexOf("//")+2);
		}
		else {
			queueId = queueUrl;	// this is the case where the queue is created from a
								// fully qualified queue name, not a full queue URL
		}
		queueId = queueId.substring(queueId.indexOf("/")+1);
		QueueService.setVersionHeader(this);
    }

	/**
	 * This method provides the URL for the message queue represented by this object.
	 *
	 * @return generated queue service url
	 */
	public URL getUrl() {
		try {
			return new URL(super.getUrl().toString());
		} catch (MalformedURLException ex) {
			return null;
		}
	}

	/**
	 * This method returns the state of the base64 encoding flag. By default, all messages
	 * are encoded on send and decoded on receive.
	 *
	 * @return state of encoding flag
	 */
	public boolean isEncoding() {
		return enableEncoding;
	}

	/**
	 * This method sets the state of the encoding flag. Use this to override the default and
	 * turn off automatic base64 encoding.
	 *
	 * @param enable the new state of the encoding flag
	 */
	public void setEncoding(boolean enable) {
		enableEncoding = enable;
	}

	/**
	 * Sends a message to a specified queue. The message must be between 1 and 256K bytes long.
	 *
	 * @param msg the message to be sent
	 * @throws SQSException wraps checked exceptions
	 */
    public String sendMessage(String msg) throws SQSException {
		Map params = new HashMap();
		String encodedMsg = enableEncoding?new String(Base64.encodeBase64(msg.getBytes())):msg;
		params.put("MessageBody", encodedMsg);
		HttpPost method = new HttpPost();
		SendMessageResponse response =
				makeRequestInt(method, "SendMessage", params, SendMessageResponse.class);
		return response.getSendMessageResult().getMessageId();
	}

	/**
	 * Attempts to receive a message from the queue. The queue default visibility timeout
	 * is used.
	 *
	 * @return the message object
	 * @throws SQSException wraps checked exceptions
	 */
    public Message receiveMessage() throws SQSException {
        Message amessage[] = receiveMessages(BigInteger.valueOf(1L), ((BigInteger) (null)), null);
        if(amessage.length > 0)
            return amessage[0];
        else
            return null;
	}

	/**
	 * Attempts to receive a message from the queue.
	 *
	 * @param visibilityTimeout the duration (in seconds) the retrieved message is hidden from
	 *                          subsequent calls to retrieve.
	 * @return the message object
	 * @throws SQSException wraps checked exceptions
	 */
    public Message receiveMessage(int visibilityTimeout) throws SQSException {
        Message amessage[] = receiveMessages(BigInteger.valueOf(1L), BigInteger.valueOf(visibilityTimeout), null);
        if(amessage.length > 0)
            return amessage[0];
        else
            return null;
	}

	/**
	 * Attempts to retrieve a number of messages from the queue. If less than that are availble,
	 * the max returned is the number of messages in the queue, but not necessarily all messages
	 * in the queue will be returned. The queue default visibility timeout is used.
	 *
	 * @param numMessages the maximum number of messages to return
	 * @return an array of message objects
	 * @throws SQSException wraps checked exceptions
	 */
    public Message[] receiveMessages(int numMessages) throws SQSException {
        return receiveMessages(BigInteger.valueOf(numMessages), ((BigInteger) (null)), null);
	}

	/**
	 * Attempts to retrieve a number of messages from the queue. If less than that are availble,
	 * the max returned is the number of messages in the queue, but not necessarily all messages
	 * in the queue will be returned.
	 *
	 * @param numMessages the maximum number of messages to return
	 * @param visibilityTimeout the duration (in seconds) the retrieved message is hidden from
	 *                          subsequent calls to retrieve.
	 * @return an array of message objects
	 * @throws SQSException wraps checked exceptions
	 */
    public Message[] receiveMessages(int numMessages, int visibilityTimeout) throws SQSException {
        return receiveMessages(BigInteger.valueOf(numMessages), BigInteger.valueOf(visibilityTimeout), null);
	}

	/**
	 * Attempts to retrieve a number of messages from the queue. If less than that are availble,
	 * the max returned is the number of messages in the queue, but not necessarily all messages
	 * in the queue will be returned.
	 *
	 * @param numMessages the maximum number of messages to return
	 * @param visibilityTimeout the duration (in seconds) the retrieved message is hidden from
	 *                          subsequent calls to retrieve.
	 * @param attributes the attributes you'd like to get (SenderId, SentTimestamp, All, ApproximateReceiveCount, ApproximateFirstReceiveTimestamp)
	 * @return an array of message objects
	 * @throws SQSException wraps checked exceptions
	 */
    public Message[] receiveMessages(int numMessages, int visibilityTimeout, List attributes)
			throws SQSException {
        return receiveMessages(BigInteger.valueOf(numMessages), BigInteger.valueOf(visibilityTimeout), attributes);
	}

	/**
	 * Internal implementation of receiveMessages.
	 *
	 * @param numMessages the maximum number of messages to return
	 * @param visibilityTimeout the duration (in seconds) the retrieved message is hidden from
	 *                          subsequent calls to retrieve.
	 * @param attributes the attributes you'd like to get (SenderId, SentTimestamp)
	 * @return an array of message objects
	 * @throws SQSException wraps checked exceptions
	 */
    protected Message[] receiveMessages(BigInteger numMessages, BigInteger visibilityTimeout, List attributes)
			throws SQSException {
		Map params = new HashMap();
		if (numMessages != null) {
			params.put("MaxNumberOfMessages", numMessages.toString());
		}
		if (visibilityTimeout != null) {
			params.put("VisibilityTimeout", visibilityTimeout.toString());
		}
		if (attributes != null) {
			int i=1;
			for (String attr : attributes) {
				params.put("AttributeName."+i, attr);
				i++;
			}
		}
		HttpGet method = new HttpGet();
		ReceiveMessageResponse response =
				makeRequestInt(method, "ReceiveMessage", params, ReceiveMessageResponse.class);
		if (response.getReceiveMessageResult().getMessages() == null) {
			return new Message[0];
		}
		else {
			ArrayList msgs = new ArrayList();
			for (com.xerox.amazonws.typica.sqs2.jaxb.Message msg : response.getReceiveMessageResult().getMessages()) {
				String decodedMsg = enableEncoding?
							new String(Base64.decodeBase64(msg.getBody().getBytes())):
										msg.getBody();
				Message newMsg = new Message(msg.getMessageId(), msg.getReceiptHandle(), decodedMsg, msg.getMD5OfBody());
				for (Attribute attr : msg.getAttributes()) {
					newMsg.setAttribute(attr.getName(), attr.getValue());
				}
				msgs.add(newMsg);
			}
			return msgs.toArray(new Message [msgs.size()]);
		}
	}

	/**
	 * Deletes the message identified by message object on the queue this object represents.
	 *
	 * @param msg the message to be deleted
	 * @throws SQSException wraps checked exceptions
	 */
    public void deleteMessage(Message msg) throws SQSException {
		deleteMessage(msg.getReceiptHandle());
	}

	/**
	 * Deletes the message identified by receiptHandle on the queue this object represents.
	 *
	 * @param receiptHandle the handle of the message to be deleted
	 * @throws SQSException wraps checked exceptions
	 */
    public void deleteMessage(String receiptHandle) throws SQSException {
		Map params = new HashMap();
		params.put("ReceiptHandle", receiptHandle);
		HttpGet method = new HttpGet();
	//	DeleteMessageResponse response =
			makeRequestInt(method, "DeleteMessage", params, DeleteMessageResponse.class);
	}

	/**
	 * Deletes the message queue represented by this object. Will delete non-empty queue.
	 *
	 * @throws SQSException wraps checked exceptions
	 */
    public void deleteQueue() throws SQSException {
		Map params = new HashMap();
		HttpGet method = new HttpGet();
	//	DeleteQueueResponse response =
			makeRequestInt(method, "DeleteQueue", params, DeleteQueueResponse.class);
	}

	/**
	 * Sets the message visibility timeout. 
	 *
	 * @param msg the message
	 * @param timeout the duration (in seconds) the retrieved message is hidden from
	 *                          subsequent calls to retrieve.
	 * @throws SQSException wraps checked exceptions
	 */
    public void setMessageVisibilityTimeout(Message msg, int timeout) throws SQSException {
		setMessageVisibilityTimeout(msg.getReceiptHandle(), timeout);
	}

	/**
	 * Sets the message visibility timeout. 
	 *
	 * @param receiptHandle the handle of the message to be deleted
	 * @param timeout the duration (in seconds) the retrieved message is hidden from
	 *                          subsequent calls to retrieve.
	 * @throws SQSException wraps checked exceptions
	 */
    public void setMessageVisibilityTimeout(String receiptHandle, int timeout) throws SQSException {
		Map params = new HashMap();
		params.put("ReceiptHandle", receiptHandle);
		params.put("VisibilityTimeout", ""+timeout);
		HttpGet method = new HttpGet();
		makeRequestInt(method, "ChangeMessageVisibility", params, ChangeMessageVisibilityResponse.class);
	}

	/**
	 * Gets the visibility timeout for the queue. Uses {@link #getQueueAttributes(QueueAttribute)}.
	 *
	 * @throws SQSException wraps checked exceptions
	 */
    public int getVisibilityTimeout() throws SQSException {
		return Integer.parseInt(getQueueAttributes(QueueAttribute.VISIBILITY_TIMEOUT)
										.values().iterator().next());
	}

	/**
	 * Gets the visibility timeout for the queue. Uses {@link #getQueueAttributes(QueueAttribute)}.
	 *
	 * @throws SQSException wraps checked exceptions
	 */
    public int getApproximateNumberOfMessages() throws SQSException {
		return Integer.parseInt(getQueueAttributes(QueueAttribute.APPROXIMATE_NUMBER_OF_MESSAGES)
										.values().iterator().next());
	}

	/**
	 * Gets queue attributes. This is provided to expose the underlying functionality.
	 * Currently supported attributes are;
	 *   ApproximateNumberOfMessages
	 *   CreatedTimestamp
	 *   LastModifiedTimestamp
	 *   VisibilityTimeout
	 *   RequestPayer
	 *   Policy
	 *
	 * @return a map of attributes and their values
	 * @throws SQSException wraps checked exceptions
	 */
	public Map getQueueAttributes(QueueAttribute qAttr) throws SQSException {
		Map params = new HashMap();
		params.put("AttributeName", qAttr.queryAttribute());
		HttpGet method = new HttpGet();
		GetQueueAttributesResponse response =
				makeRequestInt(method, "GetQueueAttributes", params, GetQueueAttributesResponse.class);
		Map ret = new HashMap();
		List attrs = response.getGetQueueAttributesResult().getAttributes();
		for (Attribute attr : attrs) {
			ret.put(attr.getName(), attr.getValue());
		}
		return ret;
	}

	/**
	 * Sets the visibility timeout of the queue. Uses {@link #setQueueAttribute(String, String)}.
	 *
	 * @param timeout the duration (in seconds) the retrieved message is hidden from
	 *                          subsequent calls to retrieve.
	 * @throws SQSException wraps checked exceptions
	 */
    public void setVisibilityTimeout(int timeout) throws SQSException {
		setQueueAttribute("VisibilityTimeout", ""+timeout);
	}

	/**
	 * Sets a queue attribute. This is provided to expose the underlying functionality, although
	 * the only attribute at this time is visibility timeout.
	 *
	 * @param attribute name of the attribute being set
	 * @param value the value being set for this attribute
	 * @throws SQSException wraps checked exceptions
	 */
    public void setQueueAttribute(String attribute, String value) throws SQSException {
		Map params = new HashMap();
		params.put("Attribute.Name", attribute);
		params.put("Attribute.Value", value);
		HttpGet method = new HttpGet();
	//	SetQueueAttributesResponse response =
			makeRequestInt(method, "SetQueueAttributes", params, SetQueueAttributesResponse.class);
	}

	/**
	 * Adds a permission to this message queue.
	 *
	 * @param label a name for this permission
	 * @param accountId the AWS account ID for the account to share this queue with
	 * @param action a value to indicate how much to share (SendMessage, ReceiveMessage, ChangeMessageVisibility, DeleteMessage, GetQueueAttributes)
	 * @throws SQSException wraps checked exceptions
	 */
	public void addPermission(String label, String accountId, String action) throws SQSException {
		Map params = new HashMap();
		params.put("Label", label);
		params.put("AWSAccountId", accountId);
		params.put("ActionName", action);
		HttpGet method = new HttpGet();
		AddPermissionResponse response =
				makeRequestInt(method, "AddPermission", params, AddPermissionResponse.class);
	}

	/**
	 * Removes a permission from this message queue.
	 *
	 * @param label a name for the permission to be removed
	 * @throws SQSException wraps checked exceptions
	 */
	public void removePermission(String label) throws SQSException {
		Map params = new HashMap();
		params.put("Label", label);
		HttpGet method = new HttpGet();
		RemovePermissionResponse response =
			makeRequestInt(method, "RemovePermission", params, RemovePermissionResponse.class);
	}

	/**
	 * Overriding this because the queue name is baked into the URL and QUERY
	 * assembles the URL within the baseclass.
	 *
	 * @throws SQSException wraps checked exceptions
	 */
	protected URL makeURL(String resource) throws MalformedURLException {
		return super.makeURL(queueId+resource);
	}

	protected  T makeRequestInt(HttpRequestBase method, String action, Map params, Class respType)
		throws SQSException {
		try {
			return makeRequest(method, action, params, respType);
		} catch (AWSException ex) {
			throw new SQSException(ex);
		} catch (JAXBException ex) {
			throw new SQSException("Problem parsing returned message.", ex);
		} catch (SAXException ex) {
			throw new SQSException("Problem parsing returned message.", ex);
		} catch (HttpException ex) {
			throw new SQSException(ex.getMessage(), ex);
		} catch (IOException ex) {
			throw new SQSException(ex.getMessage(), ex);
		}
	}

	public static List createList(String [] queueUrls, String awsAccessId,
								String awsSecretKey, boolean isSecure, int port, String server, HttpClient hc)
			throws SQSException {
		ArrayList ret = new ArrayList();
		for (int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy