Package org.objectweb.celtix.bus.ws.rm

Source Code of org.objectweb.celtix.bus.ws.rm.SourceSequence

package org.objectweb.celtix.bus.ws.rm;

import java.math.BigInteger;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;

import org.objectweb.celtix.bus.configuration.wsrm.SequenceTerminationPolicyType;
import org.objectweb.celtix.bus.ws.addressing.ContextUtils;
import org.objectweb.celtix.common.logging.LogUtils;
import org.objectweb.celtix.ws.rm.Expires;
import org.objectweb.celtix.ws.rm.Identifier;
import org.objectweb.celtix.ws.rm.SequenceAcknowledgement;
import org.objectweb.celtix.ws.rm.SequenceAcknowledgement.AcknowledgementRange;
import org.objectweb.celtix.ws.rm.persistence.RMSourceSequence;

public class SourceSequence extends AbstractSequenceImpl implements RMSourceSequence {

    public static final Duration PT0S;
    private static final Logger LOG = LogUtils.getL7dLogger(SourceSequence.class);
   
    private SequenceAcknowledgement acked;
   
    private Date expires;
    private RMSource source;
    private BigInteger currentMessageNumber;
    private boolean lastMessage;
    private Identifier offeringId;
    private org.objectweb.celtix.ws.addressing.EndpointReferenceType target;
   
    static {
        Duration pt0s = null;
        try {
            DatatypeFactory df = DatatypeFactory.newInstance();
            pt0s = df.newDuration("PT0S");
        } catch (DatatypeConfigurationException ex) {
            LOG.log(Level.INFO, "Could not create Duration object.", ex);
        }
        PT0S = pt0s;
    }
   
    public SourceSequence(Identifier i) {
        this(i, null, null);
    }
   
    public SourceSequence(Identifier i, Date e, Identifier oi) {
        this(i, e, oi, BigInteger.ZERO, false);
    }
  
   
    public SourceSequence(Identifier i, Date e, Identifier oi, BigInteger cmn, boolean lm) {
        super(i);
        expires = e;

        offeringId = oi;

        currentMessageNumber = cmn;
        lastMessage = lm;
        acked = RMUtils.getWSRMFactory().createSequenceAcknowledgement();
        acked.setIdentifier(id);
    }
   
    // begin RMSourceSequence interface
   
    public BigInteger getCurrentMessageNr() {
        return currentMessageNumber;
    }

    /**
     * @return the identifier of the rm source
     */
    public String getEndpointIdentifier() {
        if (null != source) {
            return source.getEndpointId();
        }
        return null;
    }
   
    public Date getExpiry() {
        return expires;
    }

    public boolean isLastMessage() {
        return lastMessage;
    }

    public Identifier getOfferingSequenceIdentifier() {
        return offeringId;
    }
   
    // end RMSourceSequence interface
   
    void setSource(RMSource s) {
        source = s;
    }
   
    void setLastMessage(boolean lm) {
        lastMessage = lm;
    }
   
    /**
     * Returns true if this sequence was constructed from an offer for an inbound sequence
     * includes in the CreateSequenceRequest in response to which the sequence with
     * the specified identifier was created.
     *
     * @param id the sequence identifier
     * @return true if the sequence was constructed from an offer.
     */
    boolean offeredBy(Identifier sid) {
        return null != offeringId && offeringId.getValue().equals(sid.getValue());
    }
   
    /**
     * Returns true if the sequence is expired.
     *
     * @return true if the sequence is expired.
     */

    boolean isExpired() {
        return expires == null ? false : new Date().after(expires);
    }
   
    void setExpires(Expires ex) {
        Duration d = null;
        if (null != ex) {
            d = ex.getValue();
        }

        if (null != d && (null == PT0S || !PT0S.equals(d))) {
            Date now = new Date();
            expires = new Date(now.getTime() + ex.getValue().getTimeInMillis(now));
        }
    }
   
    /**
     * Returns the next message number and increases the message number.
     *
     * @return the next message number.
     */
    BigInteger nextMessageNumber() {
        return nextMessageNumber(null, null);
    }

