Package org.apache.sandesha2.msgprocessors

Source Code of org.apache.sandesha2.msgprocessors.AcknowledgementProcessor

/*
* 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.msgprocessors;

import java.util.Iterator;
import java.util.List;

import javax.xml.namespace.QName;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.wsdl.WSDLConstants;
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.polling.PollingManager;
import org.apache.sandesha2.security.SecurityManager;
import org.apache.sandesha2.security.SecurityToken;
import org.apache.sandesha2.storage.StorageManager;
import org.apache.sandesha2.storage.beanmanagers.RMDBeanMgr;
import org.apache.sandesha2.storage.beanmanagers.SenderBeanMgr;
import org.apache.sandesha2.storage.beans.RMDBean;
import org.apache.sandesha2.storage.beans.RMSBean;
import org.apache.sandesha2.storage.beans.SenderBean;
import org.apache.sandesha2.util.FaultManager;
import org.apache.sandesha2.util.Range;
import org.apache.sandesha2.util.RangeString;
import org.apache.sandesha2.util.SandeshaUtil;
import org.apache.sandesha2.util.TerminateManager;
import org.apache.sandesha2.wsrm.AcknowledgementRange;
import org.apache.sandesha2.wsrm.SequenceAcknowledgement;

/**
* Responsible for processing acknowledgement headers on incoming messages.
*/

public class AcknowledgementProcessor {

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

  /**
   * @param message
   * @throws AxisFault
   */
  public void processAckHeaders(RMMsgContext message) throws AxisFault {
    if (log.isDebugEnabled())
      log.debug("Enter: AcknowledgementProcessor::processAckHeaders");

    SOAPEnvelope envelope = message.getMessageContext().getEnvelope();
    SOAPHeader header = envelope.getHeader();
    if(header!=null)
    {
      for(int i = 0; i < Sandesha2Constants.SPEC_NS_URIS.length; i++) {
        QName headerName = new QName(Sandesha2Constants.SPEC_NS_URIS[i], Sandesha2Constants.WSRM_COMMON.SEQUENCE_ACK);
       
        Iterator acks = header.getChildrenWithName(headerName);
        while(acks.hasNext()) {
          OMElement ack = (OMElement) acks.next();
          SequenceAcknowledgement seqAck = new SequenceAcknowledgement(headerName.getNamespaceURI());
          seqAck.fromOMElement(ack);
          processAckHeader(message, ack, seqAck);
        }
      }     
    }


    if (log.isDebugEnabled())
      log.debug("Exit: AcknowledgementProcessor::processAckHeaders");
  }
 
  /**
   * @param rmMsgCtx
   * @param soapHeader
   * @param sequenceAck
   * @throws AxisFault
   */
  private void processAckHeader(RMMsgContext rmMsgCtx, OMElement soapHeader, SequenceAcknowledgement sequenceAck)
    throws AxisFault {
    if (log.isDebugEnabled())
      log.debug("Enter: AcknowledgementProcessor::processAckHeader " + soapHeader);
   
    boolean piggybackedAck = !(rmMsgCtx.getMessageType()==Sandesha2Constants.MessageTypes.ACK);
   
    MessageContext msgCtx = rmMsgCtx.getMessageContext();
    ConfigurationContext configCtx = msgCtx.getConfigurationContext();

    StorageManager storageManager = SandeshaUtil.getSandeshaStorageManager(configCtx, configCtx
        .getAxisConfiguration());

    SenderBeanMgr retransmitterMgr = storageManager.getSenderBeanMgr();

    String outSequenceId = sequenceAck.getIdentifier().getIdentifier();
    RMSBean rmsBean = SandeshaUtil.getRMSBeanFromSequenceId(storageManager, outSequenceId);

    if (outSequenceId == null || "".equals(outSequenceId)) {
      String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.outSeqIDIsNull);
      log.debug(message);
      throw new SandeshaException(message);
    }
    if (FaultManager.checkForUnknownSequence(rmMsgCtx, outSequenceId, storageManager, piggybackedAck)) {
      if (log.isDebugEnabled())
        log.debug("Exit: AcknowledgementProcessor::processAckHeader, Unknown sequence");
      return;
    }
    if (FaultManager.checkForSequenceTerminated(rmMsgCtx, outSequenceId, rmsBean, piggybackedAck)) {
      if (log.isDebugEnabled())
        log.debug("Exit: AcknowledgementProcessor::processAckHeader, Sequence terminated");
      return;
    }

    // Check that the sender of this Ack holds the correct token
    String internalSequenceId = rmsBean.getInternalSequenceID();
    if(rmsBean.getSecurityTokenData() != null) {
      SecurityManager secManager = SandeshaUtil.getSecurityManager(configCtx);
      SecurityToken token = secManager.recoverSecurityToken(rmsBean.getSecurityTokenData());
     
      secManager.checkProofOfPossession(token, soapHeader, msgCtx);
    }
   
    if(log.isDebugEnabled()) log.debug("Got Ack for RM Sequence: " + outSequenceId + ", internalSeqId: " + internalSequenceId);
    Iterator ackRangeIterator = sequenceAck.getAcknowledgementRanges().iterator();

    if (FaultManager.checkForUnknownSequence(rmMsgCtx, outSequenceId, storageManager, piggybackedAck)) {
      if (log.isDebugEnabled())
        log.debug("Exit: AcknowledgementProcessor::processAckHeader, Unknown sequence ");
      return;
    }
   
