1 /*
   2  * Copyright (c) 2005, 2017, 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      *
 650      * @implSpec
 651      * This method will make a copy of the {@code protocols} array.
 652      *
 653      * @param protocols   an ordered array of application protocols,
 654      *                    with {@code protocols[0]} being the most preferred.
 655      *                    If the array is empty (zero-length), protocol
 656      *                    indications will not be used.
 657      * @throws IllegalArgumentException if protocols is null, or if
 658      *                    any element in a non-empty array is null or an
 659      *                    empty (zero-length) string
 660      * @see #getApplicationProtocols
 661      * @since 9
 662      */
 663     public void setApplicationProtocols(String[] protocols) {
 664         if (protocols == null) {
 665             throw new IllegalArgumentException("protocols was null");
 666         }
 667 
 668         String[] tempProtocols = protocols.clone();
 669 
 670         for (String p : tempProtocols) {
 671             if (p == null || p.equals("")) {
 672                 throw new IllegalArgumentException(
 673                     "An element of protocols was null/empty");
 674             }
 675         }
 676         applicationProtocols = tempProtocols;
 677     }
 678 }