8156650: Simplify Text message support in WebSocket API

Reviewed-by: rriggs
This commit is contained in:
Pavel Rappo 2016-06-07 12:29:19 +01:00
parent eb636ba047
commit b263937bb2
6 changed files with 24 additions and 177 deletions

View File

@ -94,11 +94,6 @@ final class WS implements WebSocket {
receiver.start();
}
@Override
public CompletableFuture<Void> sendText(ByteBuffer message, boolean isLast) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public CompletableFuture<Void> 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);

View File

@ -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<CharBuffer> text;
WSDisposableText(WSShared<CharBuffer> 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();
}
}

View File

@ -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);
}
}
}

View File

@ -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<CharBuffer> data);
void onBinary(MessagePart part, WSShared<ByteBuffer> data);

View File

@ -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<CharBuffer> 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;

View File

@ -264,7 +264,7 @@ public interface WebSocket {
* <ul>
* <li> {@link #onOpen onOpen} <br>
* This method is always the first to be invoked.
* <li> {@link #onText(WebSocket, WebSocket.Text, WebSocket.MessagePart)
* <li> {@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} <br>
@ -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}.
*
* <p> Returns immediately with a {@code CompletableFuture<Void>} which
* completes normally when the message has been sent, or completes
* exceptionally if an error occurs.
*
* <p> 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.
*
* <p> The {@code ByteBuffer} should not be modified until the returned
* {@code CompletableFuture} completes (either normally or exceptionally).
*
* <p> The returned {@code CompletableFuture} can complete exceptionally
* with:
* <ul>
* <li> {@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
* </ul>
*
* @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<Void> sendText(ByteBuffer message, boolean isLast);
/**
* Sends a Text message with characters from the given {@code
* CharSequence}.
*
* <p> Returns immediately with a {@code CompletableFuture<Void>} which
* completes normally when the message has been sent, or completes
* exceptionally if an error occurs.
*
* <p> 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.
*
* <p> 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
* </ul>
*
* @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:
* <ul>
* <li> {@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
* </ul>
*
* @param message
@ -743,9 +702,9 @@ public interface WebSocket {
* with:
* <ul>
* <li> {@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
* </ul>
*
* @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.
*
* <p> 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();
}
}