All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.xml.ws.rx.rm.runtime.sequence.Sequence Maven / Gradle / Ivy

/*
 * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0, which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package com.sun.xml.ws.rx.rm.runtime.sequence;

import com.sun.istack.NotNull;
import com.sun.istack.Nullable;
import com.sun.xml.ws.rx.rm.faults.AbstractSoapFaultException;
import com.sun.xml.ws.rx.rm.localization.LocalizationMessages;
import com.sun.xml.ws.rx.rm.runtime.ApplicationMessage;
import com.sun.xml.ws.rx.rm.runtime.delivery.DeliveryQueue;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.glassfish.gmbal.Description;
import org.glassfish.gmbal.ManagedAttribute;
import org.glassfish.gmbal.ManagedData;

/**
 *
 * @author Marek Potociar (marek.potociar at sun.com)
 */
@ManagedData
@Description("Reliable Messaging Sequence")
public interface Sequence {

    public static final long UNSPECIFIED_MESSAGE_ID = 0; // this MUST be 0 in order for AbstractSequence.createAckRanges() method to work properly
    public static final long MIN_MESSAGE_ID = 1;
    public static final long MAX_MESSAGE_ID = 9223372036854775807L;
    public static final long NO_EXPIRY = -1;

    public static enum State {
        // CREATING(10) not needed

        CREATED(15) {

            @Override
            void verifyAcceptingAcknowledgement(String sequenceId, AbstractSoapFaultException.Code code) throws AbstractSoapFaultException {
                // do nothing
            }

            @Override
            void verifyAcceptingMessageRegistration(String sequenceId, AbstractSoapFaultException.Code code) throws AbstractSoapFaultException {
                // do nothing
            }
        },
        CLOSING(20) {

            @Override
            void verifyAcceptingAcknowledgement(String sequenceId, AbstractSoapFaultException.Code code) throws AbstractSoapFaultException {
                throw new SequenceClosedException(sequenceId, LocalizationMessages.WSRM_1135_WRONG_SEQUENCE_STATE_ACKNOWLEDGEMENT_REJECTED(sequenceId, this));
            }

            @Override
            void verifyAcceptingMessageRegistration(String sequenceId, AbstractSoapFaultException.Code code) throws AbstractSoapFaultException {
                throw new SequenceClosedException(sequenceId, LocalizationMessages.WSRM_1136_WRONG_SEQUENCE_STATE_MESSAGE_REGISTRATION(sequenceId, this));
            }
        },
        CLOSED(25) {

            @Override
            void verifyAcceptingAcknowledgement(String sequenceId, AbstractSoapFaultException.Code code) throws AbstractSoapFaultException {
                throw new SequenceClosedException(sequenceId, LocalizationMessages.WSRM_1135_WRONG_SEQUENCE_STATE_ACKNOWLEDGEMENT_REJECTED(sequenceId, this));
            }

            @Override
            void verifyAcceptingMessageRegistration(String sequenceId, AbstractSoapFaultException.Code code) throws AbstractSoapFaultException {
                throw new SequenceClosedException(sequenceId, LocalizationMessages.WSRM_1136_WRONG_SEQUENCE_STATE_MESSAGE_REGISTRATION(sequenceId, this));
            }
        },
        TERMINATING(30) {

            @Override
            void verifyAcceptingAcknowledgement(String sequenceId, AbstractSoapFaultException.Code code) throws AbstractSoapFaultException {
                throw new SequenceTerminatedException(sequenceId, LocalizationMessages.WSRM_1135_WRONG_SEQUENCE_STATE_ACKNOWLEDGEMENT_REJECTED(sequenceId, this), code);
            }

            @Override
            void verifyAcceptingMessageRegistration(String sequenceId, AbstractSoapFaultException.Code code) throws AbstractSoapFaultException {
                throw new SequenceTerminatedException(sequenceId, LocalizationMessages.WSRM_1136_WRONG_SEQUENCE_STATE_MESSAGE_REGISTRATION(sequenceId, this), code);
            }
        };
        private int value;

        private State(int value) {
            this.value = value;
        }

        public int asInt() {
            return value;
        }

        public static State asState(int value) {
            for (State status : State.values()) {
                if (status.value == value) {
                    return status;
                }
            }

            return null;
        }

        abstract void verifyAcceptingMessageRegistration(String sequenceId, AbstractSoapFaultException.Code code);

