blob: 3ac0c10ac2797dd0dbc19c5352cce99f0fa73371 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.qpid.protonj2.engine;
import org.apache.qpid.protonj2.buffer.ProtonBuffer;
import org.apache.qpid.protonj2.types.DeliveryTag;
import org.apache.qpid.protonj2.types.transport.DeliveryState;
import org.apache.qpid.protonj2.types.transport.Disposition;
import org.apache.qpid.protonj2.types.transport.Transfer;
/**
* API for an incoming Delivery.
*/
public interface IncomingDelivery {
/**
* @return the link that this {@link IncomingDelivery} is bound to.
*/
Receiver getLink();
/**
* Returns the number of bytes currently available for reading form this delivery, which may not be complete yet.
* <p>
* Note that this value will change as bytes are received, and is in general not equal to the total length of
* a delivery, except the point where {@link #isPartial()} returns false and no content has yet been received by
* the application.
*
* @return the number of bytes currently available to read from this delivery.
*/
int available();
/**
* Marks all available bytes as being claimed by the caller meaning that available byte count value can
* be returned to the session which can expand the session incoming window to allow more bytes to be
* sent from the remote peer.
* <p>
* This method is useful in the case where the {@link Session} has been configured with a small incoming
* capacity and the receiver needs to expand the session window in order to read the entire contents of
* a delivery whose payload exceeds the configured session capacity. The {@link IncomingDelivery}
* implementation will track the amount of claimed bytes and ensure that it never releases back more
* bytes to the {@link Session} than has actually been received as a whole which allows this method
* to be called with each incoming {@link Transfer} frame of a large split framed delivery.
*
* @return this {@link IncomingDelivery} instance.
*/
IncomingDelivery claimAvailableBytes();
/**
* Returns the current read buffer without copying it effectively consuming all currently available
* bytes from this delivery. If no data is available then this method returns <code>null</code>.
*
* @return the currently available read bytes for this delivery.
*/
ProtonBuffer readAll();
/**
* Reads bytes from this delivery and writes them into the destination ProtonBuffer reducing the available
* bytes by the value of the number of bytes written to the target. The number of bytes written will be the
* equal to the writable bytes of the target buffer. The write index of the target buffer will be incremented
* by the number of bytes written into it.
*
* @param buffer
* The target buffer that will be written into.
*
* @return this {@link IncomingDelivery} instance.
*
* @throws IndexOutOfBoundsException if the target buffer has more writable bytes than this delivery has readable bytes.
*/
IncomingDelivery readBytes(ProtonBuffer buffer);
/**
* Reads bytes from this delivery and writes them into the destination array starting at the given offset and
* continuing for the specified length reducing the available bytes by the value of the number of bytes written
* to the target.
*
* @param array
* The target buffer that will be written into.
* @param offset
* The offset into the given array to begin writing.
* @param length
* The number of bytes to write to the given array.
*
* @return this {@link IncomingDelivery} instance.
*
* @throws IndexOutOfBoundsException if the length is greater than this delivery has readable bytes.
*/
IncomingDelivery readBytes(byte[] array, int offset, int length);
/**
* Configures a default DeliveryState to be used if a received delivery is settled/freed
* without any disposition state having been previously applied.
*
* @param state the default delivery state
*
* @return this {@link IncomingDelivery} instance.
*/
IncomingDelivery setDefaultDeliveryState(DeliveryState state);
/**
* @return the default delivery state for this delivery
*/
DeliveryState getDefaultDeliveryState();
/**
* @return the {@link Attachments} instance that is associated with this {@link IncomingDelivery}
*/
Attachments getAttachments();
/**
* Links a given resource to this {@link IncomingDelivery}.
*
* @param resource
* The resource to link to this {@link IncomingDelivery}.
*
* @return this {@link IncomingDelivery} instance.
*/
IncomingDelivery setLinkedResource(Object resource);
/**
* @param <T> The type that the linked resource should be cast to on return.
*
* @return the user set linked resource for this {@link Endpoint} instance.
*/
<T> T getLinkedResource();
/**
* Gets the linked resource (if set) and returns it using the type information
* provided to cast the returned value.
*
* @param <T> The type to cast the linked resource to if one is set.
* @param typeClass the type's Class which is used for casting the returned value.
*
* @return the user set linked resource for this Context instance.
*
* @throws ClassCastException if the linked resource cannot be cast to the type requested.
*/
<T> T getLinkedResource(Class<T> typeClass);
/**
* @return the {@link DeliveryTag} assigned to this Delivery.
*/
DeliveryTag getTag();
/**
* @return the {@link DeliveryState} at the local side of this Delivery.
*/
DeliveryState getState();
/**
* Gets the message-format for this Delivery, representing the 32bit value using an int.
* <p>
* The default value is 0 as per the message format defined in the core AMQP 1.0 specification.
* <p>
* See the following for more details:<br>
* <a href="http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#type-transfer">
* http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#type-transfer</a><br>
* <a href="http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#type-message-format">
* http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#type-message-format</a><br>
* <a href="http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#section-message-format">
* http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#section-message-format</a><br>
* <a href="http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#definition-MESSAGE-FORMAT">
* http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#definition-MESSAGE-FORMAT</a><br>
*
* @return the message-format for this Delivery.
*/
int getMessageFormat();
/**
* Check for whether the delivery is still partial.
* <p>
* For a receiving Delivery, this means the delivery does not hold
* a complete message payload as all the content hasn't been
* received yet. Note that an {@link #isAborted() aborted} delivery
* will also be considered partial and the full payload won't
* be received.
* <p>
* For a sending Delivery, this means that the application has not marked
* the delivery as complete yet.
*
* @return true if the delivery is partial
*
* @see #isAborted()
*/
boolean isPartial();
/**
* @return true if the delivery has been aborted.
*/
boolean isAborted();
/**
* @return true if the delivery has been settled locally.
*/
boolean isSettled();
/**
* updates the state of the delivery
*
* @param state the new delivery state
*
* @return this {@link IncomingDelivery} instance.
*/
IncomingDelivery disposition(DeliveryState state);
/**
* Update the delivery with the given disposition if not locally settled
* and optionally settles the delivery if not already settled.
* <p>
* Applies the given delivery state and local settlement value to this delivery
* writing a new {@link Disposition} frame if the remote has not already settled
* the delivery. Once locally settled no additional updates to the local
* {@link DeliveryState} can be applied and if attempted an {@link IllegalStateException}
* will be thrown to indicate this is not possible.
*
* @param state
* the new delivery state
* @param settle
* if true the delivery is settled.
*
* @return this {@link IncomingDelivery} instance.
*/
IncomingDelivery disposition(DeliveryState state, boolean settle);
/**
* Settles this delivery locally, transmitting a {@link Disposition} frame to the remote
* if the remote has not already settled the delivery. Once locally settled the delivery
* will not accept any additional updates to the {@link DeliveryState} via one of the
* {@link #disposition(DeliveryState)} or {@link #disposition(DeliveryState, boolean)}
* methods.
*
* @return this {@link IncomingDelivery} instance.
*/
IncomingDelivery settle();
/**
* @return the {@link DeliveryState} at the remote side of this Delivery.
*/
DeliveryState getRemoteState();
/**
* @return true if the delivery has been settled by the remote.
*/
boolean isRemotelySettled();
/**
* Returns the total number of transfer frames that have occurred for the given {@link IncomingDelivery}.
*
* @return the number of {@link Transfer} frames that this {@link OutgoingDelivery} has initiated.
*/
int getTransferCount();
//----- Event handlers for the Incoming Delivery
/**
* Handler for incoming deliveries that is called for each incoming {@link Transfer} frame that comprises
* either one complete delivery or a chunk of a split framed {@link Transfer}. The handler should check
* that the delivery being read is partial or not and act accordingly, as partial deliveries expect additional
* updates as more frames comprising that {@link IncomingDelivery} arrive or the remote aborts the transfer.
* <p>
* This handler is useful in cases where an incoming delivery is split across many incoming {@link Transfer}
* frames either due to a large size or a small max frame size setting and the processing is handed off to some
* other resource other than the {@link Receiver} that original handling the first transfer frame. If the initial
* {@link Transfer} carries the entire delivery payload then this event handler will never be called. Once set
* this event handler receiver all updates of incoming delivery {@link Transfer} frames which would otherwise have
* been sent to the {@link Receiver#deliveryReadHandler(EventHandler)} instance.
*
* @param handler
* The handler that will be invoked when {@link Transfer} frames arrive on this receiver link.
*
* @return this {@link IncomingDelivery} instance.
*/
IncomingDelivery deliveryReadHandler(EventHandler<IncomingDelivery> handler);
/**
* Handler for aborted deliveries that is called if this delivery is aborted by the {@link Sender}.
* <p>
* This handler is an optional convenience handler that supplements the standard
* {@link #deliveryReadHandler(EventHandler)} in cases where the users wishes to break out the
* processing of inbound delivery data from abort processing. If this handler is not set the
* {@link Receiver} will call the registered {@link #deliveryAbortedHandler(EventHandler)}
* if one is set.
*
* @param handler
* The handler that will be invoked when {@link Transfer} frames arrive on this receiver link.
*
* @return this {@link IncomingDelivery} instance.
*/
IncomingDelivery deliveryAbortedHandler(EventHandler<IncomingDelivery> handler);
/**
* Handler for updates to the remote state of incoming deliveries that have previously been received.
* <p>
* Remote state updates for an {@link IncomingDelivery} can happen when the remote settles a complete
* {@link IncomingDelivery} or otherwise modifies the delivery outcome and the user needs to act on those
* changes such as a spontaneous update to the {@link DeliveryState}. If the initial {@link Transfer} of
* an incoming delivery already indicates settlement then this handler will never be called.
*
* @param handler
* The handler that will be invoked when a new remote state update for an {@link IncomingDelivery} arrives on this link.
*
* @return this {@link IncomingDelivery} instance.
*/
IncomingDelivery deliveryStateUpdatedHandler(EventHandler<IncomingDelivery> handler);
}