/* (non-Javadoc)
@see com.ibm.ws.sib.msgstore.deliverydelay.DeliveryDelayable#handleInvalidDeliveryDelayable(com.ibm.ws.sib.msgstore.MessageStoreConstants.MAXIMUM_ALLOWED_DELIVERY_DELAY_ACTION)
341077
@Override
    public boolean handleInvalidDeliveryDelayable(MaximumAllowedDeliveryDelayAction action) 
    	throws MessageStoreException, SIException {
    	final String methodName = "handleInvalidDeliveryDelayable";
    	if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
             SibTr.entry(this, tc, methodName, "action=" + action);
    	
    	boolean unlocked = false;
    	if (_tuple.getDeliveryDelayTimeIsSuspect()) {
    		try {
    			// getItem() will pull the whole item into storage, so by now we should be sure we are actually going to do something.
    			AbstractItem abstractItem = getItem();
    			if (abstractItem != null) {
    				abstractItem.handleInvalidDeliveryDelayable(action);
    				switch(action) {
    				case unlock:// No break;
    				case exception:
    					LocalTransaction transaction = getMessageStore().getTransactionFactory().createLocalTransaction();
    					// Tell the DeliveryDelayable to unlock. If it returns true, then remove it from the DeliveryDelay index on return.
    					unlocked = deliveryDelayableUnlock((PersistentTransaction) transaction, AbstractItem.DELIVERY_DELAY_LOCK_ID);
    					transaction.commit();
    					break;

    				case warn:// No break;
    				default:
    					break;
    				} 	
    			}
    		} catch (MessageStoreException | SIException exception) {
    			SibTr.exit(this, tc, methodName, exception);
    			throw exception;
    		}
    	}

    	
    	if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
             SibTr.exit(this, tc, methodName, unlocked);
    	return unlocked;
    }
905601
private void validateDeliveryDelayTime(long deliveryDelayTime) throws JMSException {
        if ((deliveryDelayTime < 0) || (deliveryDelayTime > MfpConstants.MAX_DELIVERY_DELAY)) {
            throw (JMSException) JmsErrorUtils.newThrowable(
                                                            JMSException.class,
                                                            "INVALID_VALUE_CWSIA0068",
                                                            new Object[] { "deliveryDelay", "" + deliveryDelayTime },
                                                            tc
                            );
        }

    }
882618
@Override
    public void deliverExpressMessage(MessageItem msgItem,
                                      ExpressTargetStream expressTargetStream)

                    throws SIIncorrectCallException, SIResourceException
    {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.entry(tc, "deliverExpressMessage", new Object[] { msgItem });

        //Create transaction
        LocalTransaction siTran = _txManager.createLocalTransaction(false);

        try
        {
            long endTick = msgItem.getMessage().getGuaranteedValueValueTick();

            JsDestinationAddress routingDestinationAddr =
                            msgItem.getMessage().getRoutingDestination();
            if (routingDestinationAddr != null)
            {
                DestinationHandler routingDestination = null;
                try
                {
                    routingDestination =
                                    _destinationManager.getDestination(routingDestinationAddr, false, true);

                    if (_isLink)
                    {
                        LinkHandler link = (LinkHandler) _destination;

                        // If this is coming in off a link then use the link's configuration
                        // to determine if any local message points should be preferred
                        msgItem.setPreferLocal(link.preferLocalTargetQueuePoint());

                        String linkInboundUserid = ((LinkHandler) _destination).getInboundUserid();
                        if (linkInboundUserid != null)
                        {
                            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                                SibTr.debug(tc, "Set link inbound userid: " + linkInboundUserid + ", into message");
                            // Call SIB.security (ultimately) to set inbounduserid into msg
                            _messageProcessor.getAccessChecker().setSecurityIDInMessage(
                                                                                        linkInboundUserid,
                                                                                        msgItem.getMessage());
                        }
                    }
                    // If it's come from another ME in the bus then they're sending it
                    // to this message point because they want to so we prefer the local one.
                    // This allows the mesasge to be re-routed if absolutely necessary.
                    else
                        msgItem.setPreferLocal(true);

                    // Call the handler to deal with the message - passing null as the producer
                    // session id.
                    ProducerInputHandler inputHandler =
                                    (ProducerInputHandler) routingDestination.getInputHandler();

                    inputHandler.handleMessage(msgItem,
                                               siTran,
                                               _messageProcessor.getMessagingEngineUuid());

                } catch (SIException e)
                {
                    // No FFDC code needed

                    if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                    {
                        SibTr.exception(tc, e);
                        SibTr.debug(tc, "Discarding the express message as it could not be from the targetStreamManager");
                    }
                }
            }
            else
            {
                ConsumerDispatcher consumerDispatcher;

                consumerDispatcher = (ConsumerDispatcher) _destination.getLocalPtoPConsumerManager();
                consumerDispatcher.put(msgItem, siTran, null, false);
            }

            // Update the completedPrefix on the stream
            // This will put all ticks before this point into Completed state
            expressTargetStream.setCompletedPrefix(endTick);

            siTran.commit();
        } catch (SIIncorrectCallException e)
        {
            // No FFDC code needed
            handleRollback(siTran);

            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                SibTr.exit(tc, "deliverExpressMessage", e);

            throw e;
        } catch (SIResourceException e)
        {
            // No FFDC code needed
            handleRollback(siTran);

            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                SibTr.exit(tc, "deliverExpressMessage", e);

            throw e;
        } catch (RuntimeException e)
        {
            // FFDC
            FFDCFilter.processException(
                                        e,
                                        "com.ibm.ws.sib.processor.impl.PtoPInputHandler.deliverExpressMessage",
                                        "1:2840:1.323",
                                        this);

            handleRollback(siTran);

            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            {
                SibTr.exception(tc, e);
                SibTr.exit(tc, "deliverExpressMessage", e);
            }

            throw e;
        }

        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.exit(tc, "deliverExpressMessage");
    }
819923
@Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        List<String> emailAddresses = EmailAddressesParser.parse(value);
        List<String> badAddresses = null;
        for (String ea : emailAddresses) {
            if (!EMAIL_VALIDATOR.isValid(ea, null)) {
                if (badAddresses == null) {
                    badAddresses = new LinkedList<String>();
                }

                badAddresses.add(ea);
            }
        }

        if (badAddresses != null) {
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate(MessageFormat.format(constraintAnnotation.message(),
                                                                              StringUtils.join(badAddresses, ", ")))
                   .addConstraintViolation();
        }
        return (badAddresses == null);
    }
304732
public void setDeliveryDelay(long deliveryDelay) {
        if (deliveryDelay < 0 || deliveryDelay > MAXIMUM_DELIVERY_DELAY_MILLISECONDS) {
            throw new IllegalArgumentException("Delivery delay must be non-negative and at most 15 minutes: " + deliveryDelay);
        }
        if (deliveryDelay % 1000 != 0) {
            throw new IllegalArgumentException("Delivery delay must be a multiple of 1000: " + deliveryDelay);
        }
        this.deliveryDelaySeconds = (int)(deliveryDelay / 1000);
    }
284796
@Override
    public boolean validateAction(String action) {
        boolean result = false;
        if (action.equals(MessagingSecurityConstants.OPERATION_TYPE_SEND) ||
            action.equals(MessagingSecurityConstants.OPERATION_TYPE_RECEIVE)) {
            result = true;
        }
        return result;
    }
39386
@Override
    public int checkAbleToSend()
    {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.entry(tc, "checkAbleToSend", this);

        int result = DestinationHandler.OUTPUT_HANDLER_NOT_FOUND;

        // If both destination and queuepoint are sendAllowed then we can put the message
        // If we are a linkHandler we have no queue point so only check the destination def
        // on the other hand if this is an MQLink then we will check sendAllowed on
        // the local itemstream.
        boolean isSendAllowedOnLocalization = true;
        if (_baseDestinationHandler.isMQLink() || !_baseDestinationHandler.isLink())
            isSendAllowedOnLocalization = _pToPLocalMsgsItemStream.isSendAllowed();

        // Check if the queue point is send allowed (which can be set at the individual
        // message point level)
        if (!isSendAllowedOnLocalization)
            result = DestinationHandler.OUTPUT_HANDLER_SEND_ALLOWED_FALSE;
        else if (_pToPLocalMsgsItemStream != null)
        {
            if (!_pToPLocalMsgsItemStream.isQFull())
                result = DestinationHandler.OUTPUT_HANDLER_FOUND;
            else
                result = DestinationHandler.OUTPUT_HANDLER_ALL_HIGH_LIMIT;
        }

        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.exit(tc, "checkAbleToSend", Integer.valueOf(result));
        return result;
    }
296871
@Override
    public void deliveryDelayManagerStart() throws SevereMessageStoreException {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.entry(this, tc, "deliveryDelayManagerStart");
        _deliveryDelayManager.start(_deliveryDelayScanInterval, _messagingEngine);
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.exit(this, tc, "deliveryDelayManagerStart");
    }
1356067
protected void eventPreUnlocked(SIMPMessage msg, TransactionCommon tran)
  {
    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
      SibTr.entry(tc, "eventPreUnlocked", new Object[]{ msg, tran});
    
    if ((msg.guessRedeliveredCount() + 1) >= _baseDestHandler.getMaxFailedDeliveries())
    {
      // Override the check of the threshold from the local case because we only
      // reroute to the exception destination if we are local to the queuepoint.
      // If the threshold is reached we remove the AIMessageItem and drive the expiry
      // code - which should flow the relevant redeliveryCount back to the DME
      // in a reject.
      
      boolean tranCreated = false;
      if (tran == null)
      {
        /* Create a new transaction under which to perform the reroute */
        tran = _tranManager.createLocalTransaction(false);
        tranCreated = true;
      }
      
      // Perform a forced expiry
      ((AIMessageItem)msg).setRejectTransactionID(tran.getPersistentTranId());
      // Increment the unlockCount
      _aih.incrementUnlockCount(msg.getMessage().getGuaranteedRemoteGetValueTick());
      
      // Remove msg
      try
      {
        if (msg.isInStore())
        {
          Transaction msTran = _messageProcessor.resolveAndEnlistMsgStoreTransaction(tran);
          msg.remove(msTran, msg.getLockID());
        }
        
        if (tranCreated)
          ((LocalTransaction)tran).commit();
        
        // If successful, make sure we dont try to unlock the msg
        msg.setRedeliveryCountReached();
      }
      catch (MessageStoreException e) 
      {
        // FFDC
        FFDCFilter.processException(
          e,
          "com.ibm.ws.sib.processor.impl.RemoteConsumerDispatcher.eventPreUnlocked",
          "1:1090:1.97.2.21",
          this);

        SibTr.exception(tc, e);
        // Any exception will mean we wait until expiry for a reject
      }
      catch (SIException e)
      {
        // FFDC
        FFDCFilter.processException(
          e,
          "com.ibm.ws.sib.processor.impl.RemoteConsumerDispatcher.eventPreUnlocked",
          "1:1102:1.97.2.21",
          this);

        SibTr.exception(tc, e);
        // Any exception will mean we wait until expiry for a reject
      }      
    }
    
    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
      SibTr.entry(tc, "eventPreUnlocked");
  }
