throw new IllegalStateException("Thread interrupted while closing consumer");
   public void close() throws JMSException   {      try      {         synchronized (mainLock)         {            if (closed)            {               return;            }                        closing = true;                           //We wait for any activation in progress to complete and the resulting message            //(if any) to be returned and processed.            //The ensures a clean, gracefully closure of the client side consumer, without            //any messages in transit which might arrive after the consumer is closed and which            //subsequently might be cancelled out of sequence causing message ordering problems            waitForActivationsToComplete();                           //Now we know there are no activations in progress but the consumer may still be active so we call            //deactivate which returns the id of the last message we should have received            //if we have received this message then we know there is no possibility of any message still in            //transit and we can close down with confidence            //otherwise we wait for this message and timeout if it doesn't arrive which might be the case            //if the connection to the server has been lost                        //TODO Make configurable            final int TIMEOUT = 20000;                        long lastMessageIDToExpect = deactivateConsumer();                        if (lastMessageIDToExpect != -1)            {                           long waitTime = TIMEOUT;                              while (lastMessageIDToExpect != lastMessageId && waitTime > 0)               {                                 waitTime = waitOnLock(mainLock, waitTime);                          }                              if (lastMessageIDToExpect != lastMessageId)               {                  log.warn("Timed out waiting for last message to arrive, last=" + lastMessageId +" expected=" + lastMessageIDToExpect);               }            }                        //We set this even if we timed out waiting since we do not want any more to arrive now            gotLastMessage = true;                                    //Wake up any receive() thread that might be waiting            mainLock.notify();                        //Now make sure that any onMessage of a listener has finished executing                        long waitTime = TIMEOUT;                        synchronized (onMessageLock)            {                              while (onMessageExecuting && waitTime > 0)               {                  waitTime = waitOnLock(onMessageLock, waitTime);                  }               if (onMessageExecuting)               {                  //Timed out waiting for last onMessage to be processed                  log.warn("Timed out waiting for last onMessage to be executed");                           }            }                                    //Now we know that all messages have been received and processed                                                         if (!buffer.isEmpty())            {                           //Now we cancel any deliveries that might be waiting in our buffer               Iterator iter = buffer.iterator();                              List ids = new ArrayList();               while (iter.hasNext())               {                                          MessageProxy mp = (MessageProxy)iter.next();                                    ids.add(new Long(mp.getMessage().getMessageID()));                                                   }               cancelDeliveries(ids);            }                      //Now we are done            listener = null;                        receiverThread = null;                        closed = true;           }      }      catch (InterruptedException e)      {         //No one should be interrupting the thread so this shouldn't occur         throw new IllegalStateException("Thread interrupted while closing consumer");      }   }