/* * 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.IOException; import java.util.NoSuchElementException; /** * Produces {@link OutboundRequest} instances to use for attempting to * send a particular request to a remote communication endpoint. * * <p>As long as {@link #hasNext hasNext} returns <code>true</code>, * the {@link #next next} method can be invoked to initiate an attempt * to make the request. If successful, the <code>next</code> method * returns an <code>OutboundRequest</code> to use to write the request * data and read the response. * * <p>If the request communication attempt fails, such as if the * <code>next</code> invocation throws an exception or if a subsequent * I/O operation on the returned <code>OutboundRequest</code> or its * streams throws an exception, then if <code>hasNext</code> returns * <code>true</code> again, the <code>next</code> method can be * invoked again to retry the request attempt. This process of * retrying failed request attempts can repeat as long as * <code>hasNext</code> returns <code>true</code> after the previous * failed request attempt. * * <p>Note that it is the user's responsibility to abstain from * retrying a request attempt if doing so might violate any applicable * guarantees of <i>at most once</i> execution semantics (invoking * {@link OutboundRequest#getDeliveryStatus getDeliveryStatus} on the * previous <code>OutboundRequest</code> might aid in making that * determination). * * <p>A typical <code>OutboundRequestIterator</code> is likely to * support making only one request attempt, in which case after one * invocation of <code>next</code> (successful or not), * <code>hasNext</code> will return <code>false</code>. Reasons that * an <code>OutboundRequestIterator</code> might support multiple * request attempts include: * * <ul> * * <li>if the remote endpoint implementation features multiple * communication mechanism alternatives to attempt or * * <li>if the implementation can ascertain that the nature of the * previous request attempt failure indicates that it would be very * unlikely to reoccur in a subsequent attempt. * * </ul> * * The <code>hasNext</code> method should not return <code>true</code> * after successive failed request attempts indefinitely. The request * retry mechanism provided by <code>OutboundRequestIterator</code> is * not intended for implementing a strategy of general retry of the * same communication mechanism after indeterminate failures. * * <p>Note that it is permitted, although unlikely, for an * <code>OutboundRequestIterator</code>'s <code>hasNext</code> method * to never return <code>true</code>, in which case the * <code>OutboundRequestIterator</code> does not support initiating * even one attempt to send the request. * * <p>An <code>OutboundRequestIterator</code> is not guaranteed to be * safe for concurrent use by multiple threads. * * @author Sun Microsystems, Inc. * @see Endpoint * @since 2.0 **/ public interface OutboundRequestIterator { /** * Returns <code>true</code> if this iterator supports making at * least one more attempt to communicate the request, and * <code>false</code> otherwise. * * <p>If this method returns <code>true</code>, then it is * guaranteed that the next invocation of {@link #next next} on * this iterator will not throw a {@link NoSuchElementException}. * * <p>If <code>next</code> has been invoked on this iterator and * the previous invocation of <code>next</code> returned an * <code>OutboundRequest</code>, then this method should not be * invoked until that <code>OutboundRequest</code> has been used * to attempt to communicate the request and a failure has * occurred. * * <p>The security context in which this method is invoked may be * used for subsequent verification of security permissions; see * the <code>next</code> method specification for more details. * * @return <code>true</code> if this iterator supports making * another attempt to communicate the request, and * <code>false</code> otherwise **/ boolean hasNext(); /** * Initiates an attempt to communicate the request to the remote * endpoint. * * <p>After an invocation of {@link #hasNext hasNext} returns * <code>true</code>, it is guaranteed that the next invocation of * this method will not throw a {@link NoSuchElementException}. * * <p>If successful, this method returns an * <code>OutboundRequest</code> to use to write the request data * and read the response. Even if this method throws an {@link * IOException} or a {@link SecurityException}, the iteration of * attempts to communicate the request may continue with another * invocation of <code>hasNext</code>. * * <p>The implementation verifies that the user's security context * has all of the security permissions necessary to communicate * the current request attempt with the remote endpoint and to * satisfy any required constraints, as appropriate to the * implementation of this interface. The implementation is * allowed, however, to indicate failure of such a permission * check by either throwing a <code>SecurityException</code> from * this method or, after returning an <code>OutboundRequest</code> * from this method, throwing a <code>SecurityException</code> * from some subsequent operation on the * <code>OutboundRequest</code> or its streams. If such a * <code>SecurityException</code> is thrown, request data must not * have been transmitted to the server (that is, if an * <code>OutboundRequest</code> has been returned, its {@link * OutboundRequest#getDeliveryStatus getDeliveryStatus} method * must return <code>false</code>), and the client's identity must * not have been revealed to the server. * * <p>Also, the implementation of this method or the returned * <code>OutboundRequest</code> must eventually verify that the * client and server have the requisite principals and credentials * to satisfy any required constraints and if not, throw an * <code>IOException</code>. If such an <code>IOException</code> * is thrown, request data must not have been transmitted to the * server. * * <p>In verifying any such permission requirement or credential, * the implementation is allowed to use the security context in * effect for this or any previous invocation of a method on this * iterator or the security context in effect for any operation on * the <code>OutboundRequest</code> returned by this or any * previous invocation of this method on this iterator. * Therefore, this iterator and the <code>OutboundRequest</code> * instances that it produces should be used in a uniform security * context. * * @return the <code>OutboundRequest</code> to use to write the * request data and read the response * * @throws NoSuchElementException if this iterator does not * support making another attempt to communicate the request (that * is, if <code>hasNext</code> would return <code>false</code>) * * @throws IOException if an I/O exception occurs while performing * this operation; in this event, the recipient may have received * an indication of the request initiation attempt * * @throws SecurityException if the user does not have the * permissions necessary to communicate with the remote endpoint **/ OutboundRequest next() throws IOException; }