Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.net.http/share/classes/java/net/http/WebSocket.java
41159 views
1
/*
2
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package java.net.http;
27
28
import java.io.IOException;
29
import java.net.URI;
30
import java.nio.ByteBuffer;
31
import java.time.Duration;
32
import java.util.concurrent.CompletableFuture;
33
import java.util.concurrent.CompletionStage;
34
35
/**
36
* A WebSocket Client.
37
*
38
* <p> {@code WebSocket} instances are created through {@link WebSocket.Builder}.
39
*
40
* <p> WebSocket has an input and an output side. These sides are independent
41
* from each other. A side can either be open or closed. Once closed, the side
42
* remains closed. WebSocket messages are sent through a {@code WebSocket} and
43
* received through a {@code WebSocket.Listener} associated with it. Messages
44
* can be sent until the WebSocket's output is closed, and received until the
45
* WebSocket's input is closed.
46
*
47
* <p> A send method is any of the {@code sendText}, {@code sendBinary},
48
* {@code sendPing}, {@code sendPong} and {@code sendClose} methods of
49
* {@code WebSocket}. A send method initiates a send operation and returns a
50
* {@code CompletableFuture} which completes once the operation has completed.
51
* If the {@code CompletableFuture} completes normally the operation is
52
* considered succeeded. If the {@code CompletableFuture} completes
53
* exceptionally, the operation is considered failed. An operation that has been
54
* initiated but not yet completed is considered pending.
55
*
56
* <p> A receive method is any of the {@code onText}, {@code onBinary},
57
* {@code onPing}, {@code onPong} and {@code onClose} methods of
58
* {@code Listener}. WebSocket initiates a receive operation by invoking a
59
* receive method on the listener. The listener then must return a
60
* {@code CompletionStage} which completes once the operation has completed.
61
*
62
* <p> To control receiving of messages, a WebSocket maintains an
63
* <a id="counter">internal counter</a>. This counter's value is a number of
64
* times the WebSocket has yet to invoke a receive method. While this counter is
65
* zero the WebSocket does not invoke receive methods. The counter is
66
* incremented by {@code n} when {@code request(n)} is called. The counter is
67
* decremented by one when the WebSocket invokes a receive method.
68
* {@code onOpen} and {@code onError} are not receive methods. WebSocket invokes
69
* {@code onOpen} prior to any other methods on the listener. WebSocket invokes
70
* {@code onOpen} at most once. WebSocket may invoke {@code onError} at any
71
* given time. If the WebSocket invokes {@code onError} or {@code onClose}, then
72
* no further listener's methods will be invoked, no matter the value of the
73
* counter. For a newly built WebSocket the counter is zero.
74
*
75
* <p> Unless otherwise stated, {@code null} arguments will cause methods
76
* of {@code WebSocket} to throw {@code NullPointerException}, similarly,
77
* {@code WebSocket} will not pass {@code null} arguments to methods of
78
* {@code Listener}. The state of a WebSocket is not changed by the invocations
79
* that throw or return a {@code CompletableFuture} that completes with one of
80
* the {@code NullPointerException}, {@code IllegalArgumentException},
81
* {@code IllegalStateException} exceptions.
82
*
83
* <p> {@code WebSocket} handles received Ping and Close messages automatically
84
* (as per the WebSocket Protocol) by replying with Pong and Close messages. If
85
* the listener receives Ping or Close messages, no mandatory actions from the
86
* listener are required.
87
*
88
* @apiNote The relationship between a WebSocket and the associated Listener is
89
* analogous to that of a Subscription and the associated Subscriber of type
90
* {@link java.util.concurrent.Flow}.
91
*
92
* @since 11
93
*/
94
public interface WebSocket {
95
96
/**
97
* The WebSocket Close message status code (<code>{@value}</code>),
98
* indicating normal closure, meaning that the purpose for which the
99
* connection was established has been fulfilled.
100
*
101
* @see #sendClose(int, String)
102
* @see Listener#onClose(WebSocket, int, String)
103
*/
104
int NORMAL_CLOSURE = 1000;
105
106
/**
107
* A builder of {@linkplain WebSocket WebSocket Clients}.
108
*
109
* <p> Builders are created by invoking
110
* {@link HttpClient#newWebSocketBuilder HttpClient.newWebSocketBuilder}.
111
* The intermediate (setter-like) methods change the state of the builder
112
* and return the same builder they have been invoked on. If an intermediate
113
* method is not invoked, an appropriate default value (or behavior) will be
114
* assumed. A {@code Builder} is not safe for use by multiple threads
115
* without external synchronization.
116
*
117
* @since 11
118
*/
119
interface Builder {
120
121
/**
122
* Adds the given name-value pair to the list of additional HTTP headers
123
* sent during the opening handshake.
124
*
125
* <p> Headers defined in the
126
* <a href="https://tools.ietf.org/html/rfc6455#section-11.3">WebSocket
127
* Protocol</a> are illegal. If this method is not invoked, no
128
* additional HTTP headers will be sent.
129
*
130
* @param name
131
* the header name
132
* @param value
133
* the header value
134
*
135
* @return this builder
136
*/
137
Builder header(String name, String value);
138
139
/**
140
* Sets a timeout for establishing a WebSocket connection.
141
*
142
* <p> If the connection is not established within the specified
143
* duration then building of the {@code WebSocket} will fail with
144
* {@link HttpTimeoutException}. If this method is not invoked then the
145
* infinite timeout is assumed.
146
*
147
* @param timeout
148
* the timeout, non-{@linkplain Duration#isNegative() negative},
149
* non-{@linkplain Duration#ZERO ZERO}
150
*
151
* @return this builder
152
*/
153
Builder connectTimeout(Duration timeout);
154
155
/**
156
* Sets a request for the given subprotocols.
157
*
158
* <p> After the {@code WebSocket} has been built, the actual
159
* subprotocol can be queried through
160
* {@link WebSocket#getSubprotocol WebSocket.getSubprotocol()}.
161
*
162
* <p> Subprotocols are specified in the order of preference. The most
163
* preferred subprotocol is specified first. If there are any additional
164
* subprotocols they are enumerated from the most preferred to the least
165
* preferred.
166
*
167
* <p> Subprotocols not conforming to the syntax of subprotocol
168
* identifiers are illegal. If this method is not invoked then no
169
* subprotocols will be requested.
170
*
171
* @param mostPreferred
172
* the most preferred subprotocol
173
* @param lesserPreferred
174
* the lesser preferred subprotocols
175
*
176
* @return this builder
177
*/
178
Builder subprotocols(String mostPreferred, String... lesserPreferred);
179
180
/**
181
* Builds a {@link WebSocket} connected to the given {@code URI} and
182
* associated with the given {@code Listener}.
183
*
184
* <p> Returns a {@code CompletableFuture} which will either complete
185
* normally with the resulting {@code WebSocket} or complete
186
* exceptionally with one of the following errors:
187
* <ul>
188
* <li> {@link IOException} -
189
* if an I/O error occurs
190
* <li> {@link WebSocketHandshakeException} -
191
* if the opening handshake fails
192
* <li> {@link HttpTimeoutException} -
193
* if the opening handshake does not complete within
194
* the timeout
195
* <li> {@link InterruptedException} -
196
* if the operation is interrupted
197
* <li> {@link SecurityException} -
198
* if a security manager has been installed and it denies
199
* {@link java.net.URLPermission access} to {@code uri}.
200
* <a href="HttpClient.html#securitychecks">Security checks</a>
201
* contains more information relating to the security context
202
* in which the listener is invoked.
203
* <li> {@link IllegalArgumentException} -
204
* if any of the arguments of this builder's methods are
205
* illegal
206
* </ul>
207
*
208
* @param uri
209
* the WebSocket URI
210
* @param listener
211
* the listener
212
*
213
* @return a {@code CompletableFuture} with the {@code WebSocket}
214
*/
215
CompletableFuture<WebSocket> buildAsync(URI uri, Listener listener);
216
}
217
218
/**
219
* The receiving interface of {@code WebSocket}.
220
*
221
* <p> A {@code WebSocket} invokes methods of the associated listener
222
* passing itself as an argument. These methods are invoked in a thread-safe
223
* manner, such that the next invocation may start only after the previous
224
* one has finished.
225
*
226
* <p> When data has been received, the {@code WebSocket} invokes a receive
227
* method. Methods {@code onText}, {@code onBinary}, {@code onPing} and
228
* {@code onPong} must return a {@code CompletionStage} that completes once
229
* the message has been received by the listener. If a listener's method
230
* returns {@code null} rather than a {@code CompletionStage},
231
* {@code WebSocket} will behave as if the listener returned a
232
* {@code CompletionStage} that is already completed normally.
233
*
234
* <p> An {@code IOException} raised in {@code WebSocket} will result in an
235
* invocation of {@code onError} with that exception (if the input is not
236
* closed). Unless otherwise stated if the listener's method throws an
237
* exception or a {@code CompletionStage} returned from a method completes
238
* exceptionally, the WebSocket will invoke {@code onError} with this
239
* exception.
240
*
241
* @apiNote The strict sequential order of invocations from
242
* {@code WebSocket} to {@code Listener} means, in particular, that the
243
* {@code Listener}'s methods are treated as non-reentrant. This means that
244
* {@code Listener} implementations do not need to be concerned with
245
* possible recursion or the order in which they invoke
246
* {@code WebSocket.request} in relation to their processing logic.
247
*
248
* <p> Careful attention may be required if a listener is associated
249
* with more than a single {@code WebSocket}. In this case invocations
250
* related to different instances of {@code WebSocket} may not be ordered
251
* and may even happen concurrently.
252
*
253
* <p> {@code CompletionStage}s returned from the receive methods have
254
* nothing to do with the
255
* <a href="WebSocket.html#counter">counter of invocations</a>.
256
* Namely, a {@code CompletionStage} does not have to be completed in order
257
* to receive more invocations of the listener's methods.
258
* Here is an example of a listener that requests invocations, one at a
259
* time, until a complete message has been accumulated, then processes
260
* the result, and completes the {@code CompletionStage}:
261
* <pre>{@code WebSocket.Listener listener = new WebSocket.Listener() {
262
*
263
* List<CharSequence> parts = new ArrayList<>();
264
* CompletableFuture<?> accumulatedMessage = new CompletableFuture<>();
265
*
266
* public CompletionStage<?> onText(WebSocket webSocket,
267
* CharSequence message,
268
* boolean last) {
269
* parts.add(message);
270
* webSocket.request(1);
271
* if (last) {
272
* processWholeText(parts);
273
* parts = new ArrayList<>();
274
* accumulatedMessage.complete(null);
275
* CompletionStage<?> cf = accumulatedMessage;
276
* accumulatedMessage = new CompletableFuture<>();
277
* return cf;
278
* }
279
* return accumulatedMessage;
280
* }
281
* ...
282
* } } </pre>
283
*
284
* @since 11
285
*/
286
interface Listener {
287
288
/**
289
* A {@code WebSocket} has been connected.
290
*
291
* <p> This is the initial invocation and it is made once. It is
292
* typically used to make a request for more invocations.
293
*
294
* @implSpec The default implementation is equivalent to:
295
* <pre>{@code webSocket.request(1); }</pre>
296
*
297
* @param webSocket
298
* the WebSocket that has been connected
299
*/
300
default void onOpen(WebSocket webSocket) { webSocket.request(1); }
301
302
/**
303
* A textual data has been received.
304
*
305
* <p> Return a {@code CompletionStage} which will be used by the
306
* {@code WebSocket} as an indication it may reclaim the
307
* {@code CharSequence}. Do not access the {@code CharSequence} after
308
* this {@code CompletionStage} has completed.
309
*
310
* @implSpec The default implementation is equivalent to:
311
* <pre>{@code webSocket.request(1);
312
* return null; }</pre>
313
*
314
* @implNote The {@code data} is always a legal UTF-16 sequence.
315
*
316
* @param webSocket
317
* the WebSocket on which the data has been received
318
* @param data
319
* the data
320
* @param last
321
* whether this invocation completes the message
322
*
323
* @return a {@code CompletionStage} which completes when the
324
* {@code CharSequence} may be reclaimed; or {@code null} if it may be
325
* reclaimed immediately
326
*/
327
default CompletionStage<?> onText(WebSocket webSocket,
328
CharSequence data,
329
boolean last) {
330
webSocket.request(1);
331
return null;
332
}
333
334
/**
335
* A binary data has been received.
336
*
337
* <p> This data is located in bytes from the buffer's position to its
338
* limit.
339
*
340
* <p> Return a {@code CompletionStage} which will be used by the
341
* {@code WebSocket} as an indication it may reclaim the
342
* {@code ByteBuffer}. Do not access the {@code ByteBuffer} after
343
* this {@code CompletionStage} has completed.
344
*
345
* @implSpec The default implementation is equivalent to:
346
* <pre>{@code webSocket.request(1);
347
* return null; }</pre>
348
*
349
* @param webSocket
350
* the WebSocket on which the data has been received
351
* @param data
352
* the data
353
* @param last
354
* whether this invocation completes the message
355
*
356
* @return a {@code CompletionStage} which completes when the
357
* {@code ByteBuffer} may be reclaimed; or {@code null} if it may be
358
* reclaimed immediately
359
*/
360
default CompletionStage<?> onBinary(WebSocket webSocket,
361
ByteBuffer data,
362
boolean last) {
363
webSocket.request(1);
364
return null;
365
}
366
367
/**
368
* A Ping message has been received.
369
*
370
* <p> As guaranteed by the WebSocket Protocol, the message consists of
371
* not more than {@code 125} bytes. These bytes are located from the
372
* buffer's position to its limit.
373
*
374
* <p> Given that the WebSocket implementation will automatically send a
375
* reciprocal pong when a ping is received, it is rarely required to
376
* send a pong message explicitly when a ping is received.
377
*
378
* <p> Return a {@code CompletionStage} which will be used by the
379
* {@code WebSocket} as a signal it may reclaim the
380
* {@code ByteBuffer}. Do not access the {@code ByteBuffer} after
381
* this {@code CompletionStage} has completed.
382
*
383
* @implSpec The default implementation is equivalent to:
384
* <pre>{@code webSocket.request(1);
385
* return null; }</pre>
386
*
387
* @param webSocket
388
* the WebSocket on which the message has been received
389
* @param message
390
* the message
391
*
392
* @return a {@code CompletionStage} which completes when the
393
* {@code ByteBuffer} may be reclaimed; or {@code null} if it may be
394
* reclaimed immediately
395
*/
396
default CompletionStage<?> onPing(WebSocket webSocket,
397
ByteBuffer message) {
398
webSocket.request(1);
399
return null;
400
}
401
402
/**
403
* A Pong message has been received.
404
*
405
* <p> As guaranteed by the WebSocket Protocol, the message consists of
406
* not more than {@code 125} bytes. These bytes are located from the
407
* buffer's position to its limit.
408
*
409
* <p> Return a {@code CompletionStage} which will be used by the
410
* {@code WebSocket} as a signal it may reclaim the
411
* {@code ByteBuffer}. Do not access the {@code ByteBuffer} after
412
* this {@code CompletionStage} has completed.
413
*
414
* @implSpec The default implementation is equivalent to:
415
* <pre>{@code webSocket.request(1);
416
* return null; }</pre>
417
*
418
* @param webSocket
419
* the WebSocket on which the message has been received
420
* @param message
421
* the message
422
*
423
* @return a {@code CompletionStage} which completes when the
424
* {@code ByteBuffer} may be reclaimed; or {@code null} if it may be
425
* reclaimed immediately
426
*/
427
default CompletionStage<?> onPong(WebSocket webSocket,
428
ByteBuffer message) {
429
webSocket.request(1);
430
return null;
431
}
432
433
/**
434
* Receives a Close message indicating the WebSocket's input has been
435
* closed.
436
*
437
* <p> This is the last invocation from the specified {@code WebSocket}.
438
* By the time this invocation begins the WebSocket's input will have
439
* been closed.
440
*
441
* <p> A Close message consists of a status code and a reason for
442
* closing. The status code is an integer from the range
443
* {@code 1000 <= code <= 65535}. The {@code reason} is a string which
444
* has a UTF-8 representation not longer than {@code 123} bytes.
445
*
446
* <p> If the WebSocket's output is not already closed, the
447
* {@code CompletionStage} returned by this method will be used as an
448
* indication that the WebSocket's output may be closed. The WebSocket
449
* will close its output at the earliest of completion of the returned
450
* {@code CompletionStage} or invoking either of the {@code sendClose}
451
* or {@code abort} methods.
452
*
453
* @apiNote Returning a {@code CompletionStage} that never completes,
454
* effectively disables the reciprocating closure of the output.
455
*
456
* <p> To specify a custom closure code or reason code the
457
* {@code sendClose} method may be invoked from inside the
458
* {@code onClose} invocation:
459
* <pre>{@code public CompletionStage<?> onClose(WebSocket webSocket,
460
* int statusCode,
461
* String reason) {
462
* webSocket.sendClose(CUSTOM_STATUS_CODE, CUSTOM_REASON);
463
* return new CompletableFuture<Void>();
464
* } } </pre>
465
*
466
* @implSpec The default implementation of this method returns
467
* {@code null}, indicating that the output should be closed
468
* immediately.
469
*
470
* @param webSocket
471
* the WebSocket on which the message has been received
472
* @param statusCode
473
* the status code
474
* @param reason
475
* the reason
476
*
477
* @return a {@code CompletionStage} which completes when the
478
* {@code WebSocket} may be closed; or {@code null} if it may be
479
* closed immediately
480
*/
481
default CompletionStage<?> onClose(WebSocket webSocket,
482
int statusCode,
483
String reason) {
484
return null;
485
}
486
487
/**
488
* An error has occurred.
489
*
490
* <p> This is the last invocation from the specified WebSocket. By the
491
* time this invocation begins both the WebSocket's input and output
492
* will have been closed. A WebSocket may invoke this method on the
493
* associated listener at any time after it has invoked {@code onOpen},
494
* regardless of whether or not any invocations have been requested from
495
* the WebSocket.
496
*
497
* <p> If an exception is thrown from this method, resulting behavior is
498
* undefined.
499
*
500
* @param webSocket
501
* the WebSocket on which the error has occurred
502
* @param error
503
* the error
504
*/
505
default void onError(WebSocket webSocket, Throwable error) { }
506
}
507
508
/**
509
* Sends textual data with characters from the given character sequence.
510
*
511
* <p> The character sequence must not be modified until the
512
* {@code CompletableFuture} returned from this method has completed.
513
*
514
* <p> A {@code CompletableFuture} returned from this method can
515
* complete exceptionally with:
516
* <ul>
517
* <li> {@link IllegalStateException} -
518
* if there is a pending text or binary send operation
519
* or if the previous binary data does not complete the message
520
* <li> {@link IOException} -
521
* if an I/O error occurs, or if the output is closed
522
* </ul>
523
*
524
* @implNote If {@code data} is a malformed UTF-16 sequence, the operation
525
* will fail with {@code IOException}.
526
*
527
* @param data
528
* the data
529
* @param last
530
* {@code true} if this invocation completes the message,
531
* {@code false} otherwise
532
*
533
* @return a {@code CompletableFuture} that completes, with this WebSocket,
534
* when the data has been sent
535
*/
536
CompletableFuture<WebSocket> sendText(CharSequence data, boolean last);
537
538
/**
539
* Sends binary data with bytes from the given buffer.
540
*
541
* <p> The data is located in bytes from the buffer's position to its limit.
542
* Upon normal completion of a {@code CompletableFuture} returned from this
543
* method the buffer will have no remaining bytes. The buffer must not be
544
* accessed until after that.
545
*
546
* <p> The {@code CompletableFuture} returned from this method can
547
* complete exceptionally with:
548
* <ul>
549
* <li> {@link IllegalStateException} -
550
* if there is a pending text or binary send operation
551
* or if the previous textual data does not complete the message
552
* <li> {@link IOException} -
553
* if an I/O error occurs, or if the output is closed
554
* </ul>
555
*
556
* @param data
557
* the data
558
* @param last
559
* {@code true} if this invocation completes the message,
560
* {@code false} otherwise
561
*
562
* @return a {@code CompletableFuture} that completes, with this WebSocket,
563
* when the data has been sent
564
*/
565
CompletableFuture<WebSocket> sendBinary(ByteBuffer data, boolean last);
566
567
/**
568
* Sends a Ping message with bytes from the given buffer.
569
*
570
* <p> The message consists of not more than {@code 125} bytes from the
571
* buffer's position to its limit. Upon normal completion of a
572
* {@code CompletableFuture} returned from this method the buffer will
573
* have no remaining bytes. The buffer must not be accessed until after that.
574
*
575
* <p> The {@code CompletableFuture} returned from this method can
576
* complete exceptionally with:
577
* <ul>
578
* <li> {@link IllegalStateException} -
579
* if there is a pending ping or pong send operation
580
* <li> {@link IllegalArgumentException} -
581
* if the message is too long
582
* <li> {@link IOException} -
583
* if an I/O error occurs, or if the output is closed
584
* </ul>
585
*
586
* @param message
587
* the message
588
*
589
* @return a {@code CompletableFuture} that completes, with this WebSocket,
590
* when the Ping message has been sent
591
*/
592
CompletableFuture<WebSocket> sendPing(ByteBuffer message);
593
594
/**
595
* Sends a Pong message with bytes from the given buffer.
596
*
597
* <p> The message consists of not more than {@code 125} bytes from the
598
* buffer's position to its limit. Upon normal completion of a
599
* {@code CompletableFuture} returned from this method the buffer will have
600
* no remaining bytes. The buffer must not be accessed until after that.
601
*
602
* <p> Given that the WebSocket implementation will automatically send a
603
* reciprocal pong when a ping is received, it is rarely required to send a
604
* pong message explicitly.
605
*
606
* <p> The {@code CompletableFuture} returned from this method can
607
* complete exceptionally with:
608
* <ul>
609
* <li> {@link IllegalStateException} -
610
* if there is a pending ping or pong send operation
611
* <li> {@link IllegalArgumentException} -
612
* if the message is too long
613
* <li> {@link IOException} -
614
* if an I/O error occurs, or if the output is closed
615
* </ul>
616
*
617
* @param message
618
* the message
619
*
620
* @return a {@code CompletableFuture} that completes, with this WebSocket,
621
* when the Pong message has been sent
622
*/
623
CompletableFuture<WebSocket> sendPong(ByteBuffer message);
624
625
/**
626
* Initiates an orderly closure of this WebSocket's output by
627
* sending a Close message with the given status code and the reason.
628
*
629
* <p> The {@code statusCode} is an integer from the range
630
* {@code 1000 <= code <= 4999}. Status codes {@code 1002}, {@code 1003},
631
* {@code 1006}, {@code 1007}, {@code 1009}, {@code 1010}, {@code 1012},
632
* {@code 1013} and {@code 1015} are illegal. Behaviour in respect to other
633
* status codes is implementation-specific. A legal {@code reason} is a
634
* string that has a UTF-8 representation not longer than {@code 123} bytes.
635
*
636
* <p> A {@code CompletableFuture} returned from this method can
637
* complete exceptionally with:
638
* <ul>
639
* <li> {@link IllegalArgumentException} -
640
* if {@code statusCode} is illegal, or
641
* if {@code reason} is illegal
642
* <li> {@link IOException} -
643
* if an I/O error occurs, or if the output is closed
644
* </ul>
645
*
646
* <p> Unless the {@code CompletableFuture} returned from this method
647
* completes with {@code IllegalArgumentException}, or the method throws
648
* {@code NullPointerException}, the output will be closed.
649
*
650
* <p> If not already closed, the input remains open until a Close message
651
* {@linkplain Listener#onClose(WebSocket, int, String) received}, or
652
* {@code abort} is invoked, or an
653
* {@linkplain Listener#onError(WebSocket, Throwable) error} occurs.
654
*
655
* @apiNote Use the provided integer constant {@link #NORMAL_CLOSURE} as a
656
* status code and an empty string as a reason in a typical case:
657
* <pre>{@code CompletableFuture<WebSocket> webSocket = ...
658
* webSocket.thenCompose(ws -> ws.sendText("Hello, ", false))
659
* .thenCompose(ws -> ws.sendText("world!", true))
660
* .thenCompose(ws -> ws.sendClose(WebSocket.NORMAL_CLOSURE, ""))
661
* .join(); }</pre>
662
*
663
* The {@code sendClose} method does not close this WebSocket's input. It
664
* merely closes this WebSocket's output by sending a Close message. To
665
* enforce closing the input, invoke the {@code abort} method. Here is an
666
* example of an application that sends a Close message, and then starts a
667
* timer. Once no data has been received within the specified timeout, the
668
* timer goes off and the alarm aborts {@code WebSocket}:
669
* <pre>{@code MyAlarm alarm = new MyAlarm(webSocket::abort);
670
* WebSocket.Listener listener = new WebSocket.Listener() {
671
*
672
* public CompletionStage<?> onText(WebSocket webSocket,
673
* CharSequence data,
674
* boolean last) {
675
* alarm.snooze();
676
* ...
677
* }
678
* ...
679
* };
680
* ...
681
* Runnable startTimer = () -> {
682
* MyTimer idleTimer = new MyTimer();
683
* idleTimer.add(alarm, 30, TimeUnit.SECONDS);
684
* };
685
* webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok").thenRun(startTimer);
686
* } </pre>
687
*
688
* @param statusCode
689
* the status code
690
* @param reason
691
* the reason
692
*
693
* @return a {@code CompletableFuture} that completes, with this WebSocket,
694
* when the Close message has been sent
695
*/
696
CompletableFuture<WebSocket> sendClose(int statusCode, String reason);
697
698
/**
699
* Increments the counter of invocations of receive methods.
700
*
701
* <p> This WebSocket will invoke {@code onText}, {@code onBinary},
702
* {@code onPing}, {@code onPong} or {@code onClose} methods on the
703
* associated listener (i.e. receive methods) up to {@code n} more times.
704
*
705
* @apiNote The parameter of this method is the number of invocations being
706
* requested from this WebSocket to the associated listener, not the number
707
* of messages. Sometimes a message may be delivered to the listener in a
708
* single invocation, but not always. For example, Ping, Pong and Close
709
* messages are delivered in a single invocation of {@code onPing},
710
* {@code onPong} and {@code onClose} methods respectively. However, whether
711
* or not Text and Binary messages are delivered in a single invocation of
712
* {@code onText} and {@code onBinary} methods depends on the boolean
713
* argument ({@code last}) of these methods. If {@code last} is
714
* {@code false}, then there is more to a message than has been delivered to
715
* the invocation.
716
*
717
* <p> Here is an example of a listener that requests invocations, one at a
718
* time, until a complete message has been accumulated, and then processes
719
* the result:
720
* <pre>{@code WebSocket.Listener listener = new WebSocket.Listener() {
721
*
722
* StringBuilder text = new StringBuilder();
723
*
724
* public CompletionStage<?> onText(WebSocket webSocket,
725
* CharSequence message,
726
* boolean last) {
727
* text.append(message);
728
* if (last) {
729
* processCompleteTextMessage(text);
730
* text = new StringBuilder();
731
* }
732
* webSocket.request(1);
733
* return null;
734
* }
735
* ...
736
* } } </pre>
737
*
738
* @param n
739
* the number of invocations
740
*
741
* @throws IllegalArgumentException
742
* if {@code n <= 0}
743
*/
744
void request(long n);
745
746
/**
747
* Returns the subprotocol used by this WebSocket.
748
*
749
* @return the subprotocol, or an empty string if there's no subprotocol
750
*/
751
String getSubprotocol();
752
753
/**
754
* Tells whether this WebSocket's output is closed.
755
*
756
* <p> If this method returns {@code true}, subsequent invocations will also
757
* return {@code true}.
758
*
759
* @return {@code true} if closed, {@code false} otherwise
760
*/
761
boolean isOutputClosed();
762
763
/**
764
* Tells whether this WebSocket's input is closed.
765
*
766
* <p> If this method returns {@code true}, subsequent invocations will also
767
* return {@code true}.
768
*
769
* @return {@code true} if closed, {@code false} otherwise
770
*/
771
boolean isInputClosed();
772
773
/**
774
* Closes this WebSocket's input and output abruptly.
775
*
776
* <p> When this method returns both the input and the output will have been
777
* closed. Any pending send operations will fail with {@code IOException}.
778
* Subsequent invocations of {@code abort} will have no effect.
779
*/
780
void abort();
781
}
782
783