/*
* 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 net.jini.jeri;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import net.jini.core.constraint.ConstraintAlternatives;
import net.jini.core.constraint.Integrity;
import net.jini.core.constraint.InvocationConstraints;
/**
* Represents a request that is being sent and the corresponding
* response received in reply.
*
* <p>An <code>OutboundRequest</code> can be used to write out the
* contents of the request and to read in the response.
*
* <p>The communication protocol used by the implementation of this
* interface must guarantee that for each instance of this interface,
* any request data must only be delivered to the recipient (in the
* form of an <code>InboundRequest</code> passed to {@link
* RequestDispatcher#dispatch RequestDispatcher.dispatch}) <i>at most
* once</i>. The {@link #getDeliveryStatus getDeliveryStatus} method
* can be used to determine whether or not at least partial delivery
* of the request might have occurred.
*
* <p>When finished using an <code>OutboundRequest</code>, in order to
* allow the implementation to free resources associated with the
* request, users should either invoke <code>close</code> on the
* streams returned by the <code>getRequestOutputStream</code> and
* <code>getResponseInputStream</code> methods, or invoke the
* <code>abort</code> method.
*
* @author Sun Microsystems, Inc.
* @see InboundRequest
* @since 2.0
**/
public interface OutboundRequest {
/**
* Populates the supplied collection with context information
* representing this request.
*
* @param context the context collection to populate
*
* @throws NullPointerException if <code>context</code> is
* <code>null</code>
*
* @throws UnsupportedOperationException if <code>context</code>
* is unmodifiable and if any elements need to be added
**/
void populateContext(Collection context);
/**
* Returns the requirements that must be at least partially
* implemented by higher layers in order to fully satisfy the
* requirements for this request. This method may also return
* preferences that must be at least partially implemented by
* higher layers in order to fully satisfy some of the preferences
* for this request.
*
* <p>For any given constraint, there must be a clear delineation
* of which aspects (if any) must be implemented by the transport
* layer. This method must not return a constraint (as a
* requirement or a preference, directly or as an element of
* another constraint) unless this request implements all of those
* aspects. Also, this method must not return a constraint for
* which all aspects must be implemented by the transport layer.
* Most of the constraints in the {@link net.jini.core.constraint}
* package must be fully implemented by the transport layer and
* thus must not be returned by this method; the one exception is
* {@link Integrity}, for which the transport layer is responsible
* for the data integrity aspect and higher layers are responsible
* for the code integrity aspect.
*
* <p>For any {@link ConstraintAlternatives} in the constraints
* for this request, this method should only return a
* corresponding constraint if all of the alternatives satisfied
* by this request need to be at least partially implemented by
* higher layers in order to be fully satisfied.
*
* @return the constraints for this request that must be partially
* or fully implemented by higher layers
**/
InvocationConstraints getUnfulfilledConstraints();
/**
* Returns an <code>OutputStream</code> to write the request data
* to. The sequence of bytes written to the returned stream will
* be the sequence of bytes sent as the body of this request.
*
* <p>After the entirety of the request has been written to the
* stream, the stream's <code>close</code> method must be invoked
* to ensure complete delivery of the request. It is possible
* that none of the data written to the returned stream will be
* delivered before <code>close</code> has been invoked (even if
* the stream's <code>flush</code> method had been invoked at any
* time). Note, however, that some or all of the data written to
* the stream may be delivered to (and processed by) the recipient
* before the stream's <code>close</code> method has been invoked.
*
* <p>After the stream's <code>close</code> method has been
* invoked, no more data may be written to the stream; writes
* subsequent to a <code>close</code> invocation will fail with an
* <code>IOException</code>.
*
* <p>If this method is invoked more than once, it will always
* return the identical stream object that it returned the first
* time (although the stream may be in a different state than it
* was upon return from the first invocation).
*
* @return the output stream to write request data to
**/
OutputStream getRequestOutputStream();
/**
* Returns an <code>InputStream</code> to read the response data
* from. The sequence of bytes produced by reading from the
* returned stream will be the sequence of bytes received as the
* response data. When the entirety of the response has been
* successfully read, reading from the stream will indicate an
* EOF.
*
* <p>Users of an <code>OutboundRequest</code> must not expect any
* data to be available from the returned stream before the
* <code>close</code> method has been invoked on the stream
* returned by <code>getRequestOutputStream</code>; in other
* words, the user's request/response protocol must not require
* any part of a request to be a function of any part of its
* response.
*
* <p>It is possible, however, for data to be available from the
* returned stream before the <code>close</code> method has been
* invoked on, or even before the entirety of the request has been
* written to, the stream returned by
* <code>getRequestOutputStream</code>. Because such an early
* response might indicate, depending on the user's
* request/response protocol, that the recipient will not consider
* the entirety of the request, perhaps due to an error or other
* abnormal condition, the user may wish to process it
* expeditiously, rather than continuing to write the remainder of
* the request.
*
* <p>Invoking the <code>close</code> method of the returned
* stream will cause any subsequent read operations on the stream
* to fail with an <code>IOException</code>, although it will not
* terminate this request as a whole; in particular, the request
* may still be subsequently written to the stream returned by the
* <code>getRequestOutputStream</code> method. After
* <code>close</code> has been invoked on both the returned stream
* and the stream returned by <code>getRequestOutputStream</code>,
* the implementation may free all resources associated with this
* request.
*
* <p>If this method is invoked more than once, it will always
* return the identical stream object that it returned the first
* time (although the stream may be in a different state than it
* was upon return from the first invocation).
*
* @return the input stream to read response data from
**/
InputStream getResponseInputStream();
/**
* Returns <code>false</code> if it is guaranteed that no data
* written for this request has been processed by the recipient.
* This guarantee remains valid until any subsequent I/O operation
* has been attempted on this request.
*
* If this method returns <code>true</code>, then data written for
* this request may have been at least partially processed by the
* recipient (the <code>RequestDispatcher</code> receiving the
* corresponding <code>InboundRequest</code>).
*
* @return <code>false</code> if data written for this request has
* definitely not been processed by the recipient, and
* <code>true</code> if data written for this request may have
* been at least partially processed by the recipient
**/
boolean getDeliveryStatus();
/**
* Terminates this request, freeing all associated resources.
*
* <p>This method may be invoked at any stage of the processing of
* the request.
*
* <p>After this method has been invoked, I/O operations on the
* streams returned by the <code>getRequestOutputStream</code> and
* <code>getResponseInputStream</code> methods will fail with an
* <code>IOException</code>, except some operations that may
* succeed because they only affect data in local I/O buffers.
*
* <p>If this method is invoked before the <code>close</code>
* method has been invoked on the stream returned by
* <code>getRequestOutputStream</code>, there is no guarantee that
* any or none of the data written to the stream so far will be
* delivered; the implication of such an invocation of this method
* is that the user is no longer interested in the successful
* delivery of the request.
**/
void abort();
}