Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/javax/net/ssl/SSLParameters.java
41159 views
1
/*
2
* Copyright (c) 2005, 2021, 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 javax.net.ssl;
27
28
import java.security.AlgorithmConstraints;
29
import java.util.Map;
30
import java.util.List;
31
import java.util.HashMap;
32
import java.util.ArrayList;
33
import java.util.Collection;
34
import java.util.Collections;
35
import java.util.LinkedHashMap;
36
37
/**
38
* Encapsulates parameters for an SSL/TLS/DTLS connection. The parameters
39
* are the list of ciphersuites to be accepted in an SSL/TLS/DTLS handshake,
40
* the list of protocols to be allowed, the endpoint identification
41
* algorithm during SSL/TLS/DTLS handshaking, the Server Name Indication (SNI),
42
* the maximum network packet size, the algorithm constraints and whether
43
* SSL/TLS/DTLS servers should request or require client authentication, etc.
44
* <p>
45
* SSLParameters can be created via the constructors in this class.
46
* Objects can also be obtained using the {@code getSSLParameters()}
47
* methods in
48
* {@link SSLSocket#getSSLParameters SSLSocket} and
49
* {@link SSLServerSocket#getSSLParameters SSLServerSocket} and
50
* {@link SSLEngine#getSSLParameters SSLEngine} or the
51
* {@link SSLContext#getDefaultSSLParameters getDefaultSSLParameters()} and
52
* {@link SSLContext#getSupportedSSLParameters getSupportedSSLParameters()}
53
* methods in {@code SSLContext}.
54
* <p>
55
* SSLParameters can be applied to a connection via the methods
56
* {@link SSLSocket#setSSLParameters SSLSocket.setSSLParameters()} and
57
* {@link SSLServerSocket#setSSLParameters SSLServerSocket.setSSLParameters()}
58
* and {@link SSLEngine#setSSLParameters SSLEngine.setSSLParameters()}.
59
* <p>
60
* For example:
61
*
62
* <blockquote><pre>
63
* SSLParameters p = sslSocket.getSSLParameters();
64
* p.setProtocols(new String[] { "TLSv1.2" });
65
* p.setCipherSuites(
66
* new String[] { "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", ... });
67
* p.setApplicationProtocols(new String[] {"h2", "http/1.1"});
68
* sslSocket.setSSLParameters(p);
69
* </pre></blockquote>
70
*
71
* @see SSLSocket
72
* @see SSLEngine
73
* @see SSLContext
74
*
75
* @since 1.6
76
*/
77
public class SSLParameters {
78
79
private String[] cipherSuites;
80
private String[] protocols;
81
private boolean wantClientAuth;
82
private boolean needClientAuth;
83
private String identificationAlgorithm;
84
private AlgorithmConstraints algorithmConstraints;
85
private Map<Integer, SNIServerName> sniNames = null;
86
private Map<Integer, SNIMatcher> sniMatchers = null;
87
private boolean preferLocalCipherSuites;
88
private boolean enableRetransmissions = true;
89
private int maximumPacketSize = 0;
90
private String[] applicationProtocols = new String[0];
91
92
/**
93
* Constructs SSLParameters.
94
* <p>
95
* The values of cipherSuites, protocols, cryptographic algorithm
96
* constraints, endpoint identification algorithm, server names and
97
* server name matchers are set to {@code null}; useCipherSuitesOrder,
98
* wantClientAuth and needClientAuth are set to {@code false};
99
* enableRetransmissions is set to {@code true}; maximum network packet
100
* size is set to {@code 0}.
101
*/
102
public SSLParameters() {
103
// empty
104
}
105
106
/**
107
* Constructs SSLParameters from the specified array of ciphersuites.
108
* <p>
109
* Calling this constructor is equivalent to calling the no-args
110
* constructor followed by
111
* {@code setCipherSuites(cipherSuites);}. Note that the
112
* standard list of cipher suite names may be found in the <a href=
113
* "{@docRoot}/../specs/security/standard-names.html#jsse-cipher-suite-names">
114
* JSSE Cipher Suite Names</a> section of the Java Cryptography
115
* Architecture Standard Algorithm Name Documentation. Providers
116
* may support cipher suite names not found in this list.
117
*
118
* @param cipherSuites the array of ciphersuites (or null)
119
*/
120
public SSLParameters(String[] cipherSuites) {
121
setCipherSuites(cipherSuites);
122
}
123
124
/**
125
* Constructs SSLParameters from the specified array of ciphersuites
126
* and protocols.
127
* <p>
128
* Calling this constructor is equivalent to calling the no-args
129
* constructor followed by
130
* {@code setCipherSuites(cipherSuites); setProtocols(protocols);}.
131
* Note that the standard list of cipher suite names may be found in the
132
* <a href=
133
* "{@docRoot}/../specs/security/standard-names.html#jsse-cipher-suite-names">
134
* JSSE Cipher Suite Names</a> section of the Java Cryptography
135
* Architecture Standard Algorithm Name Documentation. Providers
136
* may support cipher suite names not found in this list.
137
*
138
* @param cipherSuites the array of ciphersuites (or null)
139
* @param protocols the array of protocols (or null)
140
*/
141
public SSLParameters(String[] cipherSuites, String[] protocols) {
142
setCipherSuites(cipherSuites);
143
setProtocols(protocols);
144
}
145
146
private static String[] clone(String[] s) {
147
return (s == null) ? null : s.clone();
148
}
149
150
/**
151
* Returns a copy of the array of ciphersuites or null if none
152
* have been set.
153
* <P>
154
* The returned array includes cipher suites from the list of standard
155
* cipher suite names in the <a href=
156
* "{@docRoot}/../specs/security/standard-names.html#jsse-cipher-suite-names">
157
* JSSE Cipher Suite Names</a> section of the Java Cryptography
158
* Architecture Standard Algorithm Name Documentation, and may also
159
* include other cipher suites that the provider supports.
160
*
161
* @return a copy of the array of ciphersuites or null if none
162
* have been set.
163
*/
164
public String[] getCipherSuites() {
165
return clone(cipherSuites);
166
}
167
168
/**
169
* Sets the array of ciphersuites.
170
*
171
* @param cipherSuites the array of ciphersuites (or null). Note that the
172
* standard list of cipher suite names may be found in the <a href=
173
* "{@docRoot}/../specs/security/standard-names.html#jsse-cipher-suite-names">
174
* JSSE Cipher Suite Names</a> section of the Java Cryptography
175
* Architecture Standard Algorithm Name Documentation. Providers
176
* may support cipher suite names not found in this list or might not
177
* use the recommended name for a certain cipher suite.
178
*/
179
public void setCipherSuites(String[] cipherSuites) {
180
this.cipherSuites = clone(cipherSuites);
181
}
182
183
/**
184
* Returns a copy of the array of protocols or null if none
185
* have been set.
186
*
187
* @return a copy of the array of protocols or null if none
188
* have been set.
189
*/
190
public String[] getProtocols() {
191
return clone(protocols);
192
}
193
194
/**
195
* Sets the array of protocols.
196
*
197
* @param protocols the array of protocols (or null)
198
*/
199
public void setProtocols(String[] protocols) {
200
this.protocols = clone(protocols);
201
}
202
203
/**
204
* Returns whether client authentication should be requested.
205
*
206
* @return whether client authentication should be requested.
207
*/
208
public boolean getWantClientAuth() {
209
return wantClientAuth;
210
}
211
212
/**
213
* Sets whether client authentication should be requested. Calling
214
* this method clears the {@code needClientAuth} flag.
215
*
216
* @param wantClientAuth whether client authentication should be requested
217
*/
218
public void setWantClientAuth(boolean wantClientAuth) {
219
this.wantClientAuth = wantClientAuth;
220
this.needClientAuth = false;
221
}
222
223
/**
224
* Returns whether client authentication should be required.
225
*
226
* @return whether client authentication should be required.
227
*/
228
public boolean getNeedClientAuth() {
229
return needClientAuth;
230
}
231
232
/**
233
* Sets whether client authentication should be required. Calling
234
* this method clears the {@code wantClientAuth} flag.
235
*
236
* @param needClientAuth whether client authentication should be required
237
*/
238
public void setNeedClientAuth(boolean needClientAuth) {
239
this.wantClientAuth = false;
240
this.needClientAuth = needClientAuth;
241
}
242
243
/**
244
* Returns the cryptographic algorithm constraints.
245
*
246
* @return the cryptographic algorithm constraints, or null if the
247
* constraints have not been set
248
*
249
* @see #setAlgorithmConstraints(AlgorithmConstraints)
250
*
251
* @since 1.7
252
*/
253
public AlgorithmConstraints getAlgorithmConstraints() {
254
return algorithmConstraints;
255
}
256
257
/**
258
* Sets the cryptographic algorithm constraints, which will be used
259
* in addition to any configured by the runtime environment.
260
* <p>
261
* If the {@code constraints} parameter is non-null, every
262
* cryptographic algorithm, key and algorithm parameters used in the
263
* SSL/TLS/DTLS handshake must be permitted by the constraints.
264
*
265
* @param constraints the algorithm constraints (or null)
266
*
267
* @since 1.7
268
*/
269
public void setAlgorithmConstraints(AlgorithmConstraints constraints) {
270
// the constraints object is immutable
271
this.algorithmConstraints = constraints;
272
}
273
274
/**
275
* Gets the endpoint identification algorithm.
276
*
277
* @return the endpoint identification algorithm, or null if none
278
* has been set.
279
*
280
* @see X509ExtendedTrustManager
281
* @see #setEndpointIdentificationAlgorithm(String)
282
*
283
* @since 1.7
284
*/
285
public String getEndpointIdentificationAlgorithm() {
286
return identificationAlgorithm;
287
}
288
289
/**
290
* Sets the endpoint identification algorithm.
291
* <p>
292
* If the {@code algorithm} parameter is non-null or non-empty, the
293
* endpoint identification/verification procedures must be handled during
294
* SSL/TLS/DTLS handshaking. This is to prevent man-in-the-middle attacks.
295
*
296
* @param algorithm The standard string name of the endpoint
297
* identification algorithm (or null).
298
* See the <a href=
299
* "{@docRoot}/../specs/security/standard-names.html">
300
* Java Security Standard Algorithm Names</a> document
301
* for information about standard algorithm names.
302
*
303
* @see X509ExtendedTrustManager
304
*
305
* @since 1.7
306
*/
307
public void setEndpointIdentificationAlgorithm(String algorithm) {
308
this.identificationAlgorithm = algorithm;
309
}
310
311
/**
312
* Sets the desired {@link SNIServerName}s of the Server Name
313
* Indication (SNI) parameter.
314
* <P>
315
* This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
316
* operating in client mode.
317
* <P>
318
* Note that the {@code serverNames} list is cloned
319
* to protect against subsequent modification.
320
*
321
* @param serverNames
322
* the list of desired {@link SNIServerName}s (or null)
323
*
324
* @throws NullPointerException if the {@code serverNames}
325
* contains {@code null} element
326
* @throws IllegalArgumentException if the {@code serverNames}
327
* contains more than one name of the same name type
328
*
329
* @see SNIServerName
330
* @see #getServerNames()
331
*
332
* @since 1.8
333
*/
334
public final void setServerNames(List<SNIServerName> serverNames) {
335
if (serverNames != null) {
336
if (!serverNames.isEmpty()) {
337
sniNames = new LinkedHashMap<>(serverNames.size());
338
for (SNIServerName serverName : serverNames) {
339
if (sniNames.put(serverName.getType(),
340
serverName) != null) {
341
throw new IllegalArgumentException(
342
"Duplicated server name of type " +
343
serverName.getType());
344
}
345
}
346
} else {
347
sniNames = Collections.<Integer, SNIServerName>emptyMap();
348
}
349
} else {
350
sniNames = null;
351
}
352
}
353
354
/**
355
* Returns a {@link List} containing all {@link SNIServerName}s of the
356
* Server Name Indication (SNI) parameter, or null if none has been set.
357
* <P>
358
* This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
359
* operating in client mode.
360
* <P>
361
* For SSL/TLS/DTLS connections, the underlying SSL/TLS/DTLS provider
362
* may specify a default value for a certain server name type. In
363
* client mode, it is recommended that, by default, providers should
364
* include the server name indication whenever the server can be located
365
* by a supported server name type.
366
* <P>
367
* It is recommended that providers initialize default Server Name
368
* Indications when creating {@code SSLSocket}/{@code SSLEngine}s.
369
* In the following examples, the server name could be represented by an
370
* instance of {@link SNIHostName} which has been initialized with the
371
* hostname "www.example.com" and type
372
* {@link StandardConstants#SNI_HOST_NAME}.
373
*
374
* <pre>
375
* Socket socket =
376
* sslSocketFactory.createSocket("www.example.com", 443);
377
* </pre>
378
* or
379
* <pre>
380
* SSLEngine engine =
381
* sslContext.createSSLEngine("www.example.com", 443);
382
* </pre>
383
*
384
* @return null or an immutable list of non-null {@link SNIServerName}s
385
*
386
* @see List
387
* @see #setServerNames(List)
388
*
389
* @since 1.8
390
*/
391
public final List<SNIServerName> getServerNames() {
392
if (sniNames != null) {
393
if (!sniNames.isEmpty()) {
394
return Collections.<SNIServerName>unmodifiableList(
395
new ArrayList<>(sniNames.values()));
396
} else {
397
return Collections.<SNIServerName>emptyList();
398
}
399
}
400
401
return null;
402
}
403
404
/**
405
* Sets the {@link SNIMatcher}s of the Server Name Indication (SNI)
406
* parameter.
407
* <P>
408
* This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
409
* operating in server mode.
410
* <P>
411
* Note that the {@code matchers} collection is cloned to protect
412
* against subsequent modification.
413
*
414
* @param matchers
415
* the collection of {@link SNIMatcher}s (or null)
416
*
417
* @throws NullPointerException if the {@code matchers}
418
* contains {@code null} element
419
* @throws IllegalArgumentException if the {@code matchers}
420
* contains more than one name of the same name type
421
*
422
* @see Collection
423
* @see SNIMatcher
424
* @see #getSNIMatchers()
425
*
426
* @since 1.8
427
*/
428
public final void setSNIMatchers(Collection<SNIMatcher> matchers) {
429
if (matchers != null) {
430
if (!matchers.isEmpty()) {
431
sniMatchers = new HashMap<>(matchers.size());
432
for (SNIMatcher matcher : matchers) {
433
if (sniMatchers.put(matcher.getType(),
434
matcher) != null) {
435
throw new IllegalArgumentException(
436
"Duplicated server name of type " +
437
matcher.getType());
438
}
439
}
440
} else {
441
sniMatchers = Collections.<Integer, SNIMatcher>emptyMap();
442
}
443
} else {
444
sniMatchers = null;
445
}
446
}
447
448
/**
449
* Returns a {@link Collection} containing all {@link SNIMatcher}s of the
450
* Server Name Indication (SNI) parameter, or null if none has been set.
451
* <P>
452
* This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
453
* operating in server mode.
454
* <P>
455
* For better interoperability, providers generally will not define
456
* default matchers so that by default servers will ignore the SNI
457
* extension and continue the handshake.
458
*
459
* @return null or an immutable collection of non-null {@link SNIMatcher}s
460
*
461
* @see SNIMatcher
462
* @see #setSNIMatchers(Collection)
463
*
464
* @since 1.8
465
*/
466
public final Collection<SNIMatcher> getSNIMatchers() {
467
if (sniMatchers != null) {
468
if (!sniMatchers.isEmpty()) {
469
return Collections.<SNIMatcher>unmodifiableList(
470
new ArrayList<>(sniMatchers.values()));
471
} else {
472
return Collections.<SNIMatcher>emptyList();
473
}
474
}
475
476
return null;
477
}
478
479
/**
480
* Sets whether the local cipher suites preference should be honored.
481
*
482
* @param honorOrder whether local cipher suites order in
483
* {@code #getCipherSuites} should be honored during
484
* SSL/TLS/DTLS handshaking.
485
*
486
* @see #getUseCipherSuitesOrder()
487
*
488
* @since 1.8
489
*/
490
public final void setUseCipherSuitesOrder(boolean honorOrder) {
491
this.preferLocalCipherSuites = honorOrder;
492
}
493
494
/**
495
* Returns whether the local cipher suites preference should be honored.
496
*
497
* @return whether local cipher suites order in {@code #getCipherSuites}
498
* should be honored during SSL/TLS/DTLS handshaking.
499
*
500
* @see #setUseCipherSuitesOrder(boolean)
501
*
502
* @since 1.8
503
*/
504
public final boolean getUseCipherSuitesOrder() {
505
return preferLocalCipherSuites;
506
}
507
508
/**
509
* Sets whether DTLS handshake retransmissions should be enabled.
510
*
511
* This method only applies to DTLS.
512
*
513
* @param enableRetransmissions
514
* {@code true} indicates that DTLS handshake retransmissions
515
* should be enabled; {@code false} indicates that DTLS handshake
516
* retransmissions should be disabled
517
*
518
* @see #getEnableRetransmissions()
519
*
520
* @since 9
521
*/
522
public void setEnableRetransmissions(boolean enableRetransmissions) {
523
this.enableRetransmissions = enableRetransmissions;
524
}
525
526
/**
527
* Returns whether DTLS handshake retransmissions should be enabled.
528
*
529
* This method only applies to DTLS.
530
*
531
* @return true, if DTLS handshake retransmissions should be enabled
532
*
533
* @see #setEnableRetransmissions(boolean)
534
*
535
* @since 9
536
*/
537
public boolean getEnableRetransmissions() {
538
return enableRetransmissions;
539
}
540
541
/**
542
* Sets the maximum expected network packet size in bytes for
543
* SSL/TLS/DTLS records.
544
*
545
* @apiNote It is recommended that if possible, the maximum packet size
546
* should not be less than 256 bytes so that small handshake
547
* messages, such as HelloVerifyRequests, are not fragmented.
548
*
549
* @implNote If the maximum packet size is too small to hold a minimal
550
* record, an implementation may attempt to generate as minimal
551
* records as possible. However, this may cause a generated
552
* packet to be larger than the maximum packet size.
553
*
554
* @param maximumPacketSize
555
* the maximum expected network packet size in bytes, or
556
* {@code 0} to use the implicit size that is automatically
557
* specified by the underlying implementation.
558
* @throws IllegalArgumentException
559
* if {@code maximumPacketSize} is negative.
560
*
561
* @see #getMaximumPacketSize()
562
*
563
* @since 9
564
*/
565
public void setMaximumPacketSize(int maximumPacketSize) {
566
if (maximumPacketSize < 0) {
567
throw new IllegalArgumentException(
568
"The maximum packet size cannot be negative");
569
}
570
571
this.maximumPacketSize = maximumPacketSize;
572
}
573
574
/**
575
* Returns the maximum expected network packet size in bytes for
576
* SSL/TLS/DTLS records.
577
*
578
* @apiNote The implicit size may not be a fixed value, especially
579
* for a DTLS protocols implementation.
580
*
581
* @implNote For SSL/TLS/DTLS connections, the underlying provider
582
* should calculate and specify the implicit value of the
583
* maximum expected network packet size if it is not
584
* configured explicitly. For any connection populated
585
* object, this method should never return {@code 0} so
586
* that applications can retrieve the actual implicit size
587
* of the underlying implementation.
588
* <P>
589
* An implementation should attempt to comply with the maximum
590
* packet size configuration. However, if the maximum packet
591
* size is too small to hold a minimal record, an implementation
592
* may try to generate as minimal records as possible. This
593
* may cause a generated packet to be larger than the maximum
594
* packet size.
595
*
596
* @return the maximum expected network packet size, or {@code 0} if
597
* use the implicit size that is automatically specified by
598
* the underlying implementation and this object has not been
599
* populated by any connection.
600
*
601
* @see #setMaximumPacketSize(int)
602
*
603
* @since 9
604
*/
605
public int getMaximumPacketSize() {
606
return maximumPacketSize;
607
}
608
609
/**
610
* Returns a prioritized array of application-layer protocol names that
611
* can be negotiated over the SSL/TLS/DTLS protocols.
612
* <p>
613
* The array could be empty (zero-length), in which case protocol
614
* indications will not be used.
615
* <p>
616
* This method will return a new array each time it is invoked.
617
*
618
* @return a non-null, possibly zero-length array of application protocol
619
* {@code String}s. The array is ordered based on protocol
620
* preference, with {@code protocols[0]} being the most preferred.
621
* @see #setApplicationProtocols
622
* @since 9
623
*/
624
public String[] getApplicationProtocols() {
625
return applicationProtocols.clone();
626
}
627
628
/**
629
* Sets the prioritized array of application-layer protocol names that
630
* can be negotiated over the SSL/TLS/DTLS protocols.
631
* <p>
632
* If application-layer protocols are supported by the underlying
633
* SSL/TLS implementation, this method configures which values can
634
* be negotiated by protocols such as <a
635
* href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 </a>, the
636
* Application Layer Protocol Negotiation (ALPN).
637
* <p>
638
* If this end of the connection is expected to offer application protocol
639
* values, all protocols configured by this method will be sent to the
640
* peer.
641
* <p>
642
* If this end of the connection is expected to select the application
643
* protocol value, the {@code protocols} configured by this method are
644
* compared with those sent by the peer. The first matched value becomes
645
* the negotiated value. If none of the {@code protocols} were actually
646
* requested by the peer, the underlying protocol will determine what
647
* action to take. (For example, ALPN will send a
648
* {@code "no_application_protocol"} alert and terminate the connection.)
649
* <p>
650
* The {@code String} values must be presented using the network
651
* byte representation expected by the peer. For example, if an ALPN
652
* {@code String} should be exchanged using {@code UTF-8}, the
653
* {@code String} should be converted to its {@code byte[]} representation
654
* and stored as a byte-oriented {@code String} before calling this method.
655
*
656
* <blockquote><pre>
657
* // MEETEI MAYEK LETTERS HUK UN I (Unicode 0xabcd->0xabcf): 2 bytes
658
* byte[] bytes = "\u005cuabcd\u005cuabce\u005cuabcf"
659
* .getBytes(StandardCharsets.UTF_8);
660
* String HUK_UN_I = new String(bytes, StandardCharsets.ISO_8859_1);
661
*
662
* // 0x00-0xFF: 1 byte
663
* String rfc7301Grease8A = "\u005cu008A\u005cu008A";
664
*
665
* SSLParameters p = sslSocket.getSSLParameters();
666
* p.setApplicationProtocols(new String[] {
667
* "h2", "http/1.1", rfc7301Grease8A, HUK_UN_I});
668
* sslSocket.setSSLParameters(p);
669
* </pre></blockquote>
670
*
671
* @implSpec
672
* This method will make a copy of the {@code protocols} array.
673
*
674
* @param protocols an ordered array of application protocols,
675
* with {@code protocols[0]} being the most preferred.
676
* If the array is empty (zero-length), protocol
677
* indications will not be used.
678
* @throws IllegalArgumentException if protocols is null, or if
679
* any element in a non-empty array is null or an
680
* empty (zero-length) string
681
* @see #getApplicationProtocols
682
* @since 9
683
*/
684
public void setApplicationProtocols(String[] protocols) {
685
if (protocols == null) {
686
throw new IllegalArgumentException("protocols was null");
687
}
688
689
String[] tempProtocols = protocols.clone();
690
691
for (String p : tempProtocols) {
692
if (p == null || p.isEmpty()) {
693
throw new IllegalArgumentException(
694
"An element of protocols was null/empty");
695
}
696
}
697
applicationProtocols = tempProtocols;
698
}
699
}
700
701