1255424
private void safeCustomDelay(PollingStrategyContext pollingStrategyContext) {
        try {
            pollingStrategy.getDelayStrategy().delayBeforeNextRetry(pollingStrategyContext);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        }
    }
506721
public SMTPClientFuture<Collection<FutureResult<Iterator<DeliveryRecipientStatus>>>> deliver(InetSocketAddress host, final SMTPDeliveryAgentConfig config, final SMTPDeliveryEnvelope... transactions) {
        if (transactions == null || transactions.length == 0) {
            throw new IllegalArgumentException("SMTPTransaction parameter must be not null and the length must be > 0");
        }

        final SMTPClientFutureImpl<Collection<FutureResult<Iterator<DeliveryRecipientStatus>>>> future = new SMTPClientFutureImpl<Collection<FutureResult<Iterator<DeliveryRecipientStatus>>>>();
        final SMTPClientFutureListenerFactory factory = createFactory();
        
        transport.connect(host, config).addListener(new ChainedSMTPClientFutureListener<SMTPResponse>() {
          

            @Override
            public void onException(SMTPClientSession session, SMTPException t) {
                initSession(session);
                super.onException(session, t);
            
            }
           
            /**
             * Init the SMTPClienSesion by adding all needed data to the attributes
             * 
             * @param session
             */
            private void initSession(SMTPClientSession session) {
                
                
                Iterator<SMTPDeliveryEnvelope> transactionIt = new ArrayIterator<SMTPDeliveryEnvelope>(transactions);
                session.setAttribute(SMTP_TRANSACTIONS_KEY, transactionIt);
                SMTPDeliveryEnvelope transaction = transactionIt.next();
                session.setAttribute(CURRENT_SMTP_TRANSACTION_KEY, transaction);
                session.setAttribute(RECIPIENTS_KEY, transaction.getRecipients().iterator());

                session.setAttribute(FUTURE_KEY, future);
                session.setAttribute(DELIVERY_STATUS_KEY, new ArrayList<DeliveryRecipientStatus>());
                session.setAttribute(DELIVERY_RESULT_LIST_KEY, new ArrayList<FutureResult<Iterator<DeliveryRecipientStatus>>>());
                session.setAttribute(SMTP_CLIENT_FUTURE_LISTENER_FACTORY, createFactory());
                session.setAttribute(SMTP_TRANSACTION_ACTIVE_KEY, false);
            }

            @Override
            protected void onResult(SMTPClientSession session, SMTPResponse result) throws SMTPException {
                initSession(session);
                FutureResult<SMTPResponse> fResult = new FutureResultImpl<SMTPResponse>(result);
                ReadySMTPClientFuture<FutureResult<SMTPResponse>> future = new ReadySMTPClientFuture<FutureResult<SMTPResponse>>(session, fResult);
                future.addListener(factory.getListener(session));                
            }
        });
        
       
        return future;
    }