        abstract void verifyAcceptingAcknowledgement(String sequenceId, AbstractSoapFaultException.Code code);
    }

    public static enum IncompleteSequenceBehavior {

        /**
         * The default value which indicates that no acknowledged messages in the Sequence
         * will be discarded.
         */
        NO_DISCARD,
        /**
         * Value indicates that the entire Sequence MUST be discarded if the
         * Sequence is closed, or terminated,  when there are one or more gaps
         * in the final SequenceAcknowledgement.
         */
        DISCARD_ENTIRE_SEQUENCE,
        /**
         * Value indicates that messages in the Sequence beyond the first gap
         * MUST be discarded when there are one or more gaps in the final SequenceAcknowledgement.
         */
        DISCARD_FOLLOWING_FIRST_GAP;

        public static IncompleteSequenceBehavior getDefault() {
            return NO_DISCARD;
        }
    }

    public static class AckRange {

        private static final Comparator COMPARATOR = new Comparator()  {

            public int compare(AckRange range1, AckRange range2) {
                if (range1.lower <= range2.lower) {
                    return -1;
                } else {
                    return 1;
                }
            }
        };

        public static void sort(@NotNull List ranges) {
            if (ranges.size() > 1) {
                Collections.sort(ranges, COMPARATOR);
            }
        }
        
        public List rangeValues() {
            List values = new ArrayList();
            for(long value = lower; value <= upper; value++) {
                values.add(value);
            }
            return values;
        }
        
        //
        public final long lower;
        public final long upper;
        //

        public AckRange(long lower, long upper) {
            this.lower = lower;
            this.upper = upper;
        }
    }

    /**
     * Returns unique identifier of the sequence
     * 
     * @return unique sequence identifier
     */
    @ManagedAttribute
    @Description("Unique sequence identifier")
    public String getId();

    /**
     * Provides information on the message number of the last message registered on this sequence
     *
     * @return message number of the last message registered on this sequence
     */
    @ManagedAttribute
    @Description("Last message identifier register on this sequence")
    public long getLastMessageNumber();

    /**
     * Registers given message with the sequence
     *
     * @param message application message to be registered
     * @param storeMessageFlag boolean flag indicating whether message should be stored until acknowledged or not
     *
     * @throws DuplicateMessageRegistrationException in case a message with such message number
     * has already been registered with the sequence
     *
     * @exception AbstractSoapFaultException in a case the sequence is closed or terminated
     */
    public void registerMessage(@NotNull ApplicationMessage message, boolean storeMessageFlag) throws DuplicateMessageRegistrationException, AbstractSoapFaultException;

