org.skyscreamer.nevado.jms.NevadoConnection Maven / Gradle / Ivy
package org.skyscreamer.nevado.jms;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.skyscreamer.nevado.jms.connector.SQSConnector;
import org.skyscreamer.nevado.jms.destination.*;
import javax.jms.*;
import javax.jms.IllegalStateException;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Nevado's implementation of JMS Connection.
*
* @author Carter Page
*/
public class NevadoConnection implements Connection {
public static final int DEFAULT_MAX_POLL_WAIT_MS = 5000;
private final Log _log = LogFactory.getLog(getClass());
private final AtomicBoolean _closed = new AtomicBoolean(false);
private final AtomicBoolean _running = new AtomicBoolean(false);
protected volatile boolean _inUse = false;
private final SQSConnector _sqsConnector;
private volatile String _clientID;
private volatile String _connectionID = UUID.randomUUID().toString();
private volatile Integer _jmsDeliveryMode;
private volatile Long _jmsTTL;
private volatile Integer _jmsPriority;
private volatile ExceptionListener _exceptionListener;
private final List _sessions = new CopyOnWriteArrayList();
private final Set _temporaryDestinations = new CopyOnWriteArraySet();
private String _temporaryQueueSuffix = "";
private String _temporaryTopicSuffix = "";
private long _maxPollWaitMs = DEFAULT_MAX_POLL_WAIT_MS;
private String _durableSubcriptionPrefixOveride;
public NevadoConnection(SQSConnector sqsConnector) throws JMSException {
_sqsConnector = sqsConnector;
_sqsConnector.test();
}
@Override
public NevadoSession createSession(boolean transacted, int acknowledgeMode) throws JMSException {
checkClosed();
_inUse = true;
NevadoSession nevadoSession = new NevadoSession(this, transacted, acknowledgeMode);
initializeSession(nevadoSession);
return nevadoSession;
}
protected void initializeSession(NevadoSession nevadoSession) {
nevadoSession.setOverrideJMSDeliveryMode(_jmsDeliveryMode);
nevadoSession.setOverrideJMSTTL(_jmsTTL);
nevadoSession.setOverrideJMSPriority(_jmsPriority);
synchronized (_running) {
_sessions.add(nevadoSession);
if (_running.get())
{
nevadoSession.start();
}
}
}
@Override
public NevadoConnectionMetaData getMetaData() throws JMSException {
return NevadoConnectionMetaData.getInstance();
}
@Override
public ExceptionListener getExceptionListener() {
return _exceptionListener;
}
@Override
public void setExceptionListener(ExceptionListener exceptionListener) throws IllegalStateException {
checkClosed();
_exceptionListener = exceptionListener;
}
@Override
public void start() throws JMSException
{
checkClosed();
_inUse = true;
synchronized (_running) {
_running.set(true);
for(NevadoSession session : _sessions)
{
session.start();
}
}
}
@Override
public void stop() throws JMSException
{
checkClosed();
synchronized (_running) {
_running.set(false);
for(NevadoSession session : _sessions)
{
session.stop();
}
}
}
@Override
public void close() throws JMSException {
synchronized (_closed) {
if (!_closed.get()) {
stop();
List sessionExceptions = new ArrayList();
for(NevadoSession session : _sessions)
{
try {
session.close();
} catch (JMSException e) {
sessionExceptions.add(e);
_log.warn("Caught exception closing a session. Will continue trying to clean up, then will " +
"throw it up the stack. (First one if multiple.)", e);
}
}
for(NevadoDestination temporaryDestination : new ArrayList(_temporaryDestinations)) {
try {
if (temporaryDestination instanceof NevadoTemporaryQueue)
{
deleteTemporaryQueue((NevadoTemporaryQueue)temporaryDestination);
}
else if (temporaryDestination instanceof NevadoTemporaryTopic)
{
deleteTemporaryTopic((NevadoTemporaryTopic) temporaryDestination);
}
else
{
throw new IllegalStateException("Unexpected temporary destination of type: "
+ temporaryDestination.getClass().getName());
}
} catch (JMSException e) {
// Log but continue
_log.error("Unable to delete temporary destination " + temporaryDestination, e);
}
}
_temporaryDestinations.clear();
_closed.set(true);
if (sessionExceptions.size() > 0) {
throw sessionExceptions.get(0);
}
}
}
}
@Override
public ConnectionConsumer createConnectionConsumer(Destination destination, String s, ServerSessionPool serverSessionPool, int i) throws JMSException {
checkClosed();
_inUse = true;
return null; // TODO
}
@Override
public ConnectionConsumer createDurableConnectionConsumer(Topic topic, String s, String s1, ServerSessionPool serverSessionPool, int i) throws JMSException {
checkClosed();
_inUse = true;
return null; // TODO
}
protected NevadoTemporaryTopic createTemporaryTopic() throws JMSException {
checkClosed();
String tempTopicName = "" + NevadoProviderQueuePrefix.TEMPORARY_DESTINATION_PREFIX
+ new BigInteger(64, new Random()).toString(Character.MAX_RADIX) + _temporaryTopicSuffix;
NevadoTopic topic = getSQSConnector().createTopic(tempTopicName);
_log.info("Created temporary topic " + tempTopicName);
NevadoTemporaryTopic temporaryTopic = new NevadoTemporaryTopic(this, topic);
_temporaryDestinations.add(temporaryTopic);
return temporaryTopic;
}
public void deleteTemporaryTopic(NevadoTemporaryTopic temporaryTopic) throws JMSException
{
checkClosed();
deleteTopic(temporaryTopic);
_temporaryDestinations.remove(temporaryTopic);
}
public void deleteTopic(NevadoTopic topic) throws JMSException {
getSQSConnector().deleteTopic(topic);
topic.setDeleted(true);
}
protected NevadoTemporaryQueue createTemporaryQueue() throws JMSException
{
checkClosed();
String tempQueueName = "" + NevadoProviderQueuePrefix.TEMPORARY_DESTINATION_PREFIX
+ new BigInteger(64, new Random()).toString(Character.MAX_RADIX) + _temporaryQueueSuffix;
NevadoQueue queue = getSQSConnector().createQueue(tempQueueName);
_log.info("Created temporary queue " + tempQueueName);
NevadoTemporaryQueue temporaryQueue = new NevadoTemporaryQueue(this, queue);
_temporaryDestinations.add(temporaryQueue);
return temporaryQueue;
}
public void deleteTemporaryQueue(NevadoTemporaryQueue temporaryQueue) throws JMSException
{
checkClosed();
deleteQueue(temporaryQueue);
_temporaryDestinations.remove(temporaryQueue);
}
protected void deleteQueue(NevadoQueue queue) throws JMSException {
_sqsConnector.deleteQueue(queue);
queue.setDeleted(true);
}
protected boolean ownsTemporaryDestination(Destination temporaryDestination)
{
return _temporaryDestinations.contains(temporaryDestination);
}
public Collection listAllTemporaryQueues() throws JMSException {
Collection queues = getSQSConnector()
.listQueues(NevadoProviderQueuePrefix.TEMPORARY_DESTINATION_PREFIX + "");
Collection temporaryQueues = new HashSet(queues.size());
for(NevadoQueue queue : queues) {
temporaryQueues.add(new NevadoTemporaryQueue(this, queue));
}
return temporaryQueues;
}
public Collection listAllTemporaryTopics() throws JMSException {
Collection topics = getSQSConnector().listTopics();
Collection temporaryTopics = new HashSet(topics.size());
for(NevadoTopic topic : topics) {
if (topic.getTopicName().startsWith(NevadoProviderQueuePrefix.TEMPORARY_DESTINATION_PREFIX + ""))
temporaryTopics.add(new NevadoTemporaryTopic(this, topic));
}
return temporaryTopics;
}
public Collection deleteUnusedTemporaryQueues(String suffix) throws JMSException {
if (suffix == null)
suffix = "";
Collection allQueues = listAllTemporaryQueues();
List deletedQueues = new ArrayList();
for (NevadoTemporaryQueue queue : allQueues) {
if (queue.getQueueName().endsWith(suffix) && !_temporaryDestinations.contains(queue)) {
deleteTemporaryQueue(queue);
deletedQueues.add(queue);
}
}
return deletedQueues;
}
public Collection deleteUnusedTemporaryTopics(String suffix) throws JMSException {
if (suffix == null)
suffix = "";
Collection allTopics = listAllTemporaryTopics();
List deletedTopics = new ArrayList();
for (NevadoTemporaryTopic topic : allTopics) {
if (topic.getTopicName().endsWith(suffix) && !_temporaryDestinations.contains(topic)) {
deleteTemporaryTopic(topic);
deletedTopics.add(topic);
}
}
return deletedTopics;
}
public String subscribe(NevadoTopic topic, NevadoQueue topicEndpoint) throws JMSException {
return getSQSConnector().subscribe(topic, topicEndpoint);
}
public void unsubscribe(NevadoTopic topic) throws JMSException {
getSQSConnector().unsubscribe(topic);
}
// Getters & Setters
public SQSConnector getSQSConnector() {
return _sqsConnector;
}
@Override
public String getClientID() {
return _clientID;
}
@Override
public void setClientID(String clientID) throws JMSException {
checkClosed();
if (clientID == null || clientID.trim().length() == 0)
{
throw new InvalidClientIDException("Client ID is empty");
}
if (_clientID != null) {
throw new IllegalStateException("Client ID has already been set");
}
if (_inUse) {
throw new IllegalStateException("Client ID cannot be set after the connection is in use");
}
if (clientID != null && !clientID.matches("^[\\w\\-_]+$"))
{
throw new InvalidClientIDException("Client ID can only include alphanumeric characters, hyphens, or underscores");
}
_clientID = clientID;
_connectionID = clientID;
}
public void setOverrideJMSDeliveryMode(Integer jmsDeliveryMode) throws IllegalStateException {
checkClosed();
_jmsDeliveryMode = jmsDeliveryMode;
}
public void setOverrideJMSPriority(Integer jmsPriority) throws IllegalStateException {
checkClosed();
_jmsPriority = jmsPriority;
}
public void setOverrideJMSTTL(Long jmsTTL) throws IllegalStateException {
checkClosed();
_jmsTTL = jmsTTL;
}
public void setTemporaryQueueSuffix(String temporaryQueueSuffix) {
_temporaryQueueSuffix = temporaryQueueSuffix;
}
public void setTemporaryTopicSuffix(String temporaryTopicSuffix) {
_temporaryTopicSuffix = temporaryTopicSuffix;
}
public void setMaxPollWaitMs(long maxPollWaitMs) {
_maxPollWaitMs = maxPollWaitMs;
}
protected long getMaxPollWaitMs() {
return _maxPollWaitMs;
}
public boolean isRunning() {
return _running.get();
}
/**
* Tell whether the connection is closed. If the connection is in the process of closing, this
* will return true until complete.
*
* @return true if closed, otherwise false
*/
public boolean isClosed() {
return _closed.get();
}
protected void checkClosed() throws IllegalStateException {
if (_closed.get())
{
throw new IllegalStateException("Connection is closed");
}
}
public String getConnectionID() {
return _connectionID;
}
public void setDurableSubcriptionPrefixOveride(String durableSubcriptionPrefixOveride) {
_durableSubcriptionPrefixOveride = durableSubcriptionPrefixOveride;
}
public String getDurableSubcriptionPrefixOveride() {
return _durableSubcriptionPrefixOveride;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy