--- old/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/WebSocket.java 2017-11-30 04:04:11.977188596 -0800 +++ new/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/WebSocket.java 2017-11-30 04:04:11.752168925 -0800 @@ -26,7 +26,6 @@ package jdk.incubator.http; import java.io.IOException; -import java.net.ProtocolException; import java.net.URI; import java.nio.ByteBuffer; import java.time.Duration; @@ -34,50 +33,54 @@ import java.util.concurrent.CompletionStage; /** - * A WebSocket client conforming to RFC 6455. + * A WebSocket client. * {@Incubating} * - *
A {@code WebSocket} provides full-duplex communication over a TCP - * connection. - * - *
To create a {@code WebSocket} use a {@linkplain HttpClient#newWebSocketBuilder( - * URI, Listener) builder}. Once a {@code WebSocket} is built, it's ready - * to send and receive messages. When the {@code WebSocket} is no longer needed - * it must be closed: a Close message must both be {@linkplain #sendClose - * sent} and {@linkplain Listener#onClose(WebSocket, int, String) received}. - * The {@code WebSocket} may be also closed {@linkplain #abort() abruptly}. - * - *
Once closed the {@code WebSocket} remains {@linkplain #isClosed() closed} - * and cannot be reopened. - * - *
Messages of type {@code X} (where {@code X} is one of: Text, Binary, - * Ping, Pong or Close) are sent and received asynchronously through the {@code - * WebSocket.send{X}} and {@link WebSocket.Listener}{@code .on{X}} methods - * respectively. Each method returns a {@link CompletionStage} which completes - * when the operation has completed. - * - *
Note that messages (of any type) are received only if {@linkplain - * #request(long) requested}. - * - *
One outstanding send operation is permitted. No further send operation - * can be initiated before the previous one has completed. When sending, a - * message must not be modified until the returned {@link CompletableFuture} - * completes (either normally or exceptionally). - * - *
Text and Binary messages can be sent and received as a whole or in parts. - * A whole message is transferred as a sequence of one or more invocations of a - * corresponding method where the last invocation is identified via an - * additional method argument. - * - *
If the message is contained in a {@link ByteBuffer}, bytes are considered - * arranged from the {@code buffer}'s {@link ByteBuffer#position() position} to - * the {@code buffer}'s {@link ByteBuffer#limit() limit}. - * - *
Unless otherwise stated, {@code null} parameter values will cause methods - * and constructors to throw {@link NullPointerException}. - * - * @implNote This implementation's methods do not block before returning - * a {@code CompletableFuture}. + *
To create a {@code WebSocket} use the {@link HttpClient#newWebSocketBuilder} + * method. To close a {@code WebSocket} use one of the {@code sendClose} or + * {@code abort} methods. + * + *
WebSocket messages are sent through a {@code WebSocket} and received + * through the {@code WebSocket}'s {@code Listener}. Messages can be sent until + * the output is closed, and received until the input is closed. + * A {@code WebSocket} whose output and input are both closed may be considered + * itself closed. To check these states use {@link #isOutputClosed()} and + * {@link #isInputClosed()}. + * + *
Methods that send messages return {@code CompletableFuture} which + * completes normally if the message is sent or completes exceptionally if an + * error occurs. + * + *
To receive a message, first request it. If {@code n} messages are + * requested, the listener will receive up to {@code n} more invocations of the + * designated methods from the {@code WebSocket}. To request messages use + * {@link #request(long)}. Request is an additive operation, that is + * {@code request(n)} followed by {@code request(m)} is equivalent to + * {@code request(n + m)}. + * + *
When sending or receiving a message in parts, a whole message is + * transferred as a sequence of one or more invocations where the last + * invocation is identified via an additional method argument. + * + *
Unless otherwise stated, {@code null} arguments will cause methods + * of {@code WebSocket} to throw {@code NullPointerException}, similarly, + * {@code WebSocket} will not pass {@code null} arguments to methods of + * {@code Listener}. + * + * @implSpec Methods of {@code WebSocket} are failure-atomic in respect to + * {@code NullPointerException}, {@code IllegalArgumentException} and + * {@code IllegalStateException}. That is, if a method throws said exception, or + * a returned {@code CompletableFuture} completes exceptionally with said + * exception, the {@code WebSocket} will behave as if the method has not been + * invoked at all. + * + *
A {@code WebSocket} invokes methods of its listener in a thread-safe + * manner. + * + *
{@code WebSocket} handles Ping and Close messages automatically (as per + * RFC 6455) by replying with Pong and Close messages respectively. If the + * listener receives Ping or Close messages, no mandatory actions from the + * listener are required. * * @since 9 */ @@ -97,29 +100,24 @@ * A builder for creating {@code WebSocket} instances. * {@Incubating} * - *
To build a {@code WebSocket}, {@linkplain HttpClient#newWebSocketBuilder( - * URI, Listener) create} a builder, configure it as required by + *
To obtain a {@code WebSocket} configure a builder as required by * calling intermediate methods (the ones that return the builder itself), - * then finally call {@link #buildAsync()} to get a {@link - * CompletableFuture} with resulting {@code WebSocket}. - * - *
If an intermediate method has not been called, an appropriate - * default value (or behavior) will be used. Unless otherwise noted, a - * repeated call to an intermediate method overwrites the previous value (or - * overrides the previous behaviour). + * then call {@code buildAsync()}. If an intermediate method is not called, + * an appropriate default value (or behavior) will be assumed. * - *
Instances of {@code Builder} are not safe for use by multiple threads - * without external synchronization. + *
Unless otherwise stated, {@code null} arguments will cause methods of + * {@code Builder} to throw {@code NullPointerException}. * * @since 9 */ interface Builder { /** - * Adds the given name-value pair to the list of additional headers for - * the opening handshake. + * Adds the given name-value pair to the list of additional HTTP headers + * sent during the opening handshake. * - *
Headers defined in WebSocket Protocol are not allowed to be added. + *
Headers defined in WebSocket Protocol are illegal. If this method + * is not invoked, no additional HTTP headers will be sent. * * @param name * the header name @@ -131,56 +129,53 @@ Builder header(String name, String value); /** - * Includes a request for the given subprotocols during the opening - * handshake. - * - *
Among the requested subprotocols at most one will be chosen by - * the server. This subprotocol will be available from {@link - * WebSocket#getSubprotocol}. Subprotocols are specified in the order of - * preference. - * - *
Each of the given subprotocols must conform to the relevant - * rules defined in the WebSocket Protocol. + * Sets a timeout for establishing a WebSocket connection. * - *
If this method is not invoked then no subprotocols are requested. + *
If the connection is not established within the specified + * duration then building of the {@code WebSocket} will fail with + * {@link HttpTimeoutException}. If this method is not invoked then the + * infinite timeout is assumed. * - * @param mostPreferred - * the most preferred subprotocol - * @param lesserPreferred - * the lesser preferred subprotocols, with the least preferred - * at the end + * @param timeout + * the timeout, non-{@linkplain Duration#isNegative() negative}, + * non-{@linkplain Duration#ZERO ZERO} * * @return this builder */ - Builder subprotocols(String mostPreferred, String... lesserPreferred); + Builder connectTimeout(Duration timeout); /** - * Sets a timeout for the opening handshake. - * - *
If the opening handshake does not complete within the specified - * duration then the {@code CompletableFuture} returned from {@link - * #buildAsync()} completes exceptionally with a {@link - * HttpTimeoutException}. + * Sets a request for the given subprotocols. * - *
If this method is not invoked then the timeout is deemed infinite. + *
After the {@code WebSocket} has been built, the actual + * subprotocol can be queried via + * {@link WebSocket#getSubprotocol WebSocket.getSubprotocol()}. + * + *
Subprotocols are specified in the order of preference. The most + * preferred subprotocol is specified first. If there are any additional + * subprotocols they are enumerated from the most preferred to the least + * preferred. + * + *
Subprotocols not conforming to the syntax of subprotocol + * identifiers are illegal. If this method is not invoked then no + * subprotocols will be requested. * - * @param timeout - * the timeout, non-{@linkplain Duration#isNegative() negative}, - * non-{@linkplain Duration#ZERO ZERO} + * @param mostPreferred + * the most preferred subprotocol + * @param lesserPreferred + * the lesser preferred subprotocols * * @return this builder */ - Builder connectTimeout(Duration timeout); + Builder subprotocols(String mostPreferred, String... lesserPreferred); /** - * Builds a {@code WebSocket}. - * - *
Returns a {@code CompletableFuture {@code CompletableFuture} may complete exceptionally with the
- * following errors:
+ * Returns a {@code CompletableFuture} which will either complete
+ * normally with the resulting {@code WebSocket} or complete
+ * exceptionally with one of the following errors:
* Each method of {@code Listener} corresponds to a type of event or a
- * type of message. The {@code WebSocket} argument of the method is the
- * {@code WebSocket} the event has occurred (the message has been received)
- * on. All methods with the same {@code WebSocket} argument are invoked in a
- * sequential
- * (and happens-before)
- * order, one after another, possibly by different threads.
- *
- * Messages received by the {@code Listener} conform to the WebSocket
- * Protocol, otherwise {@code onError} with a {@link ProtocolException} is
- * invoked.
- *
- * If a whole message is received, then the corresponding method
- * ({@code onText} or {@code onBinary}) will be invoked with {@link
- * WebSocket.MessagePart#WHOLE WHOLE} marker. Otherwise the method will be
- * invoked with {@link WebSocket.MessagePart#FIRST FIRST}, zero or more
- * times with {@link WebSocket.MessagePart#PART PART} and, finally, with
- * {@link WebSocket.MessagePart#LAST LAST} markers.
- *
- * If any of the methods above throws an exception, {@code onError} is then
- * invoked with the same {@code WebSocket} and this exception. Exceptions
- * thrown from {@code onError} or {@code onClose} are ignored.
- *
- * When the method returns, the message is deemed received (in
- * particular, if contained in a {@code ByteBuffer buffer}, the data is
- * deemed received completely regardless of the result {@code
- * buffer.hasRemaining()} upon the method's return. After this further
- * messages may be received.
- *
- * These invocations begin asynchronous processing which might not end
- * with the invocation. To provide coordination, methods of {@code Listener}
- * return a {@link CompletionStage CompletionStage}.
- * The {@code CompletionStage} signals the {@code WebSocket} that the
- * processing of a message has ended. For convenience, methods may return
- * {@code null}, which (by convention) means the same as returning an
- * already completed (normally) {@code CompletionStage}.
- * If the returned {@code CompletionStage} completes exceptionally, then
- * {@link #onError(WebSocket, Throwable) onError} will be invoked with the
- * same {@code WebSocket} and this exception.
- *
- * Control of the message passes to the {@code Listener} with the
- * invocation of the method. Control of the message returns to the {@code
- * WebSocket} at the earliest of, either returning {@code null} from the
- * method, or the completion of the {@code CompletionStage} returned from
- * the method. The {@code WebSocket} does not access the message while it's
- * not in its control. The {@code Listener} must not access the message
- * after its control has been returned to the {@code WebSocket}.
- *
- * A {@code WebSocket} implementation never invokes {@code Listener}'s
- * methods with {@code null}s as their arguments.
+ * A {@code WebSocket} invokes methods on its listener when it receives
+ * messages or encounters events. The invoking {@code WebSocket} is passed
+ * as an argument to {@code Listener}'s methods. A {@code WebSocket} invokes
+ * methods on its listener in a thread-safe manner.
+ *
+ * Unless otherwise stated if a listener's method throws an exception or
+ * a {@code CompletionStage} returned from a method completes exceptionally,
+ * the {@code WebSocket} will invoke {@code onError} with this exception.
+ *
+ * If a listener's method returns {@code null} rather than a
+ * {@code CompletionStage}, {@code WebSocket} will behave as if the listener
+ * returned a {@code CompletionStage} that is already completed normally.
*
* @since 9
*/
interface Listener {
/**
- * Notifies the {@code Listener} that it is connected to the provided
- * {@code WebSocket}.
+ * A {@code WebSocket} has been connected.
*
- * The {@code onOpen} method does not correspond to any message from
- * the WebSocket Protocol. It is a synthetic event and the first {@code
- * Listener}'s method to be invoked.
- *
- * This method is usually used to make an initial {@linkplain
- * WebSocket#request(long) request} for messages.
- *
- * If an exception is thrown from this method then {@link
- * #onError(WebSocket, Throwable) onError} will be invoked with the same
- * {@code WebSocket} and this exception.
+ * This is the first invocation and it is made at most once. This
+ * method is typically used to make an initial request for messages.
*
* @implSpec The default implementation of this method behaves as if:
*
@@ -302,24 +241,24 @@
* }
*
* @param webSocket
- * the WebSocket
+ * the WebSocket that has been connected
*/
default void onOpen(WebSocket webSocket) { webSocket.request(1); }
/**
- * Receives a Text message.
+ * A Text message has been received.
*
- * The {@code onText} method is invoked zero or more times between
- * {@code onOpen} and ({@code onClose} or {@code onError}).
- *
- * This message may be a partial UTF-16 sequence. However, the
- * concatenation of all messages through the last will be a whole UTF-16
- * sequence.
- *
- * If an exception is thrown from this method or the returned {@code
- * CompletionStage} completes exceptionally, then {@link
- * #onError(WebSocket, Throwable) onError} will be invoked with the same
- * {@code WebSocket} and this exception.
+ * If a whole message has been received, this method will be invoked
+ * with {@code MessagePart.WHOLE} marker. Otherwise, it will be invoked
+ * with {@code FIRST}, possibly a number of times with {@code PART} and,
+ * finally, with {@code LAST} markers. If this message is partial, it
+ * may be an incomplete UTF-16 sequence. However, the concatenation of
+ * all messages through the last will be a complete UTF-16 sequence.
+ *
+ * Return a {@code CompletionStage} which will be used by the
+ * {@code WebSocket} as a signal it may reclaim the
+ * {@code CharSequence}. Do not access the {@code CharSequence} after
+ * this {@ode CompletionStage} has completed.
*
* @implSpec The default implementation of this method behaves as if:
*
@@ -328,18 +267,19 @@
* return null;
* }
*
- * @implNote This implementation passes only complete UTF-16 sequences
- * to the {@code onText} method.
+ * @implNote This method is always invoked with character sequences
+ * which are complete UTF-16 sequences.
*
* @param webSocket
- * the WebSocket
+ * the WebSocket on which the message has been received
* @param message
* the message
* @param part
* the part
*
- * @return a {@code CompletionStage} which completes when the message
- * processing is done; or {@code null} if already done
+ * @return a {@code CompletionStage} which completes when the
+ * {@code CharSequence} may be reclaimed; or {@code null} if it may be
+ * reclaimed immediately
*/
default CompletionStage> onText(WebSocket webSocket,
CharSequence message,
@@ -349,15 +289,20 @@
}
/**
- * Receives a Binary message.
- *
- * The {@code onBinary} method is invoked zero or more times
- * between {@code onOpen} and ({@code onClose} or {@code onError}).
+ * A Binary message has been received.
*
- * If an exception is thrown from this method or the returned {@code
- * CompletionStage} completes exceptionally, then {@link
- * #onError(WebSocket, Throwable) onError} will be invoked with the same
- * {@code WebSocket} and this exception.
+ * If a whole message has been received, this method will be invoked
+ * with {@code MessagePart.WHOLE} marker. Otherwise, it will be invoked
+ * with {@code FIRST}, possibly a number of times with {@code PART} and,
+ * finally, with {@code LAST} markers.
+ *
+ * This message consists of bytes from the buffer's position to
+ * its limit.
+ *
+ * Return a {@code CompletionStage} which will be used by the
+ * {@code WebSocket} as a signal it may reclaim the
+ * {@code ByteBuffer}. Do not access the {@code ByteBuffer} after
+ * this {@ode CompletionStage} has completed.
*
* @implSpec The default implementation of this method behaves as if:
*
@@ -367,14 +312,15 @@
* }
*
* @param webSocket
- * the WebSocket
+ * the WebSocket on which the message has been received
* @param message
* the message
* @param part
* the part
*
- * @return a {@code CompletionStage} which completes when the message
- * processing is done; or {@code null} if already done
+ * @return a {@code CompletionStage} which completes when the
+ * {@code ByteBuffer} may be reclaimed; or {@code null} if it may be
+ * reclaimed immediately
*/
default CompletionStage> onBinary(WebSocket webSocket,
ByteBuffer message,
@@ -384,34 +330,15 @@
}
/**
- * Receives a Ping message.
+ * A Ping message has been received.
*
- * A Ping message may be sent or received by either client or
- * server. It may serve either as a keepalive or as a means to verify
- * that the remote endpoint is still responsive.
- *
- * The {@code WebSocket} handles Ping messages by replying with
- * appropriate Pong messages using a strategy of its choice, but within
- * the boundaries of the WebSocket Protocol. The {@code WebSocket} may
- * invoke {@code onPing} after handling a Ping message, before doing so
- * or in parallel with it. In other words no particular ordering is
- * guaranteed. If an error occurs while implementation handles this Ping
- * message, then {@code onError} will be invoked with this error. For
- * more details on handling Ping messages see RFC 6455 sections
- * 5.5.2. Ping
- * and
- * 5.5.3. Pong.
- *
- * The message will consist of not more than {@code 125} bytes:
- * {@code message.remaining() <= 125}.
- *
- * The {@code onPing} is invoked zero or more times in between
- * {@code onOpen} and ({@code onClose} or {@code onError}).
- *
- * If an exception is thrown from this method or the returned {@code
- * CompletionStage} completes exceptionally, then {@link
- * #onError(WebSocket, Throwable) onError} will be invoked with this
- * exception.
+ * The message consists of not more than {@code 125} bytes from
+ * the buffer's position to its limit.
+ *
+ * Return a {@code CompletionStage} which will be used by the
+ * {@code WebSocket} as a signal it may reclaim the
+ * {@code ByteBuffer}. Do not access the {@code ByteBuffer} after
+ * this {@ode CompletionStage} has completed.
*
* @implSpec The default implementation of this method behaves as if:
*
@@ -421,12 +348,13 @@
* }
*
* @param webSocket
- * the WebSocket
+ * the WebSocket on which the message has been received
* @param message
* the message
*
- * @return a {@code CompletionStage} which completes when the message
- * processing is done; or {@code null} if already done
+ * @return a {@code CompletionStage} which completes when the
+ * {@code ByteBuffer} may be reclaimed; or {@code null} if it may be
+ * reclaimed immediately
*/
default CompletionStage> onPing(WebSocket webSocket,
ByteBuffer message) {
@@ -435,22 +363,15 @@
}
/**
- * Receives a Pong message.
+ * A Pong message has been received.
+ *
+ * The message consists of not more than {@code 125} bytes from
+ * the buffer's position to its limit.
*
- * A Pong message may be unsolicited or may be received in response
- * to a previously sent Ping. In the latter case, the contents of the
- * Pong is identical to the originating Ping.
- *
- * The message will consist of not more than {@code 125} bytes:
- * {@code message.remaining() <= 125}.
- *
- * The {@code onPong} method is invoked zero or more times in
- * between {@code onOpen} and ({@code onClose} or {@code onError}).
- *
- * If an exception is thrown from this method or the returned {@code
- * CompletionStage} completes exceptionally, then {@link
- * #onError(WebSocket, Throwable) onError} will be invoked with this
- * exception.
+ * Return a {@code CompletionStage} which will be used by the
+ * {@code WebSocket} as a signal it may reclaim the
+ * {@code ByteBuffer}. Do not access the {@code ByteBuffer} after
+ * this {@ode CompletionStage} has completed.
*
* @implSpec The default implementation of this method behaves as if:
*
@@ -460,12 +381,13 @@
* }
*
* @param webSocket
- * the WebSocket
+ * the WebSocket on which the message has been received
* @param message
* the message
*
- * @return a {@code CompletionStage} which completes when the message
- * processing is done; or {@code null} if already done
+ * @return a {@code CompletionStage} which completes when the
+ * {@code ByteBuffer} may be reclaimed; or {@code null} if it may be
+ * reclaimed immediately
*/
default CompletionStage> onPong(WebSocket webSocket,
ByteBuffer message) {
@@ -474,52 +396,39 @@
}
/**
- * Receives a Close message.
+ * A Close message has been received.
*
- * A Close message consists of a status code and a reason for
- * closing. The status code is an integer in the range {@code 1000 <=
- * code <= 65535}. The {@code reason} is a short string that has an
- * UTF-8 representation not longer than {@code 123} bytes. For more
- * details on Close message, status codes and reason see RFC 6455 sections
- * 5.5.1. Close
- * and
- * 7.4. Status Codes.
- *
- * After the returned {@code CompletionStage} has completed
- * (normally or exceptionally), the {@code WebSocket} completes the
- * closing handshake by replying with an appropriate Close message.
- *
- * This implementation replies with a Close message that has the
- * same code this message has and an empty reason.
- *
- * {@code onClose} is the last invocation on the {@code Listener}.
- * It is invoked at most once, but after {@code onOpen}. If an exception
- * is thrown from this method, it is ignored.
- *
- * The {@code WebSocket} will close at the earliest of completion of
- * the returned {@code CompletionStage} or sending a Close message. In
- * particular, if a Close message has been {@linkplain WebSocket#sendClose
- * sent} before, then this invocation completes the closing handshake
- * and by the time this method is invoked, the {@code WebSocket} will
- * have been closed.
+ * This is the last invocation from the {@code WebSocket}. By the
+ * time this invocation begins the {@code WebSocket}'s input will have
+ * been closed. Be prepared to receive this invocation at any time after
+ * {@code onOpen} regardless of whether or not any messages have been
+ * requested from the {@code WebSocket}.
*
- * @implSpec The default implementation of this method behaves as if:
- *
- * A Close message consists of a status code and a reason for
+ * closing. The status code is an integer from the range
+ * {@code 1000 <= code <= 65535}. The {@code reason} is a string which
+ * has an UTF-8 representation not longer than {@code 123} bytes.
+ *
+ * Return a {@code CompletionStage} that will be used by the
+ * {@code WebSocket} as a signal that it may close the output. The
+ * {@code WebSocket} will close the output at the earliest of completion
+ * of the returned {@code CompletionStage} or invoking a
+ * {@link WebSocket#sendClose(int, String) sendClose} method.
+ *
+ * If an exception is thrown from this method or a
+ * {@code CompletionStage} returned from it completes exceptionally,
+ * the resulting behaviour is undefined.
*
* @param webSocket
- * the WebSocket
+ * the WebSocket on which the message has been received
* @param statusCode
* the status code
* @param reason
* the reason
*
- * @return a {@code CompletionStage} which completes when the {@code
- * WebSocket} can be closed; or {@code null} if it can be closed immediately
- *
- * @see #NORMAL_CLOSURE
+ * @return a {@code CompletionStage} which completes when the
+ * {@code WebSocket} may be closed; or {@code null} if it may be
+ * closed immediately
*/
default CompletionStage> onClose(WebSocket webSocket,
int statusCode,
@@ -528,31 +437,19 @@
}
/**
- * Notifies an I/O or protocol error has occurred.
+ * An unrecoverable error has occurred.
*
- * The {@code onError} method does not correspond to any message
- * from the WebSocket Protocol. It is a synthetic event and the last
- * {@code Listener}'s method to be invoked. It is invoked at most once
- * but after {@code onOpen}. If an exception is thrown from this method,
- * it is ignored.
- *
- * Note that the WebSocket Protocol requires some errors
- * occur in the incoming destination must be fatal to the connection. In
- * such cases the implementation takes care of Failing the WebSocket
- * Connection: by the time {@code onError} is invoked, the {@code
- * WebSocket} will have been closed. Any outstanding or subsequent send
- * operation will complete exceptionally with an {@code IOException}.
- * For more details on Failing the WebSocket Connection see RFC 6455
- * section 7.1.7. Fail the WebSocket Connection.
- *
- * @apiNote Errors associated with sending messages are reported to the
- * {@code CompletableFuture}s {@code sendX} methods return, rather than
- * to this this method.
+ * This is the last invocation from the {@code WebSocket}. By the
+ * time this invocation begins both {@code WebSocket}'s input and output
+ * will have been closed. Be prepared to receive this invocation at any
+ * time after {@code onOpen} regardless of whether or not any messages
+ * have been requested from the {@code WebSocket}.
*
- * @implSpec The default implementation of this method does nothing.
+ * If an exception is thrown from this method, resulting behavior is
+ * undefined.
*
* @param webSocket
- * the WebSocket
+ * the WebSocket on which the error has occurred
* @param error
* the error
*/
@@ -560,29 +457,26 @@
}
/**
- * A marker used by {@link WebSocket.Listener} in cases where a partial
- * message may be received.
+ * A marker used by {@link WebSocket.Listener} for identifying partial
+ * messages.
* {@Incubating}
*
- * @see Listener#onText(WebSocket, CharSequence, MessagePart)
- * @see Listener#onBinary(WebSocket, ByteBuffer, MessagePart)
- *
* @since 9
*/
enum MessagePart {
/**
- * The first part of a message in a sequence.
+ * The first part of a message.
*/
FIRST,
/**
- * A middle part of a message in a sequence.
+ * A middle part of a message.
*/
PART,
/**
- * The last part of a message in a sequence.
+ * The last part of a message.
*/
LAST,
@@ -595,31 +489,28 @@
/**
* Sends a Text message with characters from the given {@code CharSequence}.
*
- * Returns a {@code CompletableFuture To send a Text message invoke this method only after the previous
+ * Text or Binary message has been sent. The character sequence must not be
+ * modified until the {@code CompletableFuture} returned from this method
+ * has completed.
*
- * The {@code CharSequence} must not be modified until the returned
- * {@code CompletableFuture} completes (either normally or exceptionally).
- *
- * The returned {@code CompletableFuture} can complete exceptionally
- * with:
+ * A {@code CompletableFuture} returned from this method can
+ * complete exceptionally with:
* Returns a {@code CompletableFuture To send a Binary message invoke this method only after the previous
+ * Text or Binary message has been sent. The message consists of bytes from
+ * the buffer's position to its limit. Upon normal completion of a
+ * {@code CompletableFuture} returned from this method the buffer will have
+ * no remaining bytes. The buffer must not be accessed until after that.
*
- * The returned {@code CompletableFuture} can complete exceptionally
- * with:
+ * The {@code CompletableFuture} returned from this method can
+ * complete exceptionally with:
* Returns a {@code CompletableFuture A Ping message may be sent or received by either client or server.
- * It may serve either as a keepalive or as a means to verify that the
- * remote endpoint is still responsive.
+ * The message consists of not more than {@code 125} bytes from the
+ * buffer's position to its limit. Upon normal completion of a
+ * {@code CompletableFuture} returned from this method the buffer will
+ * have no remaining bytes. The buffer must not be accessed until after that.
*
- * The message must consist of not more than {@code 125} bytes: {@code
- * message.remaining() <= 125}.
- *
- * The returned {@code CompletableFuture} can complete exceptionally
- * with:
+ * The {@code CompletableFuture} returned from this method can
+ * complete exceptionally with:
* Returns a {@code CompletableFuture A Pong message may be unsolicited or may be sent in response to a
- * previously received Ping. In latter case the contents of the Pong must be
- * identical to the originating Ping.
+ * The message consists of not more than {@code 125} bytes from the
+ * buffer's position to its limit. Upon normal completion of a
+ * {@code CompletableFuture} returned from this method the buffer will
+ * have no remaining bytes. The buffer must not be accessed until after that.
*
- * The message must consist of not more than {@code 125} bytes: {@code
- * message.remaining() <= 125}.
- *
- * The returned {@code CompletableFuture} can complete exceptionally
- * with:
+ * The {@code CompletableFuture} returned from this method can
+ * complete exceptionally with:
* When this method returns the output will have been closed.
*
- * When this method has been invoked, no further messages can be sent.
+ * The {@code statusCode} is an integer from the range
+ * {@code 1000 <= code <= 4999}. Status codes {@code 1002}, {@code 1003},
+ * {@code 1006}, {@code 1007}, {@code 1009}, {@code 1010}, {@code 1012},
+ * {@code 1013} and {@code 1015} are illegal. Behaviour in respect to other
+ * status codes is implementation-specific. The {@code reason} is a string
+ * that has an UTF-8 representation not longer than {@code 123} bytes.
*
- * The {@code statusCode} is an integer in the range {@code 1000 <= code
- * <= 4999}. However, not all status codes may be legal in some
- * implementations. Regardless of an implementation,
- * The {@code reason} is a short string that must have an UTF-8
- * representation not longer than {@code 123} bytes. For more details on
- * Close message, status codes and reason see RFC 6455 sections
- * 5.5.1. Close
- * and
- * 7.4. Status Codes.
- *
- * The method returns a {@code CompletableFuture Use the provided integer constant {@link #NORMAL_CLOSURE} as a status
+ * code and an empty string as a reason in a typical case.
*
- * The returned {@code CompletableFuture} can complete exceptionally
- * with:
+ * A {@code CompletableFuture} returned from this method can
+ * complete exceptionally with:
* If this method has already been invoked or the {@code WebSocket} is
- * closed, then subsequent invocations of this method have no effect and the
- * returned {@code CompletableFuture} completes normally.
- *
- * If a Close message has been {@linkplain Listener#onClose(WebSocket,
- * int, String) received} before, then this invocation completes the closing
- * handshake and by the time the returned {@code CompletableFuture}
- * completes, the {@code WebSocket} will have been closed.
+ * @implSpec An endpoint sending a Close message might not receive a
+ * complementing Close message in a timely manner for a variety of reasons.
+ * The {@code WebSocket} implementation is responsible for providing a
+ * closure mechanism that guarantees that once {@code sendClose} method has
+ * been invoked the {@code WebSocket} will close regardless of whether or
+ * not a Close frame has been received and without further intervention from
+ * the user of this API. Method {@code sendClose} is designed to be,
+ * possibly, the last call from the user of this API.
*
* @param statusCode
* the status code
* @param reason
* the reason
*
- * @return a {@code CompletableFuture} with this {@code WebSocket}
+ * @return a {@code CompletableFuture} that completes, with this {@code
+ * WebSocket}, when the Close message has been sent
*/
CompletableFuture The actual number of received messages might be fewer if a Close
- * message is received, the {@code WebSocket} closes or an error occurs.
+ * This {@code WebSocket} will invoke its listener's {@code onText},
+ * {@code onBinary}, {@code onPing}, {@code onPong} or {@code onClose}
+ * methods up to {@code n} more times.
*
- * A {@code WebSocket} that has just been built, hasn't requested
- * anything yet. Usually the initial request for messages is made in {@link
- * Listener#onOpen(jdk.incubator.http.WebSocket) Listener.onOpen}.
- *
- * If the {@code WebSocket} is closed then invoking this method has no
- * effect.
- *
- * @implNote This implementation does not distinguish between partial and
- * whole messages, because it's not known beforehand how a message will be
- * received.
- *
- * If a server sends more messages than requested, this implementation
- * queues up these messages on the TCP connection and may eventually force
- * the sender to stop sending through TCP flow control.
+ * This method may be invoked at any time.
*
* @param n
- * the number of messages
+ * the number of messages requested
*
* @throws IllegalArgumentException
- * if {@code n < 0}
+ * if {@code n <= 0}
*/
void request(long n);
/**
- * Returns a {@linkplain Builder#subprotocols(String, String...) subprotocol}
- * which has been chosen for this {@code WebSocket}.
+ * Returns the subprotocol for this {@code WebSocket}.
*
- * @return a subprotocol, or an empty {@code String} if there is none
+ * This method may be invoked at any time.
+ *
+ * @return the subprotocol for this {@code WebSocket}, or an empty
+ * {@code String} if there's no subprotocol
*/
String getSubprotocol();
/**
- * Tells whether the {@code WebSocket} is closed.
+ * Tells whether or not this {@code WebSocket} is permanently closed
+ * for sending messages.
*
- * When a {@code WebSocket} is closed no further messages can be sent or
- * received.
+ * If this method returns {@code true}, subsequent invocations will also
+ * return {@code true}. This method may be invoked at any time.
*
- * @return {@code true} if the {@code WebSocket} is closed,
- * {@code false} otherwise
+ * @return {@code true} if closed, {@code false} otherwise
*/
- boolean isClosed();
+ boolean isOutputClosed();
/**
- * Closes the {@code WebSocket} abruptly.
+ * Tells whether or not this {@code WebSocket} is permanently closed
+ * for receiving messages.
*
- * This method may be invoked at any time. This method closes the
- * underlying TCP connection and puts the {@code WebSocket} into a closed
- * state.
+ * If this method returns {@code true}, subsequent invocations will also
+ * return {@code true}. This method may be invoked at any time.
*
- * As the result {@link Listener#onClose(WebSocket, int, String)
- * Listener.onClose} will be invoked unless either {@code onClose} or {@link
- * Listener#onError(WebSocket, Throwable) onError} has been invoked before.
- * In which case no additional invocation will happen.
+ * @return {@code true} if closed, {@code false} otherwise
+ */
+ boolean isInputClosed();
+
+ /**
+ * Closes this {@code WebSocket} abruptly.
*
- * If the {@code WebSocket} is already closed then invoking this method
- * has no effect.
+ * When this method returns both the input and output will have been
+ * closed. This method may be invoked at any time. Subsequent invocations
+ * have no effect.
*
- * @throws IOException
- * if an I/O error occurs
+ * @apiNote Depending on its implementation, the state (for example, whether
+ * or not a message is being transferred at the moment) and possible errors
+ * while releasing associated resources, this {@code WebSocket} may invoke
+ * its listener's {@code onError}.
*/
- void abort() throws IOException;
+ void abort();
}
*
*
+ * @param uri
+ * the WebSocket URI
+ * @param listener
+ * the listener
+ *
* @return a {@code CompletableFuture} with the {@code WebSocket}
*/
- CompletableFuture
- *
- *
- *
- * This method is invoked first.
- *
- * These methods are invoked zero or more times after {@code onOpen}.
- *
- * Only one of these methods is invoked, and that method is invoked last.
- * {@code
- * return null;
- * }
+ *
*
*
- * @implNote This implementation does not accept partial UTF-16 sequences.
- * In case such a sequence is passed, a returned {@code CompletableFuture}
- * completes exceptionally with {@code IOException}.
+ * @implNote If a partial UTF-16 sequence is passed to this method, a
+ * {@code CompletableFuture} returned will complete exceptionally with
+ * {@code IOException}.
*
* @param message
* the message
@@ -627,28 +518,30 @@
* {@code true} if this is the last part of the message,
* {@code false} otherwise
*
- * @return a {@code CompletableFuture} with this {@code WebSocket}
+ * @return a {@code CompletableFuture} that completes, with this {@code
+ * WebSocket}, when the message has been sent
*/
CompletableFuture
*
*
* @param message
@@ -657,200 +550,169 @@
* {@code true} if this is the last part of the message,
* {@code false} otherwise
*
- * @return a {@code CompletableFuture} with this {@code WebSocket}
+ * @return a {@code CompletableFuture} that completes, with this {@code
+ * WebSocket}, when the message has been sent
*/
CompletableFuture
*
*
* @param message
* the message
*
- * @return a {@code CompletableFuture} with this {@code WebSocket}
+ * @return a {@code CompletableFuture} that completes, with this {@code
+ * WebSocket}, when the Ping message has been sent
*/
CompletableFuture
*
*
* @param message
* the message
*
- * @return a {@code CompletableFuture} with this {@code WebSocket}
+ * @return a {@code CompletableFuture} that completes, with this {@code
+ * WebSocket}, when the Pong message has been sent
*/
CompletableFuture{@value jdk.incubator.http.WebSocket#NORMAL_CLOSURE}
- * is always legal and {@code 1002}, {@code 1003}, {@code 1005}, {@code
- * 1006}, {@code 1007}, {@code 1009}, {@code 1010}, {@code 1012}, {@code
- * 1013} and {@code 1015} are always illegal codes.
- *
- *
*
*
- *