Package org.apache.sandesha2.util

Source Code of org.apache.sandesha2.util.AcknowledgementManager

/*
* Copyright  1999-2004 The Apache Software Foundation.
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*/

package org.apache.sandesha2.util;

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.context.OperationContextFactory;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.engine.AxisEngine;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.sandesha2.RMMsgContext;
import org.apache.sandesha2.Sandesha2Constants;
import org.apache.sandesha2.SandeshaException;
import org.apache.sandesha2.i18n.SandeshaMessageHelper;
import org.apache.sandesha2.i18n.SandeshaMessageKeys;
import org.apache.sandesha2.storage.StorageManager;
import org.apache.sandesha2.storage.Transaction;
import org.apache.sandesha2.storage.beanmanagers.SenderBeanMgr;
import org.apache.sandesha2.storage.beans.RMDBean;
import org.apache.sandesha2.storage.beans.SenderBean;

/**
* Contains logic for managing acknowledgements.
*/

public class AcknowledgementManager {

  private static Log log = LogFactory.getLog(AcknowledgementManager.class);

  /**
   * Piggybacks any available acks of the same sequence to the given
   * application message.
   *
   * @param applicationRMMsgContext
   * @throws SandeshaException
   */
  public static Transaction piggybackAcksIfPresent(RMMsgContext rmMessageContext, StorageManager storageManager, Transaction transaction)
      throws SandeshaException {
    if (log.isDebugEnabled())
      log.debug("Enter: AcknowledgementManager::piggybackAcksIfPresent");
   
    SenderBeanMgr retransmitterBeanMgr = storageManager.getSenderBeanMgr();

    // If this message is going to an anonymous address, and the inbound sequence has
    // anonymous acksTo, then we add in an ack for the inbound sequence.
    EndpointReference target = rmMessageContext.getTo();
    if(target == null || target.hasAnonymousAddress()) {
      if(target != null && SandeshaUtil.isWSRMAnonymous(target.getAddress())) {
        // Search for any sequences that have an acksTo that matches this target, and add an ack
        // for each of them.
        RMDBean findBean = new RMDBean();
        findBean.setAcksToEPR(target.getAddress());
        findBean.setTerminated(false);
        Collection rmdBeans = storageManager.getRMDBeanMgr().find(findBean);
        Iterator sequences = rmdBeans.iterator();
        while(sequences.hasNext()) {
          RMDBean sequence = (RMDBean) sequences.next();
          if (sequence.getHighestInMessageNumber() > 0) {
            if(log.isDebugEnabled()) log.debug("Piggybacking ack for sequence: " + sequence.getSequenceID());
            RMMsgCreator.addAckMessage(rmMessageContext, sequence.getSequenceID(), sequence);
          }
        }
       
      } else {
        // We have no good indicator of the identity of the destination, so the only sequence
        // we can ack is the inbound one that caused us to create this response.
        String inboundSequence = (String) rmMessageContext.getProperty(Sandesha2Constants.MessageContextProperties.INBOUND_SEQUENCE_ID);
        if(inboundSequence != null) {
          RMDBean inboundBean = SandeshaUtil.getRMDBeanFromSequenceId(storageManager, inboundSequence);
          if(inboundBean != null && !inboundBean.isTerminated()) {
            String acksTo = inboundBean.getAcksToEPR();
            EndpointReference acksToEPR = new EndpointReference(acksTo);
           
            if(acksTo == null || acksToEPR.hasAnonymousAddress()) {
              if(log.isDebugEnabled()) log.debug("Piggybacking ack for inbound sequence: " + inboundSequence);
              RMMsgCreator.addAckMessage(rmMessageContext, inboundSequence, inboundBean);
            }
          }
        }
      }
      if(log.isDebugEnabled()) log.debug("Exit: AcknowledgementManager::piggybackAcksIfPresent, anon");
      return transaction;
    }
   
    // From here on, we must be dealing with a real address. Piggyback all sequences that have an
    // acksTo that matches the To address, and that have an ackMessage queued up for sending.
    Set acked = new HashSet();
    SenderBean findBean = new SenderBean();
    findBean.setMessageType(Sandesha2Constants.MessageTypes.ACK);
    findBean.setSend(true);
    findBean.setToAddress(target.getAddress());

    Collection collection = retransmitterBeanMgr.find(findBean);
   
    if (transaction != null && transaction.isActive())
      transaction.commit();
   
    transaction = storageManager.getTransaction();
   
    Iterator it = collection.iterator();
    while (it.hasNext()) {
      SenderBean ackBean = (SenderBean) it.next();

      // Piggybacking will happen only if the end of ack interval (timeToSend) is not reached.
      long timeNow = System.currentTimeMillis();
      if (ackBean.getTimeToSend() > timeNow) {
        // Delete the beans that would have sent the ack
        retransmitterBeanMgr.delete(ackBean.getMessageID());
        storageManager.removeMessageContext(ackBean.getMessageContextRefKey());

        String sequenceId = ackBean.getSequenceID();
        if (log.isDebugEnabled()) log.debug("Piggybacking ack for sequence: " + sequenceId);

        RMDBean rmdBean = SandeshaUtil.getRMDBeanFromSequenceId(storageManager, sequenceId);
        if(rmdBean != null && !rmdBean.isTerminated()) {
          RMMsgCreator.addAckMessage(rmMessageContext, sequenceId, rmdBean);
        }
        acked.add(sequenceId);
      }
    }
   
    // As a special case, if this is a terminate sequence message then add in ack messages for
    // any sequences that have an acksTo that matches the target address. This helps to ensure
    // that request-response sequence pairs end cleanly.
    if(rmMessageContext.getMessageType() == Sandesha2Constants.MessageTypes.TERMINATE_SEQ) {
      if(log.isDebugEnabled()) log.debug("Adding extra acks, as this is a terminate");
     
      RMDBean findRMDBean = new RMDBean();
      findRMDBean.setAcksToEPR(target.getAddress());
      findRMDBean.setTerminated(false);
      Collection rmdBeans = storageManager.getRMDBeanMgr().find(findRMDBean);
      Iterator sequences = rmdBeans.iterator();
      while(sequences.hasNext()) {
        RMDBean sequence = (RMDBean) sequences.next();
        String sequenceId = sequence.getSequenceID();
       
        if(!acked.contains(sequenceId) && sequence.getHighestInMessageNumber() > 0) {
          if(log.isDebugEnabled()) log.debug("Piggybacking ack for sequence: " + sequenceId);
          RMMsgCreator.addAckMessage(rmMessageContext, sequenceId, sequence);
          acked.add(sequenceId);
        }
      }
    }
   
    if (log.isDebugEnabled())
      log.debug("Exit: AcknowledgementManager::piggybackAcksIfPresent");
    return transaction;
  }

