docs: @Override
      public SIDestinationAddress checkMessagingRequired(SIDestinationAddress requestDestAddr,
                                                         SIDestinationAddress replyDestAddr,
                                                         DestinationType destinationType,
                                                         String alternateUser)
  
                      throws SIConnectionDroppedException,
                      SIConnectionUnavailableException,
                      SIErrorException,
                      SIIncorrectCallException,
                      SITemporaryDestinationNotFoundException,
                      SIResourceException,
                      SINotAuthorizedException,
                      SINotPossibleInCurrentConfigurationException
      {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              SibTr.entry(tc, "checkMessagingRequired",
                          new Object[] { requestDestAddr,
                                        replyDestAddr,
                                        alternateUser,
                                        destinationType });
  
          //Assume the bus cannot be skipped
          boolean destinationIsFastPath = false;
          boolean requestIsFastPath = false;
          boolean replyIsFastPath = true;
          boolean foreignBusFound = false;
          boolean destinationIsSendAllowed;
          List<JsDestinationAddress> rrp = new LinkedList<JsDestinationAddress>();
          SIDestinationAddress targetPort = null;
          boolean loopFound = false;
          Set<String> duplicateDestinationNames = null;
  
          // Synchronize on the close object, we don't want the connection closing
          // while we check if the destination can be fast-pathed
          synchronized (this)
          {
              // See if this connection has been closed
              checkNotClosed();
  
              //Validate the sending destination addresses is not null
              checkProducerSessionNullParameters(requestDestAddr);
  
              SecurityContext secContext = null;
              // If security is enabled then we need to set up a security context
              if (_isBusSecure)
              {
                  // Add the alternate user string to the security context
                  secContext = new SecurityContext(_subject,
                                  alternateUser,
                                  null,
                                  _messageProcessor.getAuthorisationUtils());
              }
  
              String destinationName = requestDestAddr.getDestinationName();
              String busName = requestDestAddr.getBusName();
  
              if ((busName == null) || (busName.equals(_messageProcessor.getMessagingEngineBus())))
              {
                  //Look up the named destination    
                  DestinationHandler destination = null;
                  destination = _destinationManager.getDestination(destinationName, busName, false);
  
                  // Check the destination type
                  checkDestinationType(destinationType, requestDestAddr, destination, false);
  
                  // Ensure that the destination is put enabled
                  destinationIsSendAllowed = destination.isSendAllowed();
  
                  if (!destination.isPubSub() && destination.hasLocal() && destinationIsSendAllowed)
                  {
                      PtoPLocalMsgsItemStream ptoPLocalMsgsItemStream =
                                      (PtoPLocalMsgsItemStream) destination.getQueuePoint(_messageProcessor.getMessagingEngineUuid());
  
                      destinationIsSendAllowed = ptoPLocalMsgsItemStream.isSendAllowed();
                  }
  
                  // Check authority to produce to destination
                  // If security is disabled then we'll bypass the check
                  if (_isBusSecure)
                  {
                      checkProducerAuthority(requestDestAddr,
                                             destination,
                                             destinationName,
                                             busName,
                                             secContext,
                                             false);
  
                      // Go on to check authority to consume from the reply destination.
                      // We do this up front to ensure that an SINotAuth exception can
                      // be thrown as early as possible.                       
                      if (replyDestAddr != null)
                      {
                          String replyDestinationName = replyDestAddr.getDestinationName();
                          String replyBusName = replyDestAddr.getBusName();
  
                          //Look up the reply destination    
                          DestinationHandler replyDestination =
                                          _destinationManager.getDestination(replyDestinationName,
                                                                             replyBusName,
                                                                             false);
  
                          // Check authority to produce to the reply destination.  The reply will 
                          // be produced with the same userid as the request
                          // If security is disabled then we'll bypass the check
                          checkDestinationAccess(replyDestination,
                                                 replyDestinationName,
                                                 replyBusName,
                                                 secContext);
                      }
                  }
  
                  //Set up the reverse routing path as we go along.
                  JsDestinationAddress replyDest = destination.getReplyDestination();
                  if ((replyDest != null) && (replyDestAddr != null))
                  {
                      rrp.add(replyDest);
                  }
  
                  //Now validate each entry on the administered forward routing path.
                  //If one is found that breaks the fastpath rules, then leave the
                  //loop
                  JsDestinationAddress entry = null;
                  DestinationHandler frpDestination = destination;
  
                  //Get the administered forward routing path from the named destination
                  List frp = destination.getForwardRoutingPath();
  
                  if (frp != null)
                  {
                      int frpSize = frp.size();
                      int frpCount = 0;
  
                      //Ensure there is no infinite loop in the forward routing path
                      duplicateDestinationNames = new HashSet<String>();
                      duplicateDestinationNames.add(destination.getName());
  
                      while ((!frpDestination.isPubSub()) && //not a topicspace
                             (!foreignBusFound) &&
                             (!loopFound) &&
                             (destinationIsSendAllowed) &&
                             (frpCount < frpSize)) //forward routing path
                                                   //contains entries
                      {
                          // read element from FRP
                          entry = (JsDestinationAddress) frp.get(frpCount);
                          frpCount++;
  
                          String frpName = entry.getDestinationName();
                          String frpBusName = entry.getBusName();
  
                          if ((frpBusName == null) || (frpBusName.equals(_messageProcessor.getMessagingEngineBus())))
                          {
                              //Get the named destination from the destination manager
                              frpDestination = _destinationManager.getDestination(frpName, frpBusName, false);
  
                              // If security is enabled, then we need to check authority to access
                              // the next destination
                              // Check authority to produce to destination
                              // If security is disabled then we'll bypass the check
                              if (_isBusSecure)
                              {
                                  checkDestinationAccess(frpDestination,
                                                         frpName,
                                                         frpBusName,
                                                         secContext);
                              }
  
                              //Set up the reverse routing path as we go along.
                              replyDest = frpDestination.getReplyDestination();
                              if ((replyDest != null) && (replyDestAddr != null))
                              {
                                  rrp.add(replyDest);
                              }
  
                              //If this is the last destination in the FRP, then see if this
                              //destination has a default adminstered FRP which we should now
                              //check.
                              if (frpCount == frpSize)
                              {
                                  List additionalFRP = frpDestination.getForwardRoutingPath();
                                  if (additionalFRP != null)
                                  {
                                      //Before adding an additional forward routing path, ensure it wont make us loop forever
                                      if (duplicateDestinationNames.contains(frpDestination.getName()))
                                      {
                                          loopFound = true;
                                      }
                                      else
                                      {
                                          duplicateDestinationNames.add(frpDestination.getName());
                                          frp = additionalFRP;
                                          frpSize = frp.size();
                                          frpCount = 0;
                                      }
                                  }
                              }
                          }
                          else
                          {
                              foreignBusFound = true;
                          }
                      }
                  }
  
                  //We have either succesfully checked all the destinations on the
                  //administered forward routing path, or frpDestination will be
                  //referencing the first destination that failed one of the 
                  //checks.  Determine here which is the correct response to give
                  //the caller.
                  if ((!foreignBusFound) &&
                      (!loopFound) &&
                      (destinationIsSendAllowed) &&
                      (frpDestination.hasLocal()) && //local queue-point
                      (frpDestination.getDestinationType() == DestinationType.PORT) &&
                      (!frpDestination.isPubSub())) //not a topicspace 
                  {
                      requestIsFastPath = true;
                      targetPort = JsMainAdminComponentImpl.getSIDestinationAddressFactory().createSIDestinationAddress(frpDestination.getName(), frpDestination.getBus());
                  }
  
                  //Now check if the reply message can also be fastpathed.
                  //Only worth checking if the request can be.
                  if (requestIsFastPath)
                  {
                      DestinationHandler rrpDestination = null;
  
                      while (!rrp.isEmpty())
                      {
                          // Pop off first element of RRP
                          entry = rrp.remove(0);
  
                          String rrpName = entry.getDestinationName();
                          String rrpBusName = entry.getBusName();
  
                          if ((rrpBusName != null) &&
                              (!(rrpBusName.equals(_messageProcessor.getMessagingEngineBus()))))
                          {
                              replyIsFastPath = false;
                              rrp.clear();
                          }
                          else
                          {
                              //Get the named destination from the destination manager
                              rrpDestination = _destinationManager.getDestination(rrpName, rrpBusName, false);
  
                              // If security is enabled, then we need to check authority to access
                              // the next destination
                              // Check authority to produce to destination
                              // If security is disabled then we'll bypass the check
                              if (_isBusSecure)
                              {
                                  checkDestinationAccess(rrpDestination,
                                                         rrpName,
                                                         rrpBusName,
                                                         secContext);
                              }
                          }
                      }
  
                      if (replyIsFastPath)
                      {
                          if (replyDestAddr != null)
                          {
                              //The reverse routing path was checked and is ok.  Now check the final
                              //reply destination.
  
                              destinationName = replyDestAddr.getDestinationName();
                              busName = replyDestAddr.getBusName();
  
                              if ((busName != null) &&
                                  (!(busName.equals(_messageProcessor.getMessagingEngineBus()))))
                              {
                                  replyIsFastPath = false;
                              }
                              else
                              {
                                  //Look up the named destination    
                                  destination = _destinationManager.getDestination(destinationName, busName, false);
  
                                  boolean replyDestinationHasFRP = false;
                                  List replyDestinationFRP = destination.getForwardRoutingPath();
                                  if ((replyDestinationFRP != null) &&
                                      (!(replyDestinationFRP.isEmpty())))
                                  {
                                      replyDestinationHasFRP = true;
                                  }
  
                                  //The reply destination must also have a local queue point and no Forward Routing Path
                                  if ((!(destination.hasLocal())) ||
                                      (replyDestinationHasFRP == true) ||
                                      (!(destination.isReceiveAllowed())))
                                  {
                                      replyIsFastPath = false;
                                  }
                              }
                          }
                      }
  
                      if ((requestIsFastPath) && (replyIsFastPath))
                      {
                          destinationIsFastPath = true;
                      }
                  }
              }
          }
  
          if (!destinationIsFastPath)
              targetPort = null;
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              SibTr.exit(tc, "checkMessagingRequired", targetPort);
  
          return targetPort;
      }