package vnet.sms.gateway.server.framework.test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import javax.jms.Message;
import javax.jms.MessageListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ForwardingJmsMessageListener implements MessageListener {
private static final Logger LOG = LoggerFactory
.getLogger(ForwardingJmsMessageListener.class);
private static final class LoggingMessageListener implements
MessageListener {
@Override
public void onMessage(final Message arg0) {
LOG.info("Received message {}", arg0);
}
}
private final AtomicReference<MessageListener> delegate = new AtomicReference<MessageListener>(
new LoggingMessageListener());
@Override
public void onMessage(final Message arg0) {
this.delegate.get().onMessage(arg0);
}
public MessageListener setDelegate(final MessageListener delegate) {
return this.delegate.getAndSet(delegate != null ? delegate
: new LoggingMessageListener());
}
public MessageListener unsetDelegate() {
return this.delegate.getAndSet(new LoggingMessageListener());
}
public CountDownLatch awaitMatchingMessage(
final JmsMessagePredicate predicate) {
final CountDownLatch matchingMessageReceived = new CountDownLatch(1);
final MessageListener waitForMatchingMessage = new MessageListener() {
@Override
public void onMessage(final Message arg0) {
LOG.debug("Testing if received message {} satisfies {} ...",
arg0, predicate);
if (predicate.evaluate(arg0)) {
LOG.info("Received message {} DOES satisfy {}", arg0,
predicate);
matchingMessageReceived.countDown();
} else {
LOG.debug("Received message {} does NOT satisfy {}", arg0,
predicate);
}
}
};
setDelegate(waitForMatchingMessage);
return matchingMessageReceived;
}
public Future<Message> receiveMatchingMessage(
final JmsMessagePredicate predicate) {
final CountDownLatch matchingMessageReceived = new CountDownLatch(1);
final AtomicReference<Message> receivedMatchingMessage = new AtomicReference<Message>();
final MessageListener waitForMatchingMessage = new MessageListener() {
@Override
public void onMessage(final Message arg0) {
LOG.debug("Testing if received message {} satisfies {} ...",
arg0, predicate);
if (predicate.evaluate(arg0)) {
LOG.info("Received message {} DOES satisfy {}", arg0,
predicate);
receivedMatchingMessage.set(arg0);
matchingMessageReceived.countDown();
} else {
LOG.debug("Received message {} does NOT satisfy {}", arg0,
predicate);
}
}
};
setDelegate(waitForMatchingMessage);
return new JmsMessageFuture(matchingMessageReceived,
receivedMatchingMessage);
}
private final class JmsMessageFuture implements Future<Message> {
private final CountDownLatch matchingMessageReceived;
private final AtomicReference<Message> receivedMatchingMessage;
private JmsMessageFuture(final CountDownLatch matchingMessageReceived,
final AtomicReference<Message> receivedMatchingMessage) {
this.matchingMessageReceived = matchingMessageReceived;
this.receivedMatchingMessage = receivedMatchingMessage;
}
@Override
public boolean cancel(final boolean arg0) {
return false;
}
@Override
public Message get() throws InterruptedException, ExecutionException {
this.matchingMessageReceived.await();
return this.receivedMatchingMessage.get();
}
@Override
public Message get(final long arg0, final TimeUnit arg1)
throws InterruptedException, ExecutionException,
TimeoutException {
if (!this.matchingMessageReceived.await(arg0, arg1)) {
throw new TimeoutException(
"Failed to retrieve Message after waiting for [" + arg0
+ "] " + arg1);
}
return this.receivedMatchingMessage.get();
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
return this.matchingMessageReceived.getCount() == 0;
}
}
}