From b263937bb25964b4a2e1d4e8f5f2ba2c81279208 Mon Sep 17 00:00:00 2001 From: Pavel Rappo Date: Tue, 7 Jun 2016 12:29:19 +0100 Subject: [PATCH] 8156650: Simplify Text message support in WebSocket API Reviewed-by: rriggs --- .../share/classes/java/net/http/WS.java | 7 +- .../java/net/http/WSDisposableText.java | 67 ---------- .../java/net/http/WSFrameConsumer.java | 2 +- .../java/net/http/WSMessageConsumer.java | 3 +- .../classes/java/net/http/WSReceiver.java | 5 +- .../classes/java/net/http/WebSocket.java | 117 +++--------------- 6 files changed, 24 insertions(+), 177 deletions(-) delete mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/WSDisposableText.java diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/WS.java b/jdk/src/java.httpclient/share/classes/java/net/http/WS.java index d970b5ecd2f..da8d400836d 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/WS.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/WS.java @@ -94,11 +94,6 @@ final class WS implements WebSocket { receiver.start(); } - @Override - public CompletableFuture sendText(ByteBuffer message, boolean isLast) { - throw new UnsupportedOperationException("Not implemented"); - } - @Override public CompletableFuture sendText(CharSequence message, boolean isLast) { requireNonNull(message, "message"); @@ -239,7 +234,7 @@ final class WS implements WebSocket { } @Override - public CompletionStage onText(WebSocket webSocket, Text message, + public CompletionStage onText(WebSocket webSocket, CharSequence message, MessagePart part) { synchronized (visibilityLock) { return listener.onText(webSocket, message, part); diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/WSDisposableText.java b/jdk/src/java.httpclient/share/classes/java/net/http/WSDisposableText.java deleted file mode 100644 index 08f71236f63..00000000000 --- a/jdk/src/java.httpclient/share/classes/java/net/http/WSDisposableText.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2016, 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 - * under the terms of the GNU General License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package java.net.http; - -import java.nio.ByteBuffer; -import java.nio.CharBuffer; - -final class WSDisposableText implements WebSocket.Text, WSDisposable { - - private final WSShared text; - - WSDisposableText(WSShared text) { - this.text = text; - } - - @Override - public int length() { - return text.buffer().length(); - } - - @Override - public char charAt(int index) { - return text.buffer().charAt(index); - } - - @Override - public CharSequence subSequence(int start, int end) { - return text.buffer().subSequence(start, end); - } - - @Override - public ByteBuffer asByteBuffer() { - throw new UnsupportedOperationException("To be removed from the API"); - } - - @Override - public String toString() { - return text.buffer().toString(); - } - - @Override - public void dispose() { - text.dispose(); - } -} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/WSFrameConsumer.java b/jdk/src/java.httpclient/share/classes/java/net/http/WSFrameConsumer.java index 504d72ed462..9d0521e9700 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/WSFrameConsumer.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSFrameConsumer.java @@ -214,7 +214,7 @@ final class WSFrameConsumer implements WSFrame.Consumer { if (!(binaryNonEmpty && !textData.hasRemaining())) { // If there's a binary data, that result in no text, then we // don't deliver anything - output.onText(part, new WSDisposableText(textData)); + output.onText(part, textData); } } } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageConsumer.java b/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageConsumer.java index e80605df10e..69f46668cfb 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageConsumer.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageConsumer.java @@ -27,10 +27,11 @@ package java.net.http; import java.net.http.WebSocket.CloseCode; import java.net.http.WebSocket.MessagePart; import java.nio.ByteBuffer; +import java.nio.CharBuffer; interface WSMessageConsumer { - void onText(MessagePart part, WSDisposableText data); + void onText(MessagePart part, WSShared data); void onBinary(MessagePart part, WSShared data); diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/WSReceiver.java b/jdk/src/java.httpclient/share/classes/java/net/http/WSReceiver.java index da69958653d..7ce089b4a4a 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/WSReceiver.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSReceiver.java @@ -29,6 +29,7 @@ import java.io.UncheckedIOException; import java.net.ProtocolException; import java.net.http.WebSocket.Listener; import java.nio.ByteBuffer; +import java.nio.CharBuffer; import java.nio.channels.SelectionKey; import java.util.Optional; import java.util.concurrent.CompletionStage; @@ -169,11 +170,11 @@ final class WSReceiver { private final class MessageConsumer implements WSMessageConsumer { @Override - public void onText(WebSocket.MessagePart part, WSDisposableText data) { + public void onText(WebSocket.MessagePart part, WSShared data) { decrementDemand(); CompletionStage cs; try { - cs = listener.onText(webSocket, data, part); + cs = listener.onText(webSocket, data.buffer(), part); } catch (Exception e) { closeExceptionally(new RuntimeException("onText threw an exception", e)); return; diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/WebSocket.java b/jdk/src/java.httpclient/share/classes/java/net/http/WebSocket.java index 200f12332a9..0b7123772f7 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/WebSocket.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/WebSocket.java @@ -264,7 +264,7 @@ public interface WebSocket { *
    *
  • {@link #onOpen onOpen}
    * This method is always the first to be invoked. - *
  • {@link #onText(WebSocket, WebSocket.Text, WebSocket.MessagePart) + *
  • {@link #onText(WebSocket, CharSequence, WebSocket.MessagePart) * onText}, {@link #onBinary(WebSocket, ByteBuffer, WebSocket.MessagePart) * onBinary}, {@link #onPing(WebSocket, ByteBuffer) onPing} and {@link * #onPong(WebSocket, ByteBuffer) onPong}
    @@ -375,6 +375,9 @@ public interface WebSocket { * @implSpec The default implementation {@linkplain WebSocket#request(long) * requests one more message}. * + * @implNote This implementation passes only complete UTF-16 sequences + * to the {@code onText} method. + * * @param webSocket * the WebSocket * @param message @@ -386,7 +389,7 @@ public interface WebSocket { * is done; or {@code null} if already done */ default CompletionStage onText(WebSocket webSocket, - Text message, + CharSequence message, MessagePart part) { webSocket.request(1); return null; @@ -596,60 +599,12 @@ public interface WebSocket { } /** - * Sends a Text message with bytes from the given {@code ByteBuffer}. + * Sends a Text message with characters from the given {@code CharSequence}. * *

    Returns immediately with a {@code CompletableFuture} which * completes normally when the message has been sent, or completes * exceptionally if an error occurs. * - *

    This message may be a partial UTF-8 sequence. However, the - * concatenation of all messages through the last must be a whole UTF-8 - * sequence. - * - *

    The {@code ByteBuffer} should not be modified until the returned - * {@code CompletableFuture} completes (either normally or exceptionally). - * - *

    The returned {@code CompletableFuture} can complete exceptionally - * with: - *

      - *
    • {@link IOException} - * if an I/O error occurs during this operation; or the - * {@code WebSocket} closes while this operation is in progress; - * or the {@code message} is a malformed UTF-8 sequence - *
    - * - * @param message - * the message - * @param isLast - * {@code true} if this is the final part of the message, - * {@code false} otherwise - * - * @return a CompletableFuture of Void - * - * @throws IllegalStateException - * if the WebSocket is closed - * @throws IllegalStateException - * if a Close message has been sent already - * @throws IllegalStateException - * if there is an outstanding send operation - * @throws IllegalStateException - * if a previous Binary message - * was not sent with {@code isLast == true} - */ - CompletableFuture sendText(ByteBuffer message, boolean isLast); - - /** - * Sends a Text message with characters from the given {@code - * CharSequence}. - * - *

    Returns immediately with a {@code CompletableFuture} which - * completes normally when the message has been sent, or completes - * exceptionally if an error occurs. - * - *

    This message may be a partial UTF-16 sequence. However, the - * concatenation of all messages through the last must be a whole UTF-16 - * sequence. - * *

    The {@code CharSequence} should not be modified until the returned * {@code CompletableFuture} completes (either normally or exceptionally). * @@ -662,6 +617,10 @@ public interface WebSocket { * or the {@code message} is a malformed UTF-16 sequence *

* + * @implNote This implementation does not accept partial UTF-16 + * sequences. In case such a sequence is passed, a returned {@code + * CompletableFuture} completes exceptionally. + * * @param message * the message * @param isLast @@ -700,9 +659,9 @@ public interface WebSocket { * with: *
    *
  • {@link IOException} - * if an I/O error occurs during this operation; or the - * {@code WebSocket} closes while this operation is in progress; - * or the message is a malformed UTF-16 sequence + * if an I/O error occurs during this operation; + * or the {@code WebSocket} closes while this operation is in progress; + * or the message is a malformed (or an incomplete) UTF-16 sequence *
* * @param message @@ -743,9 +702,9 @@ public interface WebSocket { * with: *
    *
  • {@link IOException} - * if an I/O error occurs during this operation; or the - * {@code WebSocket} closes while this operation is in progress; - * or the message is a malformed UTF-16 sequence + * if an I/O error occurs during this operation; + * or the {@code WebSocket} closes while this operation is in progress; + * or the message is a malformed (or an incomplete) UTF-16 sequence *
* * @param message @@ -1001,6 +960,7 @@ public interface WebSocket { * @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, the implementation * queues up these messages on the TCP connection and may eventually force * the sender to stop sending through TCP flow control. @@ -1242,47 +1202,4 @@ public interface WebSocket { return Map.entry(cc.getCode(), cc); } } - - /** - * A character sequence that provides access to the characters UTF-8 decoded - * from a message in a {@code ByteBuffer}. - * - * @since 9 - */ - interface Text extends CharSequence { - - // Methods from the CharSequence below are mentioned explicitly for the - // purpose of documentation, so when looking at javadoc it immediately - // obvious what methods Text has - - @Override - int length(); - - @Override - char charAt(int index); - - @Override - CharSequence subSequence(int start, int end); - - /** - * Returns a string containing the characters in this sequence in the - * same order as this sequence. The length of the string will be the - * length of this sequence. - * - * @return a string consisting of exactly this sequence of characters - */ - @Override - // TODO: remove the explicit javadoc above when: - // (JDK-8144034 has been resolved) AND (the comment is still identical - // to CharSequence#toString) - String toString(); - - /** - * Returns a read-only {@code ByteBuffer} containing the message encoded - * in UTF-8. - * - * @return a read-only ByteBuffer - */ - ByteBuffer asByteBuffer(); - } }