docs: public SIBusMessage nextLocked()
    throws SISessionUnavailableException, SISessionDroppedException,
           SIResourceException, SIConnectionLostException,
           SIErrorException, SIIncorrectCallException
    {
      if (TraceComponent.isAnyTracingEnabled() && CoreSPILockedMessageEnumeration.tc.isEntryEnabled())
        SibTr.entry(CoreSPILockedMessageEnumeration.tc, "nextLocked",
          new Object[] {new Integer(hashCode()), this});
  
      JsMessage jsMsg = null;
      JsMessageWrapper msg = null;
      LMEMessage dirtyMessage = null;
      boolean removeMsg = false;
  
      checkValidState("nextLocked");
  
      localConsumerPoint.checkNotClosed();
  
      // Make any list modifications under the lock
      synchronized(this)
      {
        // If we still have an unlocked message in the list remove it now
        if(currentUnlockedMessage != null)
        {
          removeMessage(currentUnlockedMessage);
          currentUnlockedMessage = null;
        }
  
        if(currentMsg != null)
          currentMsg = currentMsg.next;
        else if(!endReached)
          currentMsg = firstMsg;
  
        if(currentMsg != null)
        {
          msg = currentMsg.message;
          jsMsg = currentMsg.jsMessage;
  
          // Due to the slight dodgyness of setting jsMsg (see comment on dirtyMessage)
          // this tries to ensure our logic is correct
          if((jsMsg != null) && !currentMsg.wasRead)
          {
            SIErrorException e =
              new SIErrorException(nls.getFormattedMessage(
                              "INTERNAL_MESSAGING_ERROR_CWSIP0001",
                              new Object[] {
                                "com.ibm.ws.sib.processor.impl.AbstractLockedMessageEnumeration",
                                "1:1318:1.154.3.1" },
                                null));
  
            if (TraceComponent.isAnyTracingEnabled() && CoreSPILockedMessageEnumeration.tc.isEntryEnabled())
              SibTr.exit(CoreSPILockedMessageEnumeration.tc, "nextLocked", e);
  
            throw e;
          }
  
          // If the message was added to the message store but the consumer does
          // not require recovery we can delete the message before we return it.
          // We don't want to do it here under the lock, so we remember to do it
          // later but pretend we've already done it by the time we release the
          // lock - that way no-one else will think its in the message store when it
          // isn't.
          if(currentMsg.isStored && !currentMsg.isRecoverable)
          {
            removeMsg = true;
            currentMsg.isStored = false;
          }
  
          // We're about to release the list lock but we need to be able to set
          // the jsMessage back into the LMEMessage object later so we save a
          // pointer to it. BUT there is a slight possibility that by the time
          // we write the jsMessage into it the LMEMessage has been deleted from
          // the list (e.g. by an unlockAll() from the consumer), that's not a
          // problem in itself. BUT by deleting it from the list we actually can
          // put it into the set of pooled objects so you could be writing over
          // another message BUT we currently hold the AsynchConsumerLock and we
          // know no new messages can be added to the list unless they hold that
          // lock SO we may have moved into the pool but we couldn't have been
          // re-used SO we're safe!
          dirtyMessage = currentMsg;
          currentMsg.wasRead = true;
  
          //indicate that there is a message under the cursor
          messageAvailable = true;
        }
        else
        {
          messageAvailable = false;
          endReached = true;
        }
      } // synchronized
  
      //check it isn't null
      if((msg != null) && (jsMsg == null))
      {
        jsMsg = setPropertiesInMessage(currentMsg);
  
  
        if(removeMsg)
        {
          try
          {
            removeMessageFromStore(msg,
                                   null,
                                   false); // false = DON'T decrement active message count
                                           // (wait until the message is deleted/unlocked from the LME)
          }
          catch (SIMPMessageNotLockedException e)
          {
  //        SIMPMessageNotLockedException shouldn't occur so FFDC.
            FFDCFilter.processException(
              e,
              "com.ibm.ws.sib.processor.impl.AbstractLockedMessageEnumeration.nextLocked",
              "1:1396:1.154.3.1",
              this);
  
            SibTr.exception(tc, e);
            SibTr.error(tc, "INTERNAL_MESSAGING_ERROR_CWSIP0002",
              new Object[] {
                "com.ibm.ws.sib.processor.impl.AbstractLockedMessageEnumeration",
                "1:1403:1.154.3.1",
                e });
  
            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              SibTr.exit(tc, "nextLocked", e);
  
            throw new SIResourceException(
              nls.getFormattedMessage(
                "INTERNAL_MESSAGING_ERROR_CWSIP0002",
                new Object[] {
                  "com.ibm.ws.sib.processor.impl.AbstractLockedMessageEnumeration",
                  "1:1414:1.154.3.1",
                  e },
                null),
              e);
          }
        }
  
        dirtyMessage.jsMessage = jsMsg; // Read earlier comment before touching this!
      }
  
      if (TraceComponent.isAnyTracingEnabled() && UserTrace.tc_mt.isDebugEnabled())
        UserTrace.trace_Receive(null,
                                jsMsg,
                                consumerSession.getDestinationAddress(),
                                consumerSession.getIdInternal());
  
      if (TraceComponent.isAnyTracingEnabled() && CoreSPILockedMessageEnumeration.tc.isEntryEnabled())
        SibTr.exit(CoreSPILockedMessageEnumeration.tc, "nextLocked", new Object[] {jsMsg});
      //return the message or null
      return jsMsg;
    }