package cz.cuni.mff.d3s.been.mq;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import cz.cuni.mff.d3s.been.annotation.ThreadSafe;
/**
*
* Experimental interface for accessing queues.
*
* The idea is to gain access to message queues (inproc, tcp) by a known name
* instead of passing references around.
*
* It's a singleton.
*
*
* @author Martin Sixta
*/
@ThreadSafe
public class MessageQueues {
/**
* The singleton.
*/
private static MessageQueues ourInstance = new MessageQueues();
/**
* Stores mapping to queues.
*/
private final Map<String, IMessageQueue> queues;
/**
*
*/
private final Map<String, IMessageSender> defaultSenders;
/**
* Private constructor, it's a singleton.
*/
private MessageQueues() {
this.queues = new HashMap<>();
this.defaultSenders = new HashMap<>();
}
/**
* Returns the only one and true MessageQueues object.
*
* @return the singleton
*/
public static MessageQueues getInstance() {
return ourInstance;
}
/**
* Creates named intra-procedural message queue (communication within the
* bounds of one process).
*
* @param queueName
* name of the qeueue
* @param <T>
* type of messages
* @return Inproc message queue
* @throws MessagingException
* if the queue cannot be created
*/
public synchronized
<T extends Serializable>
IMessageQueue<T>
createInprocQueue(String queueName) throws MessagingException {
if (queues.containsKey(queueName)) {
String errorMsg = String.format("Queue %s already exists", queueName);
throw new MessagingException(errorMsg);
}
IMessageQueue<T> queue = Messaging.createInprocQueue(queueName);
queues.put(queueName, queue);
return queue;
}
/**
* Creates named tcp message queue.
*
* @param queueName name of the queue
* @return tcp message queue
* @throws MessagingException
* When the queue already exists or if it cannot be created
*/
public synchronized IMessageQueue<String> createTcpQueue(String queueName, String hostname) throws MessagingException {
if (queues.containsKey(queueName)) {
String errorMsg = String.format("Queue %s already exists", queueName);
throw new MessagingException(errorMsg);
}
IMessageQueue<String> queue = Messaging.createTcpQueue(hostname);
queues.put(queueName, queue);
return queue;
}
/**
* Creates sender associated with a named queue.
*
* @param queueName
* name of the queue
* @param <T>
* type of messages
* @return sender The sender
*
* @throws MessagingException If the desired queue is not initialized
*/
public synchronized
<T extends Serializable>
IMessageSender<T>
createSender(String queueName) throws MessagingException {
if (!queues.containsKey(queueName)) {
String errorMsg = String.format("Queue %s does not exist", queueName);
throw new MessagingException(errorMsg);
}
return queues.get(queueName).createSender();
}
/**
* Returns receiver associated with a named queue.
*
* @param queueName name of the queue
* @param <T> Type of messages this receiver will be using
*
* @return receiver The receiver
*
* @throws MessagingException When the desired queue is not initialized
*/
public synchronized
<T extends Serializable>
IMessageReceiver<T>
getReceiver(String queueName) throws MessagingException {
if (!queues.containsKey(queueName)) {
String errorMsg = String.format("Queue %s does not exist", queueName);
throw new MessagingException(errorMsg);
}
return queues.get(queueName).getReceiver();
}
/**
* Terminates a named queue.
*
* @param queueName Name of the queue to terminate
*
* @throws MessagingException If the desired queue is not initialized
*/
public synchronized void terminate(String queueName) throws MessagingException {
if (!queues.containsKey(queueName)) {
String errorMsg = String.format("Queue %s does not exist", queueName);
throw new MessagingException(errorMsg);
}
final IMessageSender sender = defaultSenders.get(queueName);
if (sender != null) {
sender.close();
defaultSenders.remove(queueName);
}
queues.get(queueName).terminate();
queues.remove(queueName);
}
/**
* Sends an object to a named queue.
*
* WARNING: This method is not very fast since it is synchronized, use with
* care.
*
* @param queueName
* name of a queue
* @param serializable
* object to send
* @throws MessagingException If the desired queue is not initialized
*/
public synchronized void send(String queueName, Serializable serializable) throws MessagingException {
if (!queues.containsKey(queueName)) {
if (!queues.containsKey(queueName)) {
String errorMsg = String.format("Queue %s does not exist", queueName);
throw new MessagingException(errorMsg);
}
}
if (!defaultSenders.containsKey(queueName)) {
defaultSenders.put(queueName, createSender(queueName));
}
final IMessageSender sender = defaultSenders.get(queueName);
sender.send(serializable);
}
}