if (iter.hasNext()) { ref = (MessageReference)iter.next(); } else
iter.remove(); }  Delivery delivery = new SimpleDelivery(this, ref, true);  acknowledgeInternal(delivery); } else {    Delivery del = push(ref);  if (del == null) {    if (trace) { log.trace(this + ": no delivery returned for message" + ref + " so no receiver got the message"); log.trace("Delivery is now complete"); }  receiversReady = false;  return; } else if (!del.isSelectorAccepted()) {             if (iter == null)
   protected void deliverInternal()   {      try      {         // The iterator is used to iterate through the refs in the channel in the case that they         // don't match the selectors of any receivers.         ListIterator iter = null;                  MessageReference ref = null;                  while (true)         {                       //TODO simplify locking - do we really need two locks??            synchronized (refLock)            {                             synchronized (deliveryLock)               {                  if (iter == null)                  {                     ref = (MessageReference) messageRefs.peekFirst();                  }                  else                  {                     if (iter.hasNext())                     {                                                ref = (MessageReference)iter.next();                     }                      else                     {                        ref = null;                     }                  }                                 if (ref != null)                  {                     // Check if message is expired (we also do this on the client                     // side)                     // If so ack it from the channel                     if (ref.isExpired())                     {                        if (trace) { log.trace("Message reference: " + ref + " has expired"); }                              // remove and acknowledge it                        if (iter == null)                        {                           removeFirstInMemory();                        }                        else                        {                           iter.remove();                        }                              Delivery delivery = new SimpleDelivery(this, ref, true);                              acknowledgeInternal(delivery);                     }                     else                     {                        // Reference is not expired                              // Attempt to push the ref to a receiver                        Delivery del = push(ref);                              if (del == null)                        {                           // no receiver, broken receiver                           // or full receiver                               // so we stop delivering                           if (trace) { log.trace(this + ": no delivery returned for message"                                         + ref + " so no receiver got the message");                                        log.trace("Delivery is now complete"); }                                 receiversReady = false;                                 return;                        }                        else if (!del.isSelectorAccepted())                        {                           // No receiver accepted the message because no selectors matched                           // So we create an iterator (if we haven't already created it) to                           // iterate through the refs in the channel                           // TODO Note that this is only a partial solution since if there are messages paged to storage                           // it won't try those - i.e. it will only iterate through those refs in memory.                           // Dealing with refs in storage is somewhat tricky since we can't just load them and iterate                           // through them since we might run out of memory                           // So we will need to load individual refs from storage given the selector expressions                           // Secondly we should also introduce some in memory indexes here to prevent having to                           // iterate through all the refs every time                           // Having said all that, having consumers on a queue that don't match many messages                           // is an antipattern and should be avoided by the user                           if (iter == null)                           {                              iter = messageRefs.iterator();                           }                                             }                        else                        {                           if (trace) { log.trace(this + ": " + del + " returned for message:" + ref); }                                                      //Receiver accepted the reference                                 // We must synchronize here to cope with another race                           // condition where message is                           // cancelled/acked in flight while the following few                           // actions are being performed.                           // e.g. delivery could be cancelled acked after being                           // removed from state but before                           // delivery being added (observed).                           synchronized (del)                           {                              if (trace) { log.trace(this + " incrementing delivery count for " + del); }                                    // FIXME - It's actually possible the delivery could be                              // cancelled before it reaches                              // here, in which case we wouldn't get a delivery but we                              // still need to increment the                              // delivery count                              // All the problems related to these race conditions and                              // fiddly edge cases will disappear                              // once we do                              // http://jira.jboss.com/jira/browse/JBMESSAGING-355                              // This will make life a lot easier                                    del.getReference().incrementDeliveryCount();                                                        if (!del.isCancelled())                              {                                 if (iter == null)                                 {                                    removeFirstInMemory();                                 }                                 else                                 {                                    iter.remove();                                                                 }                                       // delivered                                 if (!del.isDone())                                 {                                    // Add the delivery to state                                    deliveries.add(del);                                                                  }                              }                           }                        }                     }                  }                  else                  {                     // No more refs in channel                     if (trace) { log.trace(this + " no more refs to deliver "); }                     break;                  }               }            }         }      }      catch (Throwable t)      {         log.error(this + " Failed to deliver", t);      }   }