    if (FaultManager.checkForInvalidAcknowledgement(rmMsgCtx, sequenceAck, storageManager, rmsBean, piggybackedAck)) {
      if (log.isDebugEnabled())
        log.debug("Exit: AcknowledgementProcessor::processAckHeader, Invalid Ack range ");
      return;
    }
   
    String replyToAddress = rmsBean.getReplyToEPR();
    EndpointReference replyTo = new EndpointReference (replyToAddress);
    boolean anonReplyTo = replyTo.hasAnonymousAddress();
   
    String rmVersion = rmMsgCtx.getRMSpecVersion();
   
    // Compare the clientCompletedMessages with the range we just got, to work out if there
    // is any new information in this ack message
    RangeString completedMessages = rmsBean.getClientCompletedMessages();
    long numberOfNewMessagesAcked = 0;

    while(ackRangeIterator.hasNext()) {
      AcknowledgementRange ackRange = (AcknowledgementRange) ackRangeIterator.next();
      long lower = ackRange.getLowerValue();
      long upper = ackRange.getUpperValue();
      Range ackedRange = new Range(lower, upper);
      // Quick check to see if the whole range is already covered
      if(!completedMessages.isRangeCompleted(ackedRange)) {
        //we now know that this range is complete so we update it. This should aggregate the
        //ranges together and tell us which numbers are newly acked
        Range[] newRanges = completedMessages.addRange(ackedRange).getRanges();
       
        // We now take each newly acked message in turn and see if we need to update a sender bean
        for (int rangeIndex=0; rangeIndex < newRanges.length; rangeIndex++) {
          //now work on each newly acked message in this range
          for(long messageNo = newRanges[rangeIndex].lowerValue; messageNo<=newRanges[rangeIndex].upperValue; messageNo++){
           
            numberOfNewMessagesAcked++;
            SenderBean matcher = new SenderBean();
            matcher.setSequenceID(outSequenceId);
           
            matcher.setMessageNumber(messageNo);
           
            List retransmitterBeans = retransmitterMgr.find(matcher);
            if (! retransmitterBeans.isEmpty()){
              Iterator retransmitterBeansItr = retransmitterBeans.iterator();
              while (retransmitterBeansItr.hasNext()) {
                SenderBean retransmitterBean = (SenderBean) retransmitterBeansItr.next();
                if (retransmitterBean != null) {
                  // Check we haven't got an Ack for a message that hasn't been sent yet !
                  if (retransmitterBean.getSentCount() == 0) {
                    FaultManager.makeInvalidAcknowledgementFault(rmMsgCtx, sequenceAck, ackRange,
                        storageManager, piggybackedAck);
                    if (log.isDebugEnabled())
                      log.debug("Exit: AcknowledgementProcessor::processAckHeader, Invalid Ack");
                    return;
                  }
                 
                  String storageKey = retransmitterBean.getMessageContextRefKey();
                 
                  boolean syncResponseNeeded = false;
                  if (Sandesha2Constants.SPEC_VERSIONS.v1_0.equals(rmVersion) && anonReplyTo) {
                    MessageContext applicationMessage = storageManager.retrieveMessageContext(storageKey, configCtx);
                    AxisOperation operation = applicationMessage.getAxisOperation();
                    if(operation!= null) {
                      int mep = operation.getAxisSpecificMEPConstant();
                      syncResponseNeeded = (mep == WSDLConstants.MEP_CONSTANT_OUT_IN);
                    }
                  }

                  if (!syncResponseNeeded) {
                    // removing the application message from the storage.
                    retransmitterMgr.delete(retransmitterBean.getMessageID());
                    storageManager.removeMessageContext(storageKey);
                  }
                }               
              }             
            }//end of if (!retransmitterBeans.isEmpty()){

          }//end for
        }//end for
      } //end while
    }

    // updating the last activated time of the sequence.
    rmsBean.setLastActivatedTime(System.currentTimeMillis());

    //adding a MakeConnection for the response sequence if needed.
    if (rmsBean.getOfferedSequence() != null) {

      RMDBeanMgr rMDBeanMgr = storageManager.getRMDBeanMgr();
      RMDBean rMDBean = rMDBeanMgr.retrieve(outSequenceId);
     
      if (rMDBean!=null && rMDBean.isPollingMode()) {
        PollingManager manager = storageManager.getPollingManager();
        if(manager != null) manager.schedulePollingRequest(rMDBean.getSequenceID(), false);
      }
    }

    // We overwrite the previous client completed message ranges with the
    // latest view, but only if it is an update i.e. contained a new
    // ack range (which is because we do not previous acks arriving late
    // to break us)
    if (numberOfNewMessagesAcked>0) {
      rmsBean.setClientCompletedMessages(completedMessages);
    }
   
    // Update the RMSBean
    storageManager.getRMSBeanMgr().update(rmsBean);

    // Try and terminate the sequence
    if (!rmsBean.isAvoidAutoTermination())
      TerminateManager.checkAndTerminate(rmMsgCtx.getConfigurationContext(), storageManager, rmsBean);

    if (log.isDebugEnabled())
      log.debug("Exit: AcknowledgementProcessor::processAckHeader");
  }


}
TOP

Related Classes of org.apache.sandesha2.msgprocessors.AcknowledgementProcessor

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.