    /**
     * Retrieves a message stored within the sequence under the provided {@code correlationId}
     * if avalable. May return {@code null} if no stored message under given {@code correlationId}
     * is available.
     * 

* Availability of the message depends on the message identifier acknowledgement. * Message, if stored (see {@link #registerMessage(com.sun.xml.ws.rx.rm.runtime.ApplicationMessage, boolean)} * remains available for retrieval until it is acknowledged. Once the message identifier * associated with the stored message has been acknowledged, availability of the * stored message is no longer guaranteed and stored message becomes eligible for * garbage collection (if stored in memory) or removal. *

* Note however, that message MAY still be available even after it has been acknowledged. * Thus it is NOT safe to use this method as a test of a message acknowledgement. * * @param correlationId correlation identifier of the stored {@link ApplicationMessage} * * @return the message that is stored in the sequence if available, {@code null} otherwise. */ public @Nullable ApplicationMessage retrieveMessage(@NotNull String correlationId); /** * Updates a delivery queue for this sequence with any unacknowledged messages that * should be sent and returns the delivery queue instance. Messages in the queue are * the ones currently waiting for a delivery. * * @return delivery queue with a messages waiting for a delivery on this particular sequence */ public DeliveryQueue getDeliveryQueue(); /** * Marks given message numbers with the sequence as aknowledged * * @param ranges message number ranges to be acknowledged * * @exception InvalidAcknowledgementException is generated when acked ranges contain * a SequenceAcknowledgement covering messages that have not been sent. * * @exception AbstractSoapFaultException in case the sequence is terminated */ public void acknowledgeMessageNumbers(List ranges) throws InvalidAcknowledgementException, AbstractSoapFaultException; /** * Marks given message number with the sequence as aknowledged * * @param messageNumber message number to be acknowledged * * @exception AbstractSoapFaultException in case the sequence is terminated */ public void acknowledgeMessageNumber(long messageNumber) throws AbstractSoapFaultException; /** * Determines whether a given message number is registered as * received, unacknowledged and failed over. * * @param messageNumber message number to be tested * * @return {@code true} if the message number is registered as received, unacknowledged * and failed over, {@code false} otherwise */ public boolean isFailedOver(long messageNumber); /** * Provides a collection of ranges of message numbers acknowledged with the sequence * * @return collection of ranges of message numbers registered with the sequence */ public List getAcknowledgedMessageNumbers(); /** * Is this message number acknowledged with the sequence? * @param messageNumber in a sequence * @return true if acknowledged, otherwise false */ public boolean isAcknowledged(long messageNumber); /** * The method may be called to determine whether the sequence has some unacknowledged messages or not * * @return {@code true} if the sequence has any unacknowledged message identifiers, {@code false} otherwise */ @ManagedAttribute @Description("True if the sequence has unacknowledged message identifiers") public boolean hasUnacknowledgedMessages(); /** * Provides information on the state of the message sequence * * @return current state of the message sequence */ @ManagedAttribute @Description("Runtime state of the sequence") public State getState(); /** * This method should be called to set the AckRequested flag, which indicates * a pending request for acknowledgement of all message identifiers registered * with this sequence. */ public void setAckRequestedFlag(); /** * This method should be called to clear the AckRequested flag, which indicates * that any pending requests for acknowledgement of all message identifiers registered * with this sequence were satisfied. */ public void clearAckRequestedFlag(); /** * Provides information on the actual AckRequested flag status * * @return {@code true} if the AckRequested flag is set, {@code false} otherwise */ @ManagedAttribute @Description("True if AckRequested flag set") public boolean isAckRequested(); /** * Updates information on when was the last acknowledgement request for this sequence * sent to current time. */ public void updateLastAcknowledgementRequestTime(); /** * Determines whether a standalone acnowledgement request can be scheduled or not * based on the {@link #hasUnacknowledgedMessages()} value, last acknowledgement request time * (see {@link #updateLastAcknowledgementRequestTime()}) and {@code delayPeriod} * parameter. * * Returns {@code true} if the sequence has any pending acknowledgements is set and last * acknowledgement request time is older than delay period substracted from the current time. * Returns {@code false} otherwise. * * @param delayPeriod delay period that should pass since the last acknowledgement request * before an autonomous acnowledgement request is sent. * * @return {@code true} or {@code false} depending on whether */ public boolean isStandaloneAcknowledgementRequestSchedulable(long delayPeriod); /** * Provides information on a security session to which this sequence is bound to. * * @return security token reference identifier to which this sequence is bound to. */ @ManagedAttribute @Description("The security token reference identifier to which this sequence is bound") public String getBoundSecurityTokenReferenceId(); /** * Closes the sequence. Subsequent calls to this method have no effect. *

* Once this method is called, any subsequent calls to the {@code #getNextMessageId()} method will * result in a {@link IllegalStateException} being raised. It is however still possible to accept message identifier * acknowledgements, as well as retrieve any other information on the sequence. */ public void close(); /** * Provides information on the sequence closed status. * * @return {@code true} if the sequence has been closed, {@code false} otherwise */ @ManagedAttribute @Description("True if the sequence has been closed") public boolean isClosed(); /** * Provides information on the sequence expiration status. * * @return {@code true} if the sequence has already expired, {@code false} otherwise */ @ManagedAttribute @Description("True if the sequence has expired") public boolean isExpired(); /** * Provides information on the last activity time of this sequence. Following is the * list of operations invocation of which causes an update of last activity time: *

    *
  • {@link #acknowledgeMessageNumber(long) }
  • *
  • {@link #acknowledgeMessageNumbers(java.util.List) }
  • *
  • {@link #clearAckRequestedFlag() }
  • *
  • {@link #close() }
  • *
  • {@link #registerMessage(ApplicationMessage, boolean) }
  • *
  • {@link #retrieveMessage(java.lang.String) }
  • *
  • {@link #setAckRequestedFlag() }
  • *
  • {@link #updateLastAcknowledgementRequestTime() }
  • *
* * @return last activity time on the sequence in milliseconds */ @ManagedAttribute @Description("Last activity time on the sequence in milliseconds") public long getLastActivityTime(); /** * The method is called during the sequence termination to allow sequence object to release its allocated resources */ public void preDestroy(); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy