* if the timeout expires or the consumer concurrently closed
* @throws JMSException if the next message can't be received
*/
public MessageImpl receive(long consumerId, long timeout)
throws JMSException {
MessageImpl message = null;
ensureOpen();
synchronized (_receiveLock) {
if (_blockingConsumer != -1) {
throw new IllegalStateException(
"Session cannot be accessed concurrently");
}
_blockingConsumer = consumerId;
long start = (timeout != 0) ? System.currentTimeMillis() : 0;
try {
while (message == null && !isClosed()) {
if (timeout == 0) {
message = getServerSession().receive(consumerId, 0);
} else {
message = getServerSession().receive(consumerId,
timeout);
}
if (message == null && !isClosed()) {
// no message received in the required time.
// Wait for a notification from the server that
// a message has become available.
try {
if (timeout == 0) {
_receiveLock.wait();
} else {
long elapsed = System.currentTimeMillis()
- start;
if (elapsed >= timeout) {
// no message received in the required time
break;
} else {
// adjust the timeout so that the client
// only waits as long as the original
// timeout
timeout -= elapsed;
}
_receiveLock.wait(timeout);
}
} catch (InterruptedException ignore) {
// no-op
}
}
}
if (message != null) {
message.setSession(this);
if (_ackMode == AUTO_ACKNOWLEDGE
|| _ackMode == DUPS_OK_ACKNOWLEDGE) {
getServerSession().acknowledgeMessage(
message.getConsumerId(),
message.getMessageId().toString());
}
}
} finally {
_blockingConsumer = -1;
}