    /**
     * Returns the next message number and increases the message number.
     * The parameters, if not null, indicate that this message is being sent as a response
     * to the message with the specified message number in the sequence specified by the
     * by the identifier, and are used to decide if this message should be the last in
     * this sequence.
     *
     * @return the next message number.
     */
    BigInteger nextMessageNumber(Identifier inSeqId, BigInteger inMsgNumber) {

        assert !lastMessage;
       
        BigInteger result = null;
        synchronized (this) {
            currentMessageNumber = currentMessageNumber.add(BigInteger.ONE);
            checkLastMessage(inSeqId, inMsgNumber);
            result = currentMessageNumber;
        }
        return result;
    }
   
    void nextAndLastMessageNumber() {
        assert !lastMessage;
       
        synchronized (this) {
            currentMessageNumber = currentMessageNumber.add(BigInteger.ONE);
            lastMessage = true;
        }
    }
   
    /**
     * Used by the RM source to cache received acknowledgements for this
     * sequence.
     *
     * @param acknowledgement an acknowledgement for this sequence
     */
    void setAcknowledged(SequenceAcknowledgement acknowledgement) {       
        acked = acknowledgement;     
    }
   
   
    SequenceAcknowledgement getAcknowledgement() {
        return acked;
    }
   
    /**
     * Checks if the message with the given number has been acknowledged.
     *
     * @param m the message number
     * @return true of the message with the given number has been acknowledged.
     */
    boolean isAcknowledged(BigInteger m) {
        for (AcknowledgementRange r : acked.getAcknowledgementRange()) {
            if (m.subtract(r.getLower()).signum() >= 0 && r.getUpper().subtract(m).signum() >= 0) {
                return true;
            }
        }
        return false;
    }
   
    /**
     * Returns true if a last message had been sent for this sequence and if all
     * messages for this sequence have been acknowledged.
     *
     * @return true if all messages have been acknowledged.
     */
    boolean allAcknowledged() {
        if (!lastMessage) {
            return false;
        }

        if (acked.getAcknowledgementRange().size() == 1) {        
            AcknowledgementRange r = acked.getAcknowledgementRange().get(0);
            return r.getLower().equals(BigInteger.ONE) && r.getUpper().equals(currentMessageNumber);
        }
        return false;
    }
   
    /**
     * The target for the sequence is the first non-anonymous address that
     * a message is sent to as part of this sequence. It is subsequently used
     * for as the target of out-of-band protocol messages related to that
     * sequence that originate from the sequnce source (i.e. TerminateSequence
     * and LastMessage, but not AckRequested or SequenceAcknowledgement as these
     * are orignate from the sequence destination).
     *
     * @param to
     */
    synchronized void setTarget(org.objectweb.celtix.ws.addressing.EndpointReferenceType to) {
        if (target == null && !ContextUtils.isGenericAddress(to)) {
            target = to;
        }
    }
   
    synchronized org.objectweb.celtix.ws.addressing.EndpointReferenceType getTarget() {
        return target;
    }
  
    /**
     * Checks if the current message should be the last message in this sequence
     * and if so sets the lastMessageNumber property.
     */
    private void checkLastMessage(Identifier inSeqId, BigInteger inMsgNumber) {

        assert null != source;
       
        // check if this is a response to a message that was is the last message in the sequence
        // that included this sequence as an offer
       
        if (null != inSeqId && null != inMsgNumber) {
            DestinationSequence inSeq = source.getHandler().getDestination().getSequence(inSeqId);
            if (null != inSeq && offeredBy(inSeqId) && inMsgNumber.equals(inSeq.getLastMessageNr())) {
                lastMessage = true;    
            }
        }
       
        if (!lastMessage) {
            SequenceTerminationPolicyType stp = source.getSequenceTerminationPolicy();
            assert null != stp;

            if ((!stp.getMaxLength().equals(BigInteger.ZERO) && stp.getMaxLength()
                .compareTo(currentMessageNumber) <= 0)
                || (stp.getMaxRanges() > 0 && acked.getAcknowledgementRange().size() >= stp.getMaxRanges())
                || (stp.getMaxUnacknowledged() > 0 && source.getRetransmissionQueue()
                    .countUnacknowledged(this) >= stp.getMaxUnacknowledged())) {
                lastMessage = true;
            }
        }
       
        if (LOG.isLoggable(Level.FINE) && lastMessage) {
            LOG.fine(currentMessageNumber + " should be the last message in this sequence.");
        }
    }

}
TOP

Related Classes of org.objectweb.celtix.bus.ws.rm.SourceSequence

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.