  /**
   *
   * @param referenceRMMessage
   * @param sequencePropertyKey
   * @param sequenceId
   * @param storageManager
   * @param makeResponse Some work will be done to make the new ack message the response of the reference message.
   * @return
   * @throws AxisFault
   */
  public static RMMsgContext generateAckMessage(
     
      RMMsgContext referenceRMMessage,
      RMDBean rmdBean,
      String sequenceId,
      StorageManager storageManager,
      boolean serverSide
     
      ) throws AxisFault {
   
    if (log.isDebugEnabled())
      log.debug("Enter: AcknowledgementManager::generateAckMessage " + rmdBean);

    MessageContext referenceMsg = referenceRMMessage.getMessageContext();

    EndpointReference acksTo = new EndpointReference(rmdBean.getAcksToEPR());

    if (acksTo.getAddress() == null)
      throw new SandeshaException(SandeshaMessageHelper.getMessage(SandeshaMessageKeys.acksToStrNotSet));

    AxisOperation ackOperation = SpecSpecificConstants.getWSRMOperation(
        Sandesha2Constants.MessageTypes.ACK,
        rmdBean.getRMVersion(),
        referenceMsg.getAxisService());

    MessageContext ackMsgCtx = SandeshaUtil.createNewRelatedMessageContext(referenceRMMessage, ackOperation);
   
    ackMsgCtx.setProperty(Sandesha2Constants.APPLICATION_PROCESSING_DONE, "true");

    RMMsgContext ackRMMsgCtx = MsgInitializer.initializeMessage(ackMsgCtx);
    ackRMMsgCtx.setFlow(MessageContext.OUT_FLOW);
    ackRMMsgCtx.setRMNamespaceValue(referenceRMMessage.getRMNamespaceValue());

    ackMsgCtx.setMessageID(SandeshaUtil.getUUID());

    SOAPFactory factory = SOAPAbstractFactory.getSOAPFactory(SandeshaUtil
        .getSOAPVersion(referenceMsg.getEnvelope()));

    // Setting new envelope
    SOAPEnvelope envelope = factory.getDefaultEnvelope();

    ackMsgCtx.setEnvelope(envelope);

    ackMsgCtx.setTo(acksTo);
   
    ackMsgCtx.setServerSide(serverSide);

    // adding the SequenceAcknowledgement part.
    RMMsgCreator.addAckMessage(ackRMMsgCtx, sequenceId, rmdBean);

    if (log.isDebugEnabled())
      log.debug("Exit: AcknowledgementManager::generateAckMessage");
    return ackRMMsgCtx;
  }

 
 

