Repository: netty/netty
File: handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslContext.java (Java)

Code before:
        boolean tlsFalseStart = false;
        boolean useTasks = USE_TASKS;
        OpenSslPrivateKeyMethod privateKeyMethod = null;
        OpenSslAsyncPrivateKeyMethod asyncPrivateKeyMethod = null;
        OpenSslCertificateCompressionConfig certCompressionConfig = null;
        Integer maxCertificateList = null;
        String[] groups = OpenSsl.NAMED_GROUPS;
        if (ctxOptions != null) {
            for (Map.Entry<SslContextOption<?>, Object> ctxOpt : ctxOptions) {
                SslContextOption<?> option = ctxOpt.getKey();

                if (option == OpenSslContextOption.TLS_FALSE_START) {
                    tlsFalseStart = (Boolean) ctxOpt.getValue();
                } else if (option == OpenSslContextOption.USE_TASKS) {
                    useTasks = (Boolean) ctxOpt.getValue();
                } else if (option == OpenSslContextOption.PRIVATE_KEY_METHOD) {
                    privateKeyMethod = (OpenSslPrivateKeyMethod) ctxOpt.getValue();
                } else if (option == OpenSslContextOption.ASYNC_PRIVATE_KEY_METHOD) {
                    asyncPrivateKeyMethod = (OpenSslAsyncPrivateKeyMethod) ctxOpt.getValue();
                } else if (option == OpenSslContextOption.CERTIFICATE_COMPRESSION_ALGORITHMS) {
                    certCompressionConfig = (OpenSslCertificateCompressionConfig) ctxOpt.getValue();
                } else if (option == OpenSslContextOption.MAX_CERTIFICATE_LIST_BYTES) {
                    maxCertificateList = (Integer) ctxOpt.getValue();
                } else if (option == OpenSslContextOption.GROUPS) {
                    String[] groupsArray = (String[]) ctxOpt.getValue();
                    Set<String> groupsSet = new HashSet<String>(groupsArray.length);
                    for (String group : groupsArray) {
                        groupsSet.add(GroupsConverter.toOpenSsl(group));
                    }
                    groups = groupsSet.toArray(EmptyArrays.EMPTY_STRINGS);
                } else {
                    logger.debug("Skipping unsupported " + SslContextOption.class.getSimpleName()
                            + ": " + ctxOpt.getKey());
                }
            }
        }
        if (privateKeyMethod != null && asyncPrivateKeyMethod != null) {
            throw new IllegalArgumentException("You can either only use "
                    + OpenSslAsyncPrivateKeyMethod.class.getSimpleName() + " or "
                    + OpenSslPrivateKeyMethod.class.getSimpleName());
        }

        this.tlsFalseStart = tlsFalseStart;

        leak = leakDetection ? leakDetector.track(this) : null;
        this.mode = mode;
        this.clientAuth = isServer() ? checkNotNull(clientAuth, "clientAuth") : ClientAuth.NONE;
        this.protocols = protocols == null ? OpenSsl.defaultProtocols(mode == SSL.SSL_MODE_CLIENT) : protocols;
        this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm;
        this.enableOcsp = enableOcsp;


Review comment (suggestion):
```suggestion
                    Set<String> groupsSet = new LinkedHashSet<String>(groupsArray.length);
```

For clients, and some configurations of TLSv1.2 servers, the ordering of the group names implies algorithm preference.

Code after:

        boolean tlsFalseStart = false;
        boolean useTasks = USE_TASKS;
        OpenSslPrivateKeyMethod privateKeyMethod = null;
        OpenSslAsyncPrivateKeyMethod asyncPrivateKeyMethod = null;
        OpenSslCertificateCompressionConfig certCompressionConfig = null;
        Integer maxCertificateList = null;
        String[] groups = OpenSsl.NAMED_GROUPS;
        if (ctxOptions != null) {
            for (Map.Entry<SslContextOption<?>, Object> ctxOpt : ctxOptions) {
                SslContextOption<?> option = ctxOpt.getKey();

                if (option == OpenSslContextOption.TLS_FALSE_START) {
                    tlsFalseStart = (Boolean) ctxOpt.getValue();
                } else if (option == OpenSslContextOption.USE_TASKS) {
                    useTasks = (Boolean) ctxOpt.getValue();
                } else if (option == OpenSslContextOption.PRIVATE_KEY_METHOD) {
                    privateKeyMethod = (OpenSslPrivateKeyMethod) ctxOpt.getValue();
                } else if (option == OpenSslContextOption.ASYNC_PRIVATE_KEY_METHOD) {
                    asyncPrivateKeyMethod = (OpenSslAsyncPrivateKeyMethod) ctxOpt.getValue();
                } else if (option == OpenSslContextOption.CERTIFICATE_COMPRESSION_ALGORITHMS) {
                    certCompressionConfig = (OpenSslCertificateCompressionConfig) ctxOpt.getValue();
                } else if (option == OpenSslContextOption.MAX_CERTIFICATE_LIST_BYTES) {
                    maxCertificateList = (Integer) ctxOpt.getValue();
                } else if (option == OpenSslContextOption.GROUPS) {
                    String[] groupsArray = (String[]) ctxOpt.getValue();
                    Set<String> groupsSet = new LinkedHashSet<String>(groupsArray.length);
                    for (String group : groupsArray) {
                        groupsSet.add(GroupsConverter.toOpenSsl(group));
                    }
                    groups = groupsSet.toArray(EmptyArrays.EMPTY_STRINGS);
                } else {
                    logger.debug("Skipping unsupported " + SslContextOption.class.getSimpleName()
                            + ": " + ctxOpt.getKey());
                }
            }
        }
        if (privateKeyMethod != null && asyncPrivateKeyMethod != null) {
            throw new IllegalArgumentException("You can either only use "
                    + OpenSslAsyncPrivateKeyMethod.class.getSimpleName() + " or "
                    + OpenSslPrivateKeyMethod.class.getSimpleName());
        }

        this.tlsFalseStart = tlsFalseStart;

        leak = leakDetection ? leakDetector.track(this) : null;
        this.mode = mode;
        this.clientAuth = isServer() ? checkNotNull(clientAuth, "clientAuth") : ClientAuth.NONE;
        this.protocols = protocols == null ? OpenSsl.defaultProtocols(mode == SSL.SSL_MODE_CLIENT) : protocols;
        this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm;
        this.enableOcsp = enableOcsp;