* or null if one is not immediately available. Returns null if the consumer is
* concurrently closed.
*/
public MessageProxy receive(long timeout) throws JMSException
{
MessageProxy m = null;
synchronized (mainLock)
{
if (trace) { log.trace(this + " receiving, timeout = " + timeout); }
if (closed)
{
// If consumer is closed or closing calling receive returns null
if (trace) { log.trace(this + " closed, returning null"); }
return null;
}
if (listener != null)
{
throw new JMSException("The consumer has a MessageListener set, " +
"cannot call receive(..)");
}
receiverThread = Thread.currentThread();
long startTimestamp = System.currentTimeMillis();
try
{
while(true)
{
if (timeout == 0)
{
if (trace) { log.trace(this + ": receive, no timeout"); }
m = getMessage(0);
if (m == null)
{
return null;
}
}
else if (timeout == -1)
{
//ReceiveNoWait
if (trace) { log.trace(this + ": receive, noWait"); }
m = getMessage(-1);
if (m == null)
{
if (trace) { log.trace(this + ": no message available"); }
return null;
}
}
else
{
if (trace) { log.trace(this + ": receive, timeout " + timeout + " ms, blocking poll on queue"); }
m = getMessage(timeout);
if (m == null)
{
// timeout expired
if (trace) { log.trace(this + ": " + timeout + " ms timeout expired"); }
return null;
}
}
if (trace) { log.trace(this + " received " + m + " after being blocked on buffer"); }
boolean ignore =
checkExpiredOrReachedMaxdeliveries(m, sessionDelegate, maxDeliveries, shouldAck);
if (!isConnectionConsumer && !ignore)
{
final DeliveryInfo info = new DeliveryInfo(m, consumerID, queueName, null, shouldAck, m.getSource());
if (timeout <= 0 || sessionDelegate.getTransacted())
{
ignore = ! sessionDelegate.preDeliver(info);
// If post deliver didn't succeed and acknowledgement mode is auto_ack
// That means the ref wasn't acked since it couldn't be found.
// In order to maintain at most once semantics we must therefore not return
// the message
if (!ignore)
{
ignore = !sessionDelegate.postDeliver();
}
}
else
{
//JBMESSAGING-1850
Callable<Boolean> afterReceive = new Callable<Boolean>()
{
public Boolean call() throws Exception
{
if (! sessionDelegate.preDeliver(info))
{
return true;
}
// If post deliver didn't succeed and acknowledgement mode is auto_ack
// That means the ref wasn't acked since it couldn't be found.
// In order to maintain at most once semantics we must therefore not return
// the message
return !sessionDelegate.postDeliver();
}
};
java.util.concurrent.Future<Boolean> f = pool.submit(afterReceive);
long tmUsed = System.currentTimeMillis() - startTimestamp;
long timeDelta = timeout - tmUsed;
long timeLeft = timeDelta <= minTimeoutProcessTime ? minTimeoutProcessTime : timeDelta ;
if (trace)
{
log.trace("Time left: " + timeLeft + " timeout " + timeout + " tmUsed " + tmUsed);
}
try
{
ignore = f.get(timeLeft, TimeUnit.MILLISECONDS);
}
catch (InterruptedException e)
{
log.warn("Interrupted during getting future result.", e);
}
catch (ExecutionException e)
{
log.warn("received application exception.", e.getCause());
Throwable t = e.getCause();
if (t instanceof JMSException)
{
throw (JMSException)t;
}
}
catch (TimeoutException e)
{
log.warn("Timed out waiting for post message processing " + m + " within time " + timeLeft);
ignore = false;
sessionDelegate.processMessageTimeout();
}
}
if (trace)
{
log.trace("Post deliver returned " + !ignore);
}
if (!ignore)
{
m.incDeliveryCount();
}
}
if (!ignore)
{