1078908
private void validateDeliveryMode(int deliveryMode) throws JMSException {
        switch (deliveryMode) {
            case DeliveryMode.NON_PERSISTENT:
            case DeliveryMode.PERSISTENT:
                // OK - no problems.
                break;
            default:
                throw (JMSException) JmsErrorUtils.newThrowable(
                                                                JMSException.class,
                                                                "INVALID_VALUE_CWSIA0068",
                                                                new Object[] { "JMSDeliveryMode", "" + deliveryMode },
                                                                tc
                                );
        }
    }
132365
CompletableFuture<Boolean> handleMaxIdleExpireEntry(K key, V value, long maxIdle, boolean skipLocking) {
      return actualRemoveMaxIdleExpireEntry(key, value, maxIdle, skipLocking);
   }
223018
@Override
    public long getDeliveryDelay()
    {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.entry(this, tc, "getDeliveryDelay");
        long deliveryDelay = 0;

        try {
            deliveryDelay = getJSMessage(true).getDeliveryDelay();
            return deliveryDelay;
        } finally {
            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                SibTr.exit(this, tc, "getDeliveryDelay", deliveryDelay);

        }

    }
658019
private boolean checkReceiveAllowed() throws SISessionUnavailableException, SIResourceException
    {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.entry(tc, "checkReceiveAllowed");

        boolean allowed = _destinationAttachedTo.isReceiveAllowed();

        if (!allowed)
        {
            // Register that LCP stopped for Receive Allowed
            _stoppedForReceiveAllowed = true;

            // Stop LCP for Receive Allowed
            if (!_stopped)
            {
                internalStop();
            }
        }
        else
        {
            // Register that LCP not stopped for Receive Allowed
            _stoppedForReceiveAllowed = false;

            // Start LCP if no reason to be stopped
            if ((_stopped)
                && (!_stoppedByRequest))
            {
                internalStart(false);
            }
        }

        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.exit(tc, "checkReceiveAllowed", Boolean.valueOf(allowed));

        return allowed;
    }
