package uk.co.acuminous.julez.event.source;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.TimeUnit;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import uk.co.acuminous.julez.event.handler.JmsEventHandler;
import uk.co.acuminous.julez.event.pipe.PassThroughPipe;
import uk.co.acuminous.julez.marshalling.EventUnmarshaller;
import uk.co.acuminous.julez.util.ConcurrencyUtils;
import uk.co.acuminous.julez.util.JmsHelper;
public class JmsEventSource extends PassThroughPipe implements MessageListener, Runnable {
private final QueueConnection connection;
private final String queueName;
private QueueSession session;
private Thread listenerThread;
private long lastReceivedTimestamp = System.currentTimeMillis();
private long shutdownDelay = 10000;
private final EventUnmarshaller unmarshaller;
public JmsEventSource(QueueConnectionFactory connectionFactory, EventUnmarshaller unmarshaller) {
this(connectionFactory, JmsEventHandler.DEFAULT_QUEUE_NAME, unmarshaller);
}
public JmsEventSource(QueueConnectionFactory connectionFactory, String queueName, EventUnmarshaller unmarshaller) {
this.connection = JmsHelper.getConnection(connectionFactory);
this.queueName = queueName;
this.unmarshaller = unmarshaller;
}
public JmsEventSource listen() {
listenerThread = ConcurrencyUtils.start(this);
return this;
}
public void setShutdownDelay(long duration, TimeUnit timeUnit) {
this.shutdownDelay = MILLISECONDS.convert(duration, timeUnit);
}
public void run() {
synchronized (this) {
try {
this.session = JmsHelper.registerListener(queueName, connection, this);
wait();
} catch (InterruptedException e) {
// Meh
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
@Override
public void onMessage(Message message) {
try {
lastReceivedTimestamp = System.currentTimeMillis();
String text = JmsHelper.getText(message);
onEvent(unmarshaller.unmarshall(text));
} catch (Throwable t) {
System.err.println(t);
}
}
public void shutdownWhenEmpty() {
try {
while (System.currentTimeMillis() - lastReceivedTimestamp < shutdownDelay) {
ConcurrencyUtils.sleep(100, MILLISECONDS);
}
} finally {
shutdown();
}
}
public void shutdown() {
if (listenerThread != null && listenerThread.isAlive()) {
listenerThread.interrupt();
}
JmsHelper.close(session, connection);
}
@Override
protected void finalize() {
JmsHelper.close(session, connection);
}
}