docs: public void send(SIBusMessage sibMsg, SITransaction tranImpl)
    throws SISessionUnavailableException, SISessionDroppedException,
           SIConnectionUnavailableException, SIConnectionDroppedException,
           SIResourceException, SIConnectionLostException, SILimitExceededException,
           SIErrorException,
           SINotAuthorizedException,
           SIIncorrectCallException,
           SINotPossibleInCurrentConfigurationException
    {
      if (TraceComponent.isAnyTracingEnabled() && CoreSPIProducerSession.tc.isEntryEnabled())
        SibTr.entry(CoreSPIProducerSession.tc, "send", new Object[] { this, sibMsg, tranImpl });
  
      if (tranImpl != null && !((TransactionCommon)tranImpl).isAlive())
      {
        SIMPIncorrectCallException e = new SIMPIncorrectCallException(
          nls_cwsik.getFormattedMessage(
             "DELIVERY_ERROR_SIRC_16",  // TRANSACTION_SEND_USAGE_ERROR_CWSIP0093
             new Object[] { _destination },
             null) );
  
        e.setExceptionReason(SIRCConstants.SIRC0016_TRANSACTION_SEND_USAGE_ERROR);
        e.setExceptionInserts(new String[] {_destination.getName()});
  
        if (TraceComponent.isAnyTracingEnabled() && TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled())
          SibTr.exception(tc, e);
  
        if (TraceComponent.isAnyTracingEnabled() && CoreSPIProducerSession.tc.isEntryEnabled())
          SibTr.exit(CoreSPIProducerSession.tc, "send", e);
  
        throw e;
      }
      synchronized (this)
      {
        checkNotClosed();
  
        // Ensure that the destination is put enabled
        if (!_destination.isSendAllowed())
        {
          if (TraceComponent.isAnyTracingEnabled() && CoreSPIProducerSession.tc.isEntryEnabled())
            SibTr.exit(CoreSPIProducerSession.tc, "send", "Destination is send disabled");
  
          SIMPNotPossibleInCurrentConfigurationException e = new SIMPNotPossibleInCurrentConfigurationException(
            nls_cwsik.getFormattedMessage(
              "DELIVERY_ERROR_SIRC_17", // DESTINATION_LOCKED_ERROR_CWSIP0232
              new Object[] { _destination.getName(),
                             _messageProcessor.getMessagingEngineName() },
              null));
  
          e.setExceptionReason(SIRCConstants.SIRC0017_DESTINATION_LOCKED_ERROR);
          e.setExceptionInserts(new String[] { _destination.getName(),
                                        _messageProcessor.getMessagingEngineName() });
          throw e;
        }
  
        // Extract the message
        JsMessage msg = null;
        try
        {
          msg = ((JsMessage) sibMsg).getSent(_conn.getMessageCopiedWhenSent());
        }
        catch (MessageCopyFailedException e)
        {
          FFDCFilter.processException(
            e,
            "com.ibm.ws.sib.processor.impl.ProducerSessionImpl.send",
            "1:379:1.217",
            this);
  
          SibTr.exception(tc, e);
          SibTr.error(tc, "INTERNAL_MESSAGING_ERROR_CWSIP0002",
            new Object[] {
              "com.ibm.ws.sib.processor.impl.ProducerSessionImpl",
              "1:386:1.217",
              e });
  
          if (TraceComponent.isAnyTracingEnabled() && CoreSPIProducerSession.tc.isEntryEnabled())
            SibTr.exit(CoreSPIProducerSession.tc, "send", "Could not make a safe copy of message");
  
          SIMPErrorException ex = new SIMPErrorException(
            nls.getFormattedMessage(
              "INTERNAL_MESSAGING_ERROR_CWSIP0002",
              new Object[] {
                "com.ibm.ws.sib.processor.impl.ProducerSessionImpl",
                "1:397:1.217",
                e },
              null),
            e);
  
          ex.setExceptionReason(SIRCConstants.SIRC0901_INTERNAL_MESSAGING_ERROR);
          ex.setExceptionInserts(new String[] {
            "com.ibm.ws.sib.processor.impl.ProducerSessionImpl",
            "1:405:1.217",
            SIMPUtils.getStackTrace(e)});
          throw ex;
        }
        
        // Unless otherwise specified (mediations, PubSub bridge and MQLink), clear out
        // any fingerprints already in the message to prevent accidental 'loop' detection
        // occuring.
        if(_clearPubSubFingerprints)
        {
          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
            SibTr.debug(this, tc, "clearFingerprints");
          msg.clearFingerprints();
        }
  
        // On entry to Message Processor trace the message content
        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
          SibTr.debug(this, tc, "verboseMsg IN : " + msg.toVerboseString());
  
        // Set the RFH2 allowed flag (for messages destined for MQ)
        if (_destination.isAlias() ||
            _destination.isForeign() ||
            _destination.isForeignBus())
        {
          setRFH2Allowed(msg, _destination);
        }
  
        // Set the message put time if required
        if (msg.getTimestamp().longValue() == SIMPConstants.TIMESTAMP_REQUIRED)
        {
          msg.setTimestamp(System.currentTimeMillis());
        }
  
        // If security is enabled then we'll do the discriminator access check
        if(_conn.isBusSecure())
        {
          // If pubsub, then we need to check access to the discriminator
          // And if the discriminator access was checked at create time, then
          // we need to set the discriminator into the message.
          if(_checkDiscriminatorAccessAtSend)
          {
            // set the discriminator into the security context
            _securityContext.setDiscriminator(msg.getDiscriminator());
            if(!_destination.
                checkDiscriminatorAccess(_securityContext,
                                         OperationType.SEND))
            {
              if (TraceComponent.isAnyTracingEnabled() && CoreSPIProducerSession.tc.isEntryEnabled())
                SibTr.exit(CoreSPIProducerSession.tc, "send", "not authorized to produce to this destination's discriminator");
  
              // Write an audit record if access is denied
              SibTr.audit(tc, nls_cwsik.getFormattedMessage(
                "DELIVERY_ERROR_SIRC_20", // USER_NOT_AUTH_SEND_ERROR_CWSIP0308
                new Object[] { _destination.getName(),
                               msg.getDiscriminator(),
                               _conn.getResolvedUserid() },
                null));
  
              // Thrown if user denied access to destination
              SIMPNotAuthorizedException e = new SIMPNotAuthorizedException(
                nls_cwsik.getFormattedMessage(
                  "DELIVERY_ERROR_SIRC_20", // USER_NOT_AUTH_SEND_ERROR_CWSIP0308
                new Object[] { _destination.getName(),
                               msg.getDiscriminator(),
                               _conn.getResolvedUserid() },
                null));
  
              e.setExceptionReason(SIRCConstants.SIRC0020_USER_NOT_AUTH_SEND_ERROR);
              e.setExceptionInserts(new String[] { _destination.getName(),
                                                    msg.getDiscriminator(),
                                                    _conn.getResolvedUserid() });
              throw e;
            }
          }
          else // Access was checked at session creation time
          {
            // set the stored discriminator into the message
            msg.setDiscriminator(_discriminatorAtCreate);
          }
        }
  
        // Set the userid associated with the connection into the message
        // unless the sender has alternate user privilege - in which case
        // the alternate userid will be set into the message
        if(_securityContext != null &&
           _securityContext.isAlternateUserBased())
        {
          // Set the alternate user into the message
          if(!_keepSecurityUserid)
          {
            _messageProcessor.
              getAccessChecker().
              setSecurityIDInMessage(_securityContext.getAlternateUser(),msg);
          }
        }
        else
        {
          // Set the userid associated with the connection into the message
          if(!_keepSecurityUserid)
          {
            _messageProcessor.
              getAccessChecker().
              setSecurityIDInMessage(_conn.getSecuritySubject(),msg);
          }
        }
  
    
       
      
        //Create a message item.  If the message has come from a mediation it
        //has a message wait time in it from its time before the mediation
        //and this must be maintained, otherwise 0 can be assumed and this
        //saves having to read the waittime from the JsMessage, which is
        //fairly expensive to do performance wise.
        MessageItem item = null;
  
  
        item = new MessageItem(msg, 0L);
  
        // Mark this message to indicate if local queue points are preferred over others
        item.setPreferLocal(_preferLocal);
  
        if(_destination.isPubSub())
        {
          //defect 278038:
          //Set the connectionUuid to this connection (for durable subs noLocal matching)
          //The field will be set in the jsMsg when the msgitem is persisted or
          //when the jsMsg is sent over the wire.
          item.setProducerConnectionUuid(_conn.getUuid());
        }
        item.setProducerSeed(++_seed);
  
        //-----199744------------------------
        //If no message priority has been set in thes message, the default is taken
        //from the destination.  This cannot be the case for JMS messages, as JMS
        //always sets a default of 4 itself, however for non JMS messages it does
        //have a use.
        if (item.getPriority() == -1)
        {
          item.setPriority(_destination.getDefaultPriority());
        }
  
        if (!_destination.isOverrideOfQOSByProducerAllowed())
        {
          item.setReliability(_destination.getDefaultReliability());
        }
  
          // Indicate that this message requires a new SystemId
          item.setRequiresNewId(true);
  
        TransactionCommon transaction = null;
  
        if (tranImpl != null)
        {
          transaction = (TransactionCommon) tranImpl;
        }
        else
        {
          transaction = _autoCommitTransaction;
        }
  
        //Inidcates whether the send was a sucess, used for the rm unblock call
        boolean sucessful = false;
        Object rmCallBackObject = null;
  
        try
        {
  
          if (TraceComponent.isAnyTracingEnabled() && UserTrace.tc_mt.isDebugEnabled())
            traceSend(item, tranImpl);
  
          // We need to know if the FRP in the message came from an app or a
          // destination's FRP. As this is the point of entry from an app it's
          // the best place to look.
          boolean msgFRP = false;
          if(!msg.isForwardRoutingPathEmpty())
            msgFRP = true;
  
          _inputHandler.handleProducerMessage(item,
                                      transaction,
                                      _address,
                                      this, // If mediated, don't use us as context across messages
                                      msgFRP);
  
          sucessful = true;
        }
        catch(SIMPNoLocalisationsException e)
        {
          // No FFDC code needed
  
          // We can't find a suitable localisation.
          // Although a queue must have at least one localisation this is
          // possible if the sender restricted the potential localisations
          // using a fixed ME or a scoping alias (to an out-of-date set of
          // localisation)
        
      	
          
          if (TraceComponent.isAnyTracingEnabled() && CoreSPIProducerSession.tc.isEntryEnabled())
            SibTr.exit(CoreSPIProducerSession.tc, "send", "SINotPossibleInCurrentConfigurationException");
  
          SIMPNotPossibleInCurrentConfigurationException ee =
            new SIMPNotPossibleInCurrentConfigurationException(e);
          ee.setExceptionReason(SIRCConstants.SIRC0026_NO_LOCALISATIONS_FOUND_ERROR);
          ee.setExceptionInserts(new String[] { _destination.getName() });
          throw ee;
        }
       
      }//end sync
  
      if (TraceComponent.isAnyTracingEnabled() && CoreSPIProducerSession.tc.isEntryEnabled())
        SibTr.exit(CoreSPIProducerSession.tc, "send");
    }