  public static boolean verifySequenceCompletion(RangeString ackRanges, long lastMessageNo) {
    if (log.isDebugEnabled())
      log.debug("Enter: AcknowledgementManager::verifySequenceCompletion");

    boolean result = false;
    Range complete = new Range(1, lastMessageNo);
    if(ackRanges.isRangeCompleted(complete)) {
      result = true;
    }

    if (log.isDebugEnabled())
      log.debug("Exit: AcknowledgementManager::verifySequenceCompletion " + result);
    return result;
  }
 
  public static void addAckBeanEntry (
      RMMsgContext ackRMMsgContext,
      String sequenceId,
      long timeToSend,
      StorageManager storageManager) throws AxisFault {
    if(log.isDebugEnabled()) log.debug("Enter: AcknowledgementManager::addAckBeanEntry");

    // Write the acks into the envelope
    ackRMMsgContext.addSOAPEnvelope();
   
    MessageContext ackMsgContext = ackRMMsgContext.getMessageContext();

    SenderBeanMgr retransmitterBeanMgr = storageManager.getSenderBeanMgr();

    String key = SandeshaUtil.getUUID();

    SenderBean ackBean = new SenderBean();
    ackBean.setMessageContextRefKey(key);
    ackBean.setMessageID(ackMsgContext.getMessageID());
    ackBean.setReSend(false);
    ackBean.setSequenceID(sequenceId);
    EndpointReference to = ackMsgContext.getTo();
    if (to!=null)
      ackBean.setToAddress(to.getAddress());

    ackBean.setSend(true);
    ackMsgContext.setProperty(Sandesha2Constants.QUALIFIED_FOR_SENDING, Sandesha2Constants.VALUE_FALSE);

    ackBean.setMessageType(Sandesha2Constants.MessageTypes.ACK);

    // removing old acks.
    SenderBean findBean = new SenderBean();
    findBean.setMessageType(Sandesha2Constants.MessageTypes.ACK);
    findBean.setSend(true);
    findBean.setReSend(false);
    findBean.setSequenceID(sequenceId);
    Collection coll = retransmitterBeanMgr.find(findBean);
    Iterator it = coll.iterator();

    while(it.hasNext()) {
      SenderBean oldAckBean = (SenderBean) it.next();
      if(oldAckBean.getTimeToSend() < timeToSend)
        timeToSend = oldAckBean.getTimeToSend();

      // removing the retransmitted entry for the oldAck
      retransmitterBeanMgr.delete(oldAckBean.getMessageID());

      // removing the message store entry for the old ack
      storageManager.removeMessageContext(oldAckBean.getMessageContextRefKey());
    }

    ackBean.setTimeToSend(timeToSend);

    ackMsgContext.setProperty(Sandesha2Constants.QUALIFIED_FOR_SENDING, Sandesha2Constants.VALUE_FALSE);
   
    // passing the message through sandesha2sender
    ackMsgContext.setProperty(Sandesha2Constants.SET_SEND_TO_TRUE, Sandesha2Constants.VALUE_TRUE);
   
    SandeshaUtil.executeAndStore(ackRMMsgContext, key);

    // inserting the new ack.
    retransmitterBeanMgr.insert(ackBean);

    if(log.isDebugEnabled()) log.debug("Exit: AcknowledgementManager::addAckBeanEntry");
  }
 
  public static void sendAckNow (RMMsgContext ackRMMsgContext) throws AxisFault {
    if (log.isDebugEnabled())
      log.debug("Enter: AcknowledgementManager::sendAckNow");

    // Write the acks into the envelope
    ackRMMsgContext.addSOAPEnvelope();
   
    MessageContext ackMsgContext = ackRMMsgContext.getMessageContext();
   
    // setting CONTEXT_WRITTEN since acksto is anonymous
    if (ackRMMsgContext.getMessageContext().getOperationContext() == null) {
      // operation context will be null when doing in a GLOBAL
      // handler.
      AxisOperation op = ackMsgContext.getAxisOperation();

      OperationContext opCtx = OperationContextFactory.createOperationContext(op.getAxisSpecificMEPConstant(), op, ackRMMsgContext.getMessageContext().getServiceContext());
      ackRMMsgContext.getMessageContext().setOperationContext(opCtx);
    }

    ackRMMsgContext.getMessageContext().setServerSide(true);
   
    AxisEngine.send(ackMsgContext);
   
    if (log.isDebugEnabled())
      log.debug("Exit: AcknowledgementManager::sendAckNow");   
 
}
TOP

Related Classes of org.apache.sandesha2.util.AcknowledgementManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.