8156650: Simplify Text message support in WebSocket API
authorprappo
Tue, 07 Jun 2016 12:29:19 +0100
changeset 38856 cc3a0d1e96e0
parent 38855 4e587173e37e
child 38857 da63f7ec513b
8156650: Simplify Text message support in WebSocket API Reviewed-by: rriggs
jdk/src/java.httpclient/share/classes/java/net/http/WS.java
jdk/src/java.httpclient/share/classes/java/net/http/WSDisposableText.java
jdk/src/java.httpclient/share/classes/java/net/http/WSFrameConsumer.java
jdk/src/java.httpclient/share/classes/java/net/http/WSMessageConsumer.java
jdk/src/java.httpclient/share/classes/java/net/http/WSReceiver.java
jdk/src/java.httpclient/share/classes/java/net/http/WebSocket.java
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WS.java	Tue Jun 07 10:33:38 2016 +0800
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WS.java	Tue Jun 07 12:29:19 2016 +0100
@@ -95,11 +95,6 @@
     }
 
     @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");
         synchronized (stateLock) {
@@ -239,7 +234,7 @@
             }
 
             @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);
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSDisposableText.java	Tue Jun 07 10:33:38 2016 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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();
-    }
-}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSFrameConsumer.java	Tue Jun 07 10:33:38 2016 +0800
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSFrameConsumer.java	Tue Jun 07 12:29:19 2016 +0100
@@ -214,7 +214,7 @@
                 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);
                 }
             }
         }
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageConsumer.java	Tue Jun 07 10:33:38 2016 +0800
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageConsumer.java	Tue Jun 07 12:29:19 2016 +0100
@@ -27,10 +27,11 @@
 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);
 
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSReceiver.java	Tue Jun 07 10:33:38 2016 +0800
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSReceiver.java	Tue Jun 07 12:29:19 2016 +0100
@@ -29,6 +29,7 @@
 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 @@
     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;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WebSocket.java	Tue Jun 07 10:33:38 2016 +0800
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WebSocket.java	Tue Jun 07 12:29:19 2016 +0100
@@ -264,7 +264,7 @@
      * <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 @@
          * @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 @@
          * 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 @@
     }
 
     /**
-     * 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 @@
      *          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 @@
      * 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 @@
      * 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 @@
      * @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 @@
             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();
-    }
 }