1315681
private void internalHandleMessage(MessageItem msg,
                                       TransactionCommon transaction,
                                       SIBUuid8 sourceMEUuid,
                                       JsDestinationAddress inAddress,
                                       MessageProducer sender,
                                       boolean msgFRP)
                    throws SIConnectionLostException, SIRollbackException, SINotPossibleInCurrentConfigurationException,
                    SIIncorrectCallException, SIResourceException
    {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.entry(this, tc, "internalHandleMessage", new Object[] { msg,
                                                                         transaction,
                                                                         sourceMEUuid,
                                                                         inAddress,
                                                                         sender,
                                                                         msgFRP });

        if (TraceComponent.isAnyTracingEnabled() && UserTrace.tc_mt.isDebugEnabled())
            traceSend(msg);

        boolean lockedDestination = false;
        boolean forcePut = msg.isForcePut();

        // This checks the message Reliability against the destination
        // and sets the max storage strategy for temporary destinations
        super.handleMessage(msg);

        SIBUuid8 localMEUuid = _messageProcessor.getMessagingEngineUuid();

        // Remember if the original user transaction was a real one or not
        msg.setTransacted(!transaction.isAutoCommit());

        if (localMEUuid.equals(sourceMEUuid))
        {
            // The message may actually have been produced locally or it may have come
            // from a remote ME and been re-routed to this inputHandler using the
            // routingDestination.

            // First, sort out any changes to the message's reverse routing path
            updateReverseRoutingPath(msg);

            // First, sort out any changes to the message's reverse routing path
            List<SIDestinationAddress> frp = updateForwardRoutingPath(msg);

            //defect 269072: we cannot skip FRP destinations if the next
            //destination is on a foreign bus as we do not know anything
            //about it.
            boolean isPuttingToForeignBus = _destination.isForeignBus();

            if (frp != null && !isPuttingToForeignBus) // Correct foreign bus check (aliases?)??
            {
                handleFRPMessage(msg, transaction, sender, msgFRP);
            }
            else if ((frp == null) &&
                     (_destination.getDestinationType() == DestinationType.SERVICE))
            {
                //Put the message to the exception destination
                handleUndeliverableMessage(_destination
                                           , null
                                           , msg
                                           , SIRCConstants.SIRC0034_FORWARD_ROUTING_PATH_ERROR
                                           , new String[] { _destination.getName(),
                                                           _messageProcessor.getMessagingEngineName() },
                                           transaction);
            }
            // Otherwise, we process the message on this destination (or the destination
            // that this destination references - if an alias).
            else
            {
                // We have not sideways punted the message so need to perform
                // additional checks now

                //For debug purposes, tell the message which destinations its on
                if (TraceComponent.isAnyTracingEnabled() && UserTrace.tc_mt.isDebugEnabled())
                {
                    msg.setDebugName(_destination.getName());
                }

                // If the message came in from a remote bus then
                // check whether the userId is authorised to this destination
                if (msg.isFromRemoteBus() && _messageProcessor.isBusSecure())
                    checkInboundAuthorisation(msg.getMessage());

                // If possible use the sender's cached routing destination (which would
                // also include any fixed message point).
                // We can't use it if this message had an FRP already in it as the message
                // may go elsewhere. This means messages with an embedded FRP cannot be bound to a
                // single mesage point if the sender requests it

                // Will we need to set a routing destination back into the sender?
                boolean newSenderRoutingAddr = false;
                JsDestinationAddress routingAddr = null;

                // Work out if we're already bound to a single ME, or we need to
                SIBUuid8 fixedME = null;
                boolean fixToME = false;
                // If we're in the context of a sender that has specified bindToMessagePoint
                // and the message doesn't have an FRP embedded into it then we can fix to a single ME
                if ((sender != null) && sender.fixedMessagePoint() && !msgFRP)
                {
                    // Fixing on an ME doesn't make sense when sending down a link as we only have the one.
                    // In fact, if you fix to an ME you end up fixing to the target ME (the one at the
                    // other end of the link) which then cancels any attept to workload balance messages
                    // as they come of the link.
                    // TODO: If we ever support multiple links then we need to fix this so that you can
                    //       fix to a single link, rather than the target ME.
                    if (!_destination.isTargetedAtLink())
                        fixToME = true;
                }

                if (inAddress != null)
                {
                    // If the address is marked localOnly but we don't already have an
                    // ME in it we'll only use the local message point
                    // if it exists (even if it's currently unavailable).
                    // If we don't have a local one we simply ignore the option
                    // If the destination is foreign it can't possibly have a local
                    // message point.
                    if ((inAddress.getME() == null) && inAddress.isLocalOnly())
                    {
                        if (!_destination.isTargetedAtLink() && _destination.hasLocal())
                        {
                            // Burn this ME's UUID into the address
                            inAddress.setME(_messageProcessor.getMessagingEngineUuid());
                        }
                    }

                    // If the address that the sender used has an ME in it, we'll use it
                    if (inAddress.getME() != null)
                    {
                        fixedME = inAddress.getME();
                        fixToME = true;
                    }
                }

                if (msg.getMessage().isMediated())
                {

                    // The originator of the message (the app)
                    // may have bound the producer to a single message point in the hope of
                    // getting affinity across multiple messages.

                    // If this message has only been transformed rather than re-routed 
                    // then we'll have a go at maintaining the affinity on the outbound
                    // queue point. As we don't have the producer's session context we use the existence
                    // of a fixed ME in the routingAddress in the message to indicate that the sender
                    // bound the messages to a single message point.

                    // The only routing restriction we can apply reliably (i.e. across ME restarts) is to
                    // send all such messages to the local queue point if it exists (not just available).
                    JsDestinationAddress inRoutingAddress = msg.getMessage().getRoutingDestination();
                    if ((inRoutingAddress != null) && (inRoutingAddress.getME() != null))
                    {
                        if (_destination.hasLocal())
                        {
                            fixedME = _messageProcessor.getMessagingEngineUuid();
                            fixToME = true;
                        }
                    }
                }

                // If a local sender doesn't already have a routing destination for us or we
                // can't use it because some *** of an application set an FRP into the message
                // (which means we can't bind to a single ME if they ask) or the message came in
                // remotely we need to resolve a routing address.
                if (msgFRP || (sender == null) || !sender.isRoutingDestinationSet())
                {
                    // Resolve any required routing destination. This is quite likely to be null
                    // as we only need one for certain reasons (e.g. foreign destination, fixed ME
                    // scoped alias).
                    routingAddr = _destination.getRoutingDestinationAddr(inAddress,
                                                                         fixToME);

                    // If we have a fixed ME then set it into the routing address for
                    // anyone else looking at this message.
                    if (fixedME != null)
                    {
                        if ((inAddress == null) || !routingAddr.equals(inAddress))
                        {
                            // If we got this address from the destination handler we need to make a copy of it
                            // before we modify it as this is actually a reference to the cached address on the
                            // destination itself
                            routingAddr = SIMPUtils.createJsDestinationAddress(routingAddr.getDestinationName(),
                                                                               fixedME,
                                                                               routingAddr.getBusName());
                        }
                        else
                        {
                            routingAddr = inAddress; // Use the inAddress (which may be 'equal' the destination's but be a different object)
                            routingAddr.setME(fixedME);
                        }
                    }

                    // We'll set it back into the sender, if we're allowed.
                    if ((sender != null) && !msgFRP)
                        newSenderRoutingAddr = true;
                }
                // If the sender already has a routing destination set (which may be null)
                // then use it
                else if ((sender != null) && sender.isRoutingDestinationSet())
                {
                    routingAddr = sender.getRoutingDestination();

                    // Pull out any fixed ME that it has
                    if (routingAddr != null)
                    {
                        fixedME = routingAddr.getME();
                        if (fixedME != null)
                            fixToME = true;
                    }
                }

                // Now we know if we're fixed to a particular ME or not we can check for
                // a 'good' OutputHandler. We do this check now, in case we're transacted
                // and don't try the OutputHandlers until the transaction commits
                try
                {
                    checkHandlerAvailable(fixedME);
                }
                // This indicates that the queue high limit has been reached
                catch (SIMPLimitExceededException e)
                {
                    // No FFDC code needed

                    //If we are forcing put then we ignore queue high limits.
                    if (forcePut)
                    {
                        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                            SibTr.debug(tc, "Forcing msg put despite exception :" + e);
                    }
                    // We don't accept messages produced locally when we're full,
                    // we throw an exception back to the app.
                    else if (!msg.isFromRemoteME())
                    {
                        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                        {
                            SibTr.exception(tc, e);
                            SibTr.exit(tc, "internalHandleMessage", "SIMPLimitExceededException");
                        }
                        throw e;
                    }
                    //If it came from another bus then we put the message to the
                    //exception destination.
                    else if (msg.isFromRemoteBus())
                    {
                        if (msg.getReliability().compareTo(Reliability.EXPRESS_NONPERSISTENT) > 0)
                        {
                            // We have already checked at the target stream to see if there is
                            // space for this message either on its destination or on the link's
                            // exception destination.
                            // However, there is a window when either (or both) could have filled
                            // up since the check, perhaps due to local puts.
                            // We rethrow the exception, which will allow the message to be put to
                            // the link's exception destination if possible.
                            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                                SibTr.debug(tc, "Message from remote bus rethrow exception: " + e);
                            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                            {
                                SibTr.exception(tc, e);
                                SibTr.exit(tc, "internalHandleMessage", "SIMPLimitExceededException");
                            }
                            throw e;
                        }
                        else if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                            SibTr.debug(tc, "Message dropped - it was only best effort");

                        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                            SibTr.exit(tc, "internalHandleMessage");

                        return;
                    }
                    // Otherwise, this is a message from a remote ME in this bus. We let
                    // these onto the destination as they've already performed a WLM check
                    // to get here, which mean't we weren't full at the time.
                    else
                    {
                        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                            SibTr.debug(tc, "Allowing remote message on to destination :" + e);
                    }
                } catch (SIMPNotPossibleInCurrentConfigurationException e)
                {
                    // No FFDC code needed
                    // This indicates that the queue was put disabled
                    // It doesn't matter whether the message was produced remotely
                    // or locally this is a problem
                    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                    {
                        SibTr.exception(tc, e);
                        SibTr.exit(tc, "internalHandleMessage", "SIMPNotPossibleInCurrentConfigurationException");
                    }
                    throw e;
                }

                SIBUuid8 preferredME = null;
                // If the sender prefers any local ME over others then we'll
                // give it a go for them
                if (msg.preferLocal())
                {
                    if (_destination.hasLocal())
                        preferredME = _messageProcessor.getMessagingEngineUuid();
                }

                // If message was produced locally and transacted and we have not
                // decided to force it to be stored now,  we delay the store until
                // we get a callback at pre-prepare time.
                if (!(msg.isFromRemoteME())
                    && (msg.isTransacted())
                    && !(msg.isToBeStoredAtSendTime()))
                {
                    // We need to set any required routing destination into the message
                    // before we register it with the transaction. However, because we're
                    // about to loose the context of the sender (we've no guarantee that
                    // the sender will exist by the time the transaction commits) we need
                    // to make sure that if a fixed message point is still required we
                    // resolve it now.

                    // If we've decided we need to fix to a single ME but haven't yet chosen
                    // one, choose it now.
                    if (fixToME && (fixedME == null))
                    {
                        // Choose one of the available output handlers
                        OutputHandler outputHandler =
                                        _destination.choosePtoPOutputHandler(null,
                                                                             preferredME,
                                                                             !msg.isFromRemoteME(),
                                                                             forcePut,
                                                                             null);

                        //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)
                        //In some cases all we can do is put the message to the exception destination.  In others, we
                        //can throw an exception to the putting application.  From here, we throw an exception
                        //and its up to the calling class to determine how best to handle it
                        if (outputHandler == null)
                        {
                            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                                SibTr.exit(
                                           tc,
                                           "internalHandleMessage",
                                           "SIMPNoLocalisationsException");
                            SIMPNoLocalisationsException e = new SIMPNoLocalisationsException(
                                            nls_cwsik.getFormattedMessage(
                                                                          "DELIVERY_ERROR_SIRC_26", // NO_LOCALISATIONS_FOUND_ERROR_CWSIP0032
                                                                          new Object[] { _destination.getName() }, null));

                            e.setExceptionReason(SIRCConstants.SIRC0026_NO_LOCALISATIONS_FOUND_ERROR);
                            e.setExceptionInserts(new String[] { _destination.getName() });
                            throw e;
                        }

                        // Set the chosen one into the routing destination
                        if ((inAddress == null) || !routingAddr.equals(inAddress))
                        {
                            // If we got this address from the destination handler we need to make a copy of it
                            // before we modify it as this is actually a reference to the cached address on the
                            // destination itself
                            routingAddr = SIMPUtils.createJsDestinationAddress(routingAddr.getDestinationName(),
                                                                               outputHandler.getTargetMEUuid(),
                                                                               routingAddr.getBusName());
                        }
                        else
                        {
                            routingAddr = inAddress; // Use the inAddress (which may be 'equal' the destination's but be a different object)
                            routingAddr.setME(outputHandler.getTargetMEUuid());
                        }
                    }

                    // Set the routing destination into the message if it's changed
                    if ((routingAddr != null) || (msg.getMessage().getRoutingDestination() != null))
                        msg.getMessage().setRoutingDestination(routingAddr);

                    // If necessary, set a new routing destination into the sender.
                    if (newSenderRoutingAddr)
                        sender.setRoutingAddress(routingAddr);

                    // Register the message for storing at pre-prepare of the transaction.
                    registerMessage(msg, transaction); //183715.1
                }
                else
                {
                    // If COD reports required, register for the prePrepare callback
                    if (msg.getReportCOD() != null && _destination instanceof BaseDestinationHandler)
                        msg.registerMessageEventListener(MessageEvents.COD_CALLBACK, (BaseDestinationHandler) _destination);

                    // Read Lock the destination to prevent the reallocator running on the chosen localisation
                    LockManager reallocationLock = _destination.getReallocationLockManager();
                    reallocationLock.lock();
                    lockedDestination = true;

                    try
                    {
                        // 176658.3.5
                        // Now look for the best OutputHander at this time.
                        OutputHandler outputHandler =
                                        _destination.choosePtoPOutputHandler(fixedME,
                                                                             preferredME,
                                                                             (!msg.isFromRemoteME()),
                                                                             forcePut,
                                                                             null);

                        //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)
                        //In some cases all we can do is put the message to the exception destination.  In others, we
                        //can throw an exception to the putting application.  From here, we throw an exception
                        //and its up to the calling class to determine how best to handle it
                        if (outputHandler == null)
                        {
                            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                                SibTr.exit(
                                           tc,
                                           "internalHandleMessage",
                                           "SIMPNoLocalisationsException");
                            SIMPNoLocalisationsException e = new SIMPNoLocalisationsException(
                                            nls_cwsik.getFormattedMessage(
                                                                          "DELIVERY_ERROR_SIRC_26", // NO_LOCALISATIONS_FOUND_ERROR_CWSIP0032
                                                                          new Object[] { _destination.getName() }, null));

                            e.setExceptionReason(SIRCConstants.SIRC0026_NO_LOCALISATIONS_FOUND_ERROR);
                            e.setExceptionInserts(new String[] { _destination.getName() });
                            throw e;
                        }

                        // If the sender wants all future message to go to the same message
                        // point we fix the message point to be this one for all future requests
                        // (unless it already had it set or this message had an FRP from the message)
                        if (fixToME && (fixedME == null))
                        {
                            // We need to set this chosen ME into the routing destination
                            // as we don't already have it.
                            if ((inAddress == null) || !routingAddr.equals(inAddress))
                            {
                                // If we got this address from the destination handler we need to make a copy of it
                                // before we modify it as this is actually a reference to the cached address on the
                                // destination itself
                                routingAddr = SIMPUtils.createJsDestinationAddress(routingAddr.getDestinationName(),
                                                                                   outputHandler.getTargetMEUuid(),
                                                                                   routingAddr.getBusName());
                            }
                            else
                            {
                                routingAddr = inAddress; // Use the inAddress (which may be 'equal' the destination's but be a different object)
                                routingAddr.setME(outputHandler.getTargetMEUuid());
                            }
                        }

                        // Now we set the routing destination into the sender for future use
                        // (with the fixed ME set into it if applicable)
                        if (newSenderRoutingAddr)
                            sender.setRoutingAddress(routingAddr);

                        // Now we've resolved any possible fixed ME in the routing destination
                        // we set it into the message (remember, the routing destination is still
                        // most likely to be null).
                        if ((routingAddr != null) || (msg.getMessage().getRoutingDestination() != null))
                            msg.getMessage().setRoutingDestination(routingAddr);

                        //Indicate in the message if this was a guess
                        msg.setStreamIsGuess(outputHandler.isWLMGuess());

                        boolean stored = false;

                        outputHandler.put(msg,
                                          transaction,
                                          null,
                                          stored);
                    } catch (SIMPNoLocalisationsException e)
                    {
                        //No FFDC code needed
                        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                            SibTr.exit(tc, "internalHandleMessage", e);
                        throw e;
                    } catch (SIRollbackException e)
                    {
                        // No FFDC code needed

                        SIMPRollbackException ee = new SIMPRollbackException(e.getMessage());
                        ee.setStackTrace(e.getStackTrace());
                        ee.setExceptionReason(SIRCConstants.SIRC0901_INTERNAL_MESSAGING_ERROR);
                        ee.setExceptionInserts(new String[] { "com.ibm.ws.sib.processor.impl.ProducerSessionImpl.handleMessage",
                                                             "1:804:1.323",
                                                             SIMPUtils.getStackTrace(e) });

                        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                            SibTr.exit(tc, "internalHandleMessage", ee);

                        throw ee;
                    } catch (SIConnectionLostException e)
                    {
                        // No FFDC code needed

                        SIMPConnectionLostException ee = new SIMPConnectionLostException(e.getMessage());
                        ee.setStackTrace(e.getStackTrace());
                        ee.setExceptionReason(SIRCConstants.SIRC0901_INTERNAL_MESSAGING_ERROR);
                        ee.setExceptionInserts(new String[] { "com.ibm.ws.sib.processor.impl.ProducerSessionImpl.handleMessage",
                                                             "1:820:1.323",
                                                             SIMPUtils.getStackTrace(e) });

                        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                            SibTr.exit(tc, "internalHandleMessage", ee);

                        throw ee;
                    } catch (SIResourceException e)
                    {
                        // No FFDC code needed

                        SIMPResourceException ee = new SIMPResourceException(e);

                        ee.setExceptionReason(SIRCConstants.SIRC0901_INTERNAL_MESSAGING_ERROR);
                        ee.setExceptionInserts(new String[] { "com.ibm.ws.sib.processor.impl.ProducerSessionImpl.handleMessage",
                                                             "1:836:1.323",
                                                             SIMPUtils.getStackTrace(e) });
                        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                            SibTr.exit(tc, "internalHandleMessage", ee);
                        throw ee;
                    } catch (RuntimeException e)
                    {
                        // FFDC
                        FFDCFilter.processException(
                                                    e,
                                                    "com.ibm.ws.sib.processor.impl.PtoPInputHandler.internalHandleMessage",
                                                    "1:848:1.323",
                                                    this);

                        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                        {
                            SibTr.exception(tc, e);
                        }

                        SIMPErrorException ee = new SIMPErrorException(e);

                        ee.setExceptionReason(SIRCConstants.SIRC0901_INTERNAL_MESSAGING_ERROR);
                        ee.setExceptionInserts(new String[] { "com.ibm.ws.sib.processor.impl.ProducerSessionImpl.handleMessage",
                                                             "1:860:1.323",
                                                             SIMPUtils.getStackTrace(e) });
                        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                            SibTr.exit(tc, "internalHandleMessage", ee);
                        throw ee;
                    } finally
                    {
                        if (lockedDestination == true)
                        {
                            // unlock the reallocation lock
                            reallocationLock.unlock();
                            lockedDestination = false;
                        }
                    }
                }
            }
        }
        else
        {
            // This is a message that has been received from a
            // remote ME. Call remoteToLocal put to add it to the
            // in this case and instead use the one attached to
            // target stream
            // The message will be processed in deliverOrderedMessages when
            // the stream is in order

            // We actually ignore the source cellule in this case and
            // instead use the one attached to the message itself.
            try
            {
                remoteToLocalPut(msg, sourceMEUuid);
            } catch (SIResourceException e)
            {
                // No FFDC code needed
                SIMPResourceException ee = new SIMPResourceException(e);

                ee.setExceptionReason(SIRCConstants.SIRC0901_INTERNAL_MESSAGING_ERROR);
                ee.setExceptionInserts(new String[] { "com.ibm.ws.sib.processor.impl.ProducerSessionImpl.handleMessage",
                                                     "1:900:1.323",
                                                     SIMPUtils.getStackTrace(e) });
                if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                    SibTr.exit(tc, "internalHandleMessage", ee);
                throw ee;
            }
        }

        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.exit(tc, "internalHandleMessage");

        return;
    }
307394
public void abortAdd(final PersistentTransaction transaction) throws SevereMessageStoreException
    {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.entry(this, tc, "abortAdd", transaction);

        synchronized (this)
        {
            if ((_itemLinkState == ItemLinkState.STATE_ADDING_LOCKED)
                || (_itemLinkState == ItemLinkState.STATE_ADDING_UNLOCKED))
            {
                _assertCorrectTransaction(transaction);

                MessageStoreImpl msi = getMessageStoreImpl();
                Expirer expirer = msi._getExpirer();
                long expiryTime = getTuple().getExpiryTime();
                if (null != expirer && 0 != expiryTime)
                {
                    expirer.removeExpirable(this);
                }

                // Remove from the DeliveryDelayManager as well
                DeliveryDelayManager deliveryDelayManager = msi._getDeliveryDelayManager();
                long deliveryDelayTime = getTuple().getDeliveryDelayTime();
                if (null != deliveryDelayManager && 0 != deliveryDelayTime) {
                    deliveryDelayManager.removeDeliveryDelayable(this);
                }

                // going back to 'not stored' state requires a decrement in total count
                ListStatistics stats = getParentStatistics();

                // Defect 510343.1
                stats.decrementAdding(_inMemoryItemSize);

                _lockID = NO_LOCK_ID;
                _transactionId = null;
                _itemLinkState = ItemLinkState.STATE_NOT_STORED;

                msi.unregister(this);

                // Now, pay attention. This was added under defect 290610.
                // It looks it was omitted in changes for v6.0.2 and would result
                // in rolled back additions leaking into the linked lists.
                unlink();
            }
            else
            {
                if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled())
                    SibTr.event(this, tc, "Invalid Item state: " + _itemLinkState);
                if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                    SibTr.exit(this, tc, "abortAdd");
                throw new StateException(_itemLinkState.toString());
            }
        }

        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.exit(this, tc, "abortAdd");
    }