--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/WebSocket.java Wed Jan 31 16:18:41 2018 +0000
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/WebSocket.java Wed Jan 31 16:31:48 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -506,9 +506,8 @@
* <li> {@link IllegalArgumentException} -
* if {@code message} is a malformed UTF-16 sequence
* <li> {@link IllegalStateException} -
- * if {@code sendClose} has been invoked
- * or if the previous message has not been sent yet
- * or if a previous Binary message was sent with
+ * if the previous Text or Binary message has not been sent yet
+ * or if a previous Binary message has been sent with
* {@code isLast == false}
* <li> {@link IOException} -
* if an I/O error occurs
@@ -542,9 +541,8 @@
* complete exceptionally with:
* <ul>
* <li> {@link IllegalStateException} -
- * if {@code sendClose} has been invoked
- * or if the previous message has not been sent yet
- * or if a previous Text message was sent with
+ * if the previous Binary or Text message has not been sent yet
+ * or if a previous Text message has been sent with
* {@code isLast == false}
* <li> {@link IOException} -
* if an I/O error occurs
@@ -574,8 +572,6 @@
* <ul>
* <li> {@link IllegalArgumentException} -
* if the message is too long
- * <li> {@link IllegalStateException} -
- * if {@code sendClose} has been invoked
* <li> {@link IOException} -
* if an I/O error occurs
* </ul>
@@ -601,8 +597,6 @@
* <ul>
* <li> {@link IllegalArgumentException} -
* if the message is too long
- * <li> {@link IllegalStateException} -
- * if {@code sendClose} has been invoked
* <li> {@link IOException} -
* if an I/O error occurs
* </ul>
@@ -619,8 +613,6 @@
* Sends a Close message with the given status code and the reason,
* initiating an orderly closure.
*
- * <p> When this method returns the output will have been closed.
- *
* <p> 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},
@@ -640,6 +632,9 @@
* if an I/O error occurs
* </ul>
*
+ * <p> By the time the {@code CompletableFuture} returned from this method
+ * completes normally, the output 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
@@ -666,8 +661,6 @@
* {@code onBinary}, {@code onPing}, {@code onPong} or {@code onClose}
* methods up to {@code n} more times.
*
- * <p> This method may be invoked at any time.
- *
* @param n
* the number of messages requested
*
@@ -679,8 +672,6 @@
/**
* Returns the subprotocol for this {@code WebSocket}.
*
- * <p> 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
*/
@@ -691,7 +682,7 @@
* for sending messages.
*
* <p> If this method returns {@code true}, subsequent invocations will also
- * return {@code true}. This method may be invoked at any time.
+ * return {@code true}.
*
* @return {@code true} if closed, {@code false} otherwise
*/
@@ -702,7 +693,7 @@
* for receiving messages.
*
* <p> If this method returns {@code true}, subsequent invocations will also
- * return {@code true}. This method may be invoked at any time.
+ * return {@code true}.
*
* @return {@code true} if closed, {@code false} otherwise
*/
@@ -711,9 +702,8 @@
/**
* Closes this {@code WebSocket} abruptly.
*
- * <p> 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.
+ * <p> When this method returns both the input and the output will have been
+ * closed. Subsequent invocations will have no effect.
*
* @apiNote Depending on its implementation, the state (for example, whether
* or not a message is being transferred at the moment) and possible errors
--- a/test/jdk/java/net/httpclient/websocket/WebSocketTest.java Wed Jan 31 16:18:41 2018 +0000
+++ b/test/jdk/java/net/httpclient/websocket/WebSocketTest.java Wed Jan 31 16:31:48 2018 +0000
@@ -58,6 +58,39 @@
= IllegalStateException.class;
@Test
+ public void abort() throws IOException {
+ try (DummyWebSocketServer server = new DummyWebSocketServer()) {
+ server.open();
+ WebSocket ws = newHttpClient()
+ .newWebSocketBuilder()
+ .buildAsync(server.getURI(), new WebSocket.Listener() {
+ @Override
+ public void onOpen(WebSocket webSocket) { /* no initial request */ }
+ })
+ .join();
+
+ ws.abort();
+ // Each consecutive abort MUST be a no-op:
+ ws.abort();
+ assertTrue(ws.isInputClosed());
+ assertTrue(ws.isOutputClosed());
+ assertEquals(ws.getSubprotocol(), "");
+ ws.abort();
+ assertTrue(ws.isInputClosed());
+ assertTrue(ws.isOutputClosed());
+ assertEquals(ws.getSubprotocol(), "");
+ // At this point request MUST be a no-op:
+ ws.request(1);
+ ws.request(Long.MAX_VALUE);
+ // Throws IAE regardless of whether WebSocket is closed or not:
+ assertThrows(IAE, () -> ws.request(Integer.MIN_VALUE));
+ assertThrows(IAE, () -> ws.request(Long.MIN_VALUE));
+ assertThrows(IAE, () -> ws.request(-1));
+ assertThrows(IAE, () -> ws.request(0));
+ }
+ }
+
+ @Test
public void testNull() throws IOException {
try (DummyWebSocketServer server = new DummyWebSocketServer()) {
server.open();
@@ -197,6 +230,7 @@
assertCompletesExceptionally(IAE, ws.sendClose(Integer.MIN_VALUE, "a reason"));
assertThrows(IAE, () -> ws.request(Integer.MIN_VALUE));
+ assertThrows(IAE, () -> ws.request(Long.MIN_VALUE));
assertThrows(IAE, () -> ws.request(-1));
assertThrows(IAE, () -> ws.request(0));
}