/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.ignite.internal.client;

import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import org.apache.ignite.internal.client.balancer.GridClientLoadBalancer;
import org.apache.ignite.internal.client.balancer.GridClientRandomBalancer;
import org.apache.ignite.internal.client.balancer.GridClientRoundRobinBalancer;
import org.apache.ignite.internal.client.marshaller.GridClientMarshaller;
import org.apache.ignite.internal.client.marshaller.optimized.GridClientOptimizedMarshaller;
import org.apache.ignite.internal.client.ssl.GridSslBasicContextFactory;
import org.apache.ignite.internal.client.ssl.GridSslContextFactory;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.plugin.security.SecurityCredentials;
import org.apache.ignite.plugin.security.SecurityCredentialsBasicProvider;
import org.apache.ignite.plugin.security.SecurityCredentialsProvider;
import org.jetbrains.annotations.Nullable;

/**
 * Java client configuration.
 */
public class GridClientConfiguration {
    /** Default client protocol. */
    public static final GridClientProtocol DFLT_CLIENT_PROTOCOL = GridClientProtocol.TCP;

    /** Default topology refresh frequency is 2 sec. */
    public static final int DFLT_TOP_REFRESH_FREQ = 2000;

    /** Default maximum time connection can be idle. */
    public static final long DFLT_MAX_CONN_IDLE_TIME = 30000;

    /** Default ping interval in milliseconds. */
    public static final long DFLT_PING_INTERVAL = 5000;

    /** Default ping timeout in milliseconds. */
    public static final long DFLT_PING_TIMEOUT = 7000;

    /** Default connect timeout in milliseconds. */
    public static final int DFLT_CONNECT_TIMEOUT = 10000;

    /** Default flag setting for TCP_NODELAY option. */
    public static final boolean DFLT_TCP_NODELAY = true;

    /** List of servers to connect to. */
    private Collection<String> srvs = Collections.emptySet();

    /** List of routers to connect to. */
    private Collection<String> routers = Collections.emptySet();

    /** Client protocol. */
    private GridClientProtocol proto = DFLT_CLIENT_PROTOCOL;

    /** Socket connect timeout. */
    private int connectTimeout = DFLT_CONNECT_TIMEOUT;

    /** TCP_NODELAY flag. */
    private boolean tcpNoDelay = DFLT_TCP_NODELAY;

    /** SSL context factory  */
    private GridSslContextFactory sslCtxFactory;

    /** Flag indicating whether metrics cache is enabled. */
    private boolean enableMetricsCache = true;

    /** Flag indicating whether attributes cache is enabled. */
    private boolean enableAttrsCache = true;

    /** Flag indicating whether metrics should be automatically fetched. */
    private boolean autoFetchMetrics = true;

    /** Flag indicating whether attributes should be automatically fetched. */
    private boolean autoFetchAttrs = true;

    /** Topology refresh  frequency. */
    private long topRefreshFreq = DFLT_TOP_REFRESH_FREQ;

    /** Max time of connection idleness. */
    private long maxConnIdleTime = DFLT_MAX_CONN_IDLE_TIME;

    /** Ping interval. */
    private long pingInterval = DFLT_PING_INTERVAL;

    /** Ping timeout. */
    private long pingTimeout = DFLT_PING_TIMEOUT;

    /** Default balancer. */
    private GridClientLoadBalancer balancer = new GridClientRandomBalancer();

    /** Collection of data configurations. */
    private Map<String, GridClientDataConfiguration> dataCfgs = Collections.emptyMap();

    /** Credentials. */
    private SecurityCredentialsProvider credProvider;

    /** Executor. */
    private ExecutorService executor;

    /** Marshaller. */
    private GridClientMarshaller marshaller = new GridClientOptimizedMarshaller(U.allPluginProviders());

    /** Daemon flag. */
    private boolean daemon;

    /**
     * Creates default configuration.
     */
    public GridClientConfiguration() {
        // No-op.
    }

    /**
     * Copy constructor.
     *
     * @param cfg Configuration to be copied.
     */
    public GridClientConfiguration(GridClientConfiguration cfg) {
        // Preserve alphabetical order for maintenance;
        autoFetchAttrs = cfg.isAutoFetchAttributes();
        autoFetchMetrics = cfg.isAutoFetchMetrics();
        balancer = cfg.getBalancer();
        connectTimeout = cfg.getConnectTimeout();
        credProvider = cfg.getSecurityCredentialsProvider();
        enableAttrsCache = cfg.isEnableAttributesCache();
        enableMetricsCache = cfg.isEnableMetricsCache();
        executor = cfg.getExecutorService();
        marshaller = cfg.getMarshaller();
        maxConnIdleTime = cfg.getMaxConnectionIdleTime();
        pingInterval = cfg.getPingInterval();
        pingTimeout = cfg.getPingTimeout();
        proto = cfg.getProtocol();
        routers = cfg.getRouters();
        srvs = cfg.getServers();
        sslCtxFactory = cfg.getSslContextFactory();
        tcpNoDelay = cfg.isTcpNoDelay();
        topRefreshFreq = cfg.getTopologyRefreshFrequency();
        daemon = cfg.isDaemon();

        setDataConfigurations(cfg.getDataConfigurations());
    }

    /**
     * Creates properties-based configuration based on passed in properties.
     *
     * @param in Client configuration in properties format.
     * @throws GridClientException If parsing configuration failed.
     */
    public GridClientConfiguration(Properties in) throws GridClientException {
        this("ignite.client", in);
    }

    /**
     * Creates properties-based configuration.
     *
     * @param prefix Prefix for the client properties.
     * @param in Properties map to load configuration from.
     * @throws GridClientException If parsing configuration failed.
     */
    public GridClientConfiguration(String prefix, Properties in) throws GridClientException {
        load(prefix, in);
    }

    /**
     * Collection of {@code 'host:port'} pairs representing
     * remote grid servers used to establish initial connection to
     * the grid. Once connection is established, Ignite will get
     * a full view on grid topology and will be able to connect to
     * any available remote node.
     * <p>
     * Note that only these addresses are used to perform
     * topology updates in background and to detect Grid connectivity
     * status.
     *
     * @return Collection of {@code 'host:port'} pairs representing remote
     *      grid servers.
     * @see GridClient#connected()
     */
    public Collection<String> getServers() {
        return Collections.unmodifiableCollection(srvs);
    }

    /**
     * Collection of {@code 'host:port'} pairs representing
     * grid routers used to establish connection to the grid.
     * <p>
     * Addresses here could be owned by Routers as well as
     * by individual Grid nodes. No additional connections
     * will be made even if other Grid nodes are available.
     * <p>
     * This configuration mode is designated for cases when
     * some Grid nodes are unavailable (due to security restrictions
     * for example). So only few nodes acting as routers or
     * dedicated router components used to access entire Grid.
     * <p>
     * This configuration parameter will not be used and direct
     * connections to all grid nodes will be established if
     * {@link #getServers()} return non-empty collection value.
     * <p>
     * Note that only these addresses are used to perform
     * topology updates in background and to detect Grid connectivity
     * status.
     *
     * @return Collection of {@code 'host:port'} pairs
     *      representing routers.
     * @see GridClient#connected()
     */
    public Collection<String> getRouters() {
        return routers;
    }

    /**
     * Sets list of servers this client should connect to.
     *
     * @param srvs List of servers.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setServers(Collection<String> srvs) {
        this.srvs = srvs != null ? srvs : Collections.<String>emptySet();

        return this;
    }

    /**
     * Sets list of routers this client should connect to.
     *
     * @param routers List of routers.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setRouters(Collection<String> routers) {
        this.routers = routers != null ? routers : Collections.<String>emptySet();

        return this;
    }

    /**
     * Gets protocol for communication between client and remote grid.
     * Default is defined by {@link #DFLT_CLIENT_PROTOCOL} constant.
     *
     * @return Protocol for communication between client and remote grid.
     */
    public GridClientProtocol getProtocol() {
        return proto;
    }

    /**
     * Sets protocol type that should be used in communication. Protocol type cannot be changed after
     * client is created.
     *
     * @param proto Protocol type.
     * @see GridClientProtocol
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setProtocol(GridClientProtocol proto) {
        this.proto = proto;

        return this;
    }

    /**
     * Gets timeout for socket connect operation in milliseconds. If {@code 0} -
     * then wait infinitely. Default is defined by {@link #DFLT_CONNECT_TIMEOUT} constant.
     *
     * @return Connect timeout in milliseconds.
     */
    public int getConnectTimeout() {
        return connectTimeout;
    }

    /**
     * Gets flag indicating whether {@code TCP_NODELAY} flag should be enabled for outgoing connections.
     * This flag reduces communication latency and in the majority of cases should be set to true. For more
     * information, see {@link Socket#setTcpNoDelay(boolean)}
     * <p>
     * If not set, default value is {@link #DFLT_TCP_NODELAY}
     *
     * @return If {@code TCP_NODELAY} should be set on underlying sockets.
     */
    public boolean isTcpNoDelay() {
        return tcpNoDelay;
    }

    /**
     * Sets whether {@code TCP_NODELAY} flag should be set on underlying socket connections.
     *
     * @param tcpNoDelay {@code True} if flag should be set.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setTcpNoDelay(boolean tcpNoDelay) {
        this.tcpNoDelay = tcpNoDelay;

        return this;
    }

    /**
     * Sets timeout for socket connect operation.
     *
     * @param connectTimeout Connect timeout in milliseconds.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setConnectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;

        return this;
    }

    /**
     * Gets a factory that should be used for SSL context creation.
     * If it returns {@code null} then SSL is considered disabled.
     *
     * @return Factory instance.
     * @see GridSslContextFactory
     */
    public GridSslContextFactory getSslContextFactory() {
        return sslCtxFactory;
    }

    /**
     * Sets SSL context factory that will be used for creation of secure connections.
     *
     * @param sslCtxFactory Context factory.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setSslContextFactory(GridSslContextFactory sslCtxFactory) {
        this.sslCtxFactory = sslCtxFactory;

        return this;
    }

    /**
     * Default balancer to be used for computational client. It can be overridden
     * for different compute instances. By default {@link GridClientRandomBalancer}
     * is used.
     *
     * @return Default balancer to be used for computational client.
     */
    public GridClientLoadBalancer getBalancer() {
        return balancer;
    }

    /**
     * Sets default compute balancer.
     *
     * @param balancer Balancer to use.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setBalancer(GridClientLoadBalancer balancer) {
        this.balancer = balancer;

        return this;
    }

    /**
     * Gets client credentials provider to authenticate with.
     *
     * @return Credentials provider.
     */
    public SecurityCredentialsProvider getSecurityCredentialsProvider() {
        return credProvider;
    }

    /**
     * Sets client credentials provider used in authentication process.
     *
     * @param credProvider Client credentials provider.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setSecurityCredentialsProvider(SecurityCredentialsProvider credProvider) {
        this.credProvider = credProvider;

        return this;
    }

    /**
     * Gets a collection of data configurations specified by user.
     *
     * @return Collection of data configurations (possibly empty).
     */
    public Collection<GridClientDataConfiguration> getDataConfigurations() {
        return dataCfgs.values();
    }

    /**
     * Sets data configurations.
     *
     * @param dataCfgs Data configurations.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setDataConfigurations(Collection<? extends GridClientDataConfiguration> dataCfgs) {
        this.dataCfgs = U.newHashMap(dataCfgs.size());

        for (GridClientDataConfiguration dataCfg : dataCfgs)
            this.dataCfgs.put(dataCfg.getName(), new GridClientDataConfiguration(dataCfg));

        return this;
    }

    /**
     * Gets data configuration for a cache with specified name.
     *
     * @param name Name of grid cache.
     * @return Configuration or {@code null} if there is not configuration for specified name.
     */
    public GridClientDataConfiguration getDataConfiguration(@Nullable String name) {
        return dataCfgs.get(name);
    }

    /**
     * Sets flag indicating whether node and cache metrics should be cached by client.
     *
     * @param enableMetricsCache {@code True} if cache should be enabled.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setEnableMetricsCache(boolean enableMetricsCache) {
        this.enableMetricsCache = enableMetricsCache;

        return this;
    }

    /**
     * Enables client to cache per-node and per-cache metrics internally. In memory
     * sensitive environments, such as mobile platforms, caching metrics
     * may be expensive and, hence, this parameter should be set to {@code false}.
     * <p>
     * Note that topology is refreshed automatically every {@link #getTopologyRefreshFrequency()}
     * interval, and if {@link #isAutoFetchMetrics()} enabled then metrics will be updated
     * with that frequency.
     * <p>
     * By default this value is {@code true} which means that metrics will be cached
     * on the client side.
     *
     * @return {@code True} if metrics cache is enabled, {@code false} otherwise.
     */
    public boolean isEnableMetricsCache() {
        return enableMetricsCache;
    }

    /**
     * Sets flag indicating whether node attributes should be cached by client.
     *
     * @param enableAttrsCache {@code True} if cache should be enabled.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setEnableAttributesCache(boolean enableAttrsCache) {
        this.enableAttrsCache = enableAttrsCache;

        return this;
    }

    /**
     * Enables client to cache per-node attributes internally. In memory
     * sensitive environments, such as mobile platforms, caching node attributes
     * may be expensive and, hence, this parameter should be set to {@code false}.
     * <p>
     * Note that node attributes are static and, if cached, there is no need
     * to refresh them again. If {@link #isAutoFetchAttributes()} is enabled then
     * attributes will be cached during client initialization.
     * <p>
     * By default this value is {@code true} which means that node attributes
     * will be cached on the client side.
     *
     * @return {@code True} if attributes cache is enabled, {@code false} otherwise.
     */
    public boolean isEnableAttributesCache() {
        return enableAttrsCache;
    }

    /**
     * Sets flag indicating whether node metrics should be fetched by client automatically.
     *
     * @param autoFetchMetrics {@code True} if metrics should be fetched.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setAutoFetchMetrics(boolean autoFetchMetrics) {
        this.autoFetchMetrics = autoFetchMetrics;

        return this;
    }

    /**
     * Allows client to fetch node metrics automatically with background topology refresh.
     * <p>
     * Note that this parameter will only affect auto-fetching of node metrics.
     * Cache metrics still need to be fetched explicitly via
     * {@link GridClientData#metrics()} or {@link GridClientData#metricsAsync()} methods.
     * <p>
     * By default this value is {@code true} which means that metrics will be fetched
     * automatically.
     *
     * @return {@code true} if client should fetch metrics on topology refresh,
     *      {@code false} otherwise.
     */
    public boolean isAutoFetchMetrics() {
        return autoFetchMetrics;
    }

    /**
     * Sets flag indicating whether node attributes should be fetched by client automatically.
     *
     * @param autoFetchAttrs {@code True} if attributes should be fetched.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setAutoFetchAttributes(boolean autoFetchAttrs) {
        this.autoFetchAttrs = autoFetchAttrs;

        return this;
    }

    /**
     * Allows client to fetch node attributes automatically with background topology refresh.
     * <p>
     * By default this value is {@code true} which means that attributes will be fetched
     * automatically.
     *
     * @return {@code True} if client should fetch attributes once on topology refresh,
     *      {@code false} otherwise.
     */
    public boolean isAutoFetchAttributes() {
        return autoFetchAttrs;
    }

    /**
     * Gets topology refresh frequency. Default is defined by {@link #DFLT_TOP_REFRESH_FREQ}
     * constant.
     *
     * @return Topology refresh frequency.
     */
    public long getTopologyRefreshFrequency() {
        return topRefreshFreq;
    }

    /**
     * Sets topology refresh frequency. If topology cache is enabled, grid topology
     * will be refreshed every {@code topRefreshFreq} milliseconds.
     *
     * @param topRefreshFreq Topology refresh frequency in milliseconds.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setTopologyRefreshFrequency(long topRefreshFreq) {
        this.topRefreshFreq = topRefreshFreq;

        return this;
    }

    /**
     * Gets maximum amount of time that client connection can be idle before it is closed.
     * Default is defined by {@link #DFLT_MAX_CONN_IDLE_TIME} constant.
     *
     * @return Maximum idle time in milliseconds.
     */
    public long getMaxConnectionIdleTime() {
        return maxConnIdleTime;
    }

    /**
     * Sets maximum time in milliseconds which connection can be idle before it is closed by client.
     *
     * @param maxConnIdleTime Maximum time of connection idleness in milliseconds.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setMaxConnectionIdleTime(long maxConnIdleTime) {
        this.maxConnIdleTime = maxConnIdleTime;

        return this;
    }

    /**
     * Gets time interval in milliseconds between ping requests. Default is defined
     * by {@link #DFLT_PING_INTERVAL} constant.
     * <p>
     * Ping requests used by {@link GridClientProtocol#TCP} protocol
     * to detect network failures and half-opened sockets.
     *
     * @return Ping interval.
     */
    public long getPingInterval() {
        return pingInterval;
    }

    /**
     * Sets ping interval in milliseconds.
     *
     * @param pingInterval Ping interval in milliseconds.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setPingInterval(long pingInterval) {
        this.pingInterval = pingInterval;

        return this;
    }

    /**
     * Gets ping timeout. Default is defined by {@link #DFLT_PING_TIMEOUT} constant.
     * <p>
     * Ping requests used by {@link GridClientProtocol#TCP} protocol
     * to detect network failures and half-opened sockets.
     * If no response received in period equal to this timeout than connection
     * considered broken and closed.
     *
     * @return Ping timeout.
     */
    public long getPingTimeout() {
        return pingTimeout;
    }

    /**
     * Sets ping timeout in milliseconds.
     *
     * @param pingTimeout Ping interval in milliseconds.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setPingTimeout(long pingTimeout) {
        this.pingTimeout = pingTimeout;

        return this;
    }

    /**
     * Gets {@link ExecutorService} where client could run asynchronous operations.
     * <p>
     * When using {@link GridClientProtocol#TCP} this executor should be able to serve at least
     * {@code Runtime.getRuntime().availableProcessors()} parallel tasks.
     * <p>
     * Note that this executor will be automatically shut down when client get closed.
     *
     * @return {@link ExecutorService} instance to use.
     */
    public ExecutorService getExecutorService() {
        return executor;
    }

    /**
     * Sets executor service.
     *
     * @param executor Executor service to use in client.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setExecutorService(ExecutorService executor) {
        this.executor = executor;

        return this;
    }

    /**
     * Gets the marshaller, that is used to communicate between client and server.
     * <p>
     * Options, that can be used out-of-the-box:
     * <ul>
     *     <li>{@link GridClientOptimizedMarshaller} (default) - Ignite's optimized marshaller.</li>
     *     <li>{@code GridClientBinaryMarshaller} - Marshaller that supports binary objects.</li>
     *     <li>{@link org.apache.ignite.internal.client.marshaller.jdk.GridClientJdkMarshaller} - JDK marshaller (not recommended).</li>
     * </ul>
     *
     * @return A marshaller to use.
     */
    public GridClientMarshaller getMarshaller() {
        return marshaller;
    }

    /**
     * Sets the marshaller to use for communication.
     *
     * @param marshaller A marshaller to use.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setMarshaller(GridClientMarshaller marshaller) {
        this.marshaller = marshaller;

        return this;
    }

    /**
     * Load client configuration from the properties map.
     *
     * @param prefix Prefix for the client properties.
     * @param in Properties map to load configuration from.
     * @throws GridClientException If parsing configuration failed.
     */
    public void load(String prefix, Properties in) throws GridClientException {
        while (prefix.endsWith("."))
            prefix = prefix.substring(0, prefix.length() - 1);

        if (!prefix.isEmpty())
            prefix += ".";

        String balancer = in.getProperty(prefix + "balancer");
        String connectTimeout = in.getProperty(prefix + "connectTimeout");
        String cred = in.getProperty(prefix + "credentials");
        String autoFetchMetrics = in.getProperty(prefix + "autoFetchMetrics");
        String autoFetchAttrs = in.getProperty(prefix + "autoFetchAttributes");
        String maxConnIdleTime = in.getProperty(prefix + "idleTimeout");
        String proto = in.getProperty(prefix + "protocol");
        String srvrs = in.getProperty(prefix + "servers");
        String tcpNoDelay = in.getProperty(prefix + "tcp.noDelay");
        String topRefreshFreq = in.getProperty(prefix + "topology.refresh");

        String sslEnabled = in.getProperty(prefix + "ssl.enabled");

        String sslProto = in.getProperty(prefix + "ssl.protocol", "TLS");
        String sslKeyAlg = in.getProperty(prefix + "ssl.key.algorithm", "SunX509");

        String keyStorePath = in.getProperty(prefix + "ssl.keystore.location");
        String keyStorePwd = in.getProperty(prefix + "ssl.keystore.password");
        String keyStoreType = in.getProperty(prefix + "ssl.keystore.type");

        String trustStorePath = in.getProperty(prefix + "ssl.truststore.location");
        String trustStorePwd = in.getProperty(prefix + "ssl.truststore.password");
        String trustStoreType = in.getProperty(prefix + "ssl.truststore.type");

        String dataCfgs = in.getProperty(prefix + "data.configurations");

        setBalancer(resolveBalancer(balancer));

        if (!F.isEmpty(connectTimeout))
            setConnectTimeout(Integer.parseInt(connectTimeout));

        if (!F.isEmpty(cred)) {
            int idx = cred.indexOf(':');

            if (idx >= 0 && idx < cred.length() - 1) {
                setSecurityCredentialsProvider(new SecurityCredentialsBasicProvider(
                    new SecurityCredentials(cred.substring(0, idx), cred.substring(idx + 1))));
            }
            else {
                setSecurityCredentialsProvider(new SecurityCredentialsBasicProvider(
                    new SecurityCredentials(null, null, cred)));
            }
        }

        if (!F.isEmpty(autoFetchMetrics))
            setAutoFetchMetrics(Boolean.parseBoolean(autoFetchMetrics));

        if (!F.isEmpty(autoFetchAttrs))
            setAutoFetchAttributes(Boolean.parseBoolean(autoFetchAttrs));

        if (!F.isEmpty(maxConnIdleTime))
            setMaxConnectionIdleTime(Integer.parseInt(maxConnIdleTime));

        if (!F.isEmpty(proto))
            setProtocol(GridClientProtocol.valueOf(proto));

        if (!F.isEmpty(srvrs))
            setServers(Arrays.asList(srvrs.replaceAll("\\s+", "").split(",")));

        if (!F.isEmpty(tcpNoDelay))
            setTcpNoDelay(Boolean.parseBoolean(tcpNoDelay));

        if (!F.isEmpty(topRefreshFreq))
            setTopologyRefreshFrequency(Long.parseLong(topRefreshFreq));

        //
        // SSL configuration section
        //

        if (!F.isEmpty(sslEnabled) && Boolean.parseBoolean(sslEnabled)) {
            GridSslBasicContextFactory factory = new GridSslBasicContextFactory();

            factory.setProtocol(F.isEmpty(sslProto) ? "TLS" : sslProto);
            factory.setKeyAlgorithm(F.isEmpty(sslKeyAlg) ? "SunX509" : sslKeyAlg);

            if (F.isEmpty(keyStorePath))
                throw new IllegalArgumentException("SSL key store location is not specified.");

            factory.setKeyStoreFilePath(keyStorePath);

            if (keyStorePwd != null)
                factory.setKeyStorePassword(keyStorePwd.toCharArray());

            factory.setKeyStoreType(F.isEmpty(keyStoreType) ? "jks" : keyStoreType);

            if (F.isEmpty(trustStorePath))
                factory.setTrustManagers(GridSslBasicContextFactory.getDisabledTrustManager());
            else {
                factory.setTrustStoreFilePath(trustStorePath);

                if (trustStorePwd != null)
                    factory.setTrustStorePassword(trustStorePwd.toCharArray());

                factory.setTrustStoreType(F.isEmpty(trustStoreType) ? "jks" : trustStoreType);
            }

            setSslContextFactory(factory);
        }

        //
        // Data configuration section
        //

        if (!F.isEmpty(dataCfgs)) {
            String[] names = dataCfgs.replaceAll("\\s+", "").split(",");
            Collection<GridClientDataConfiguration> list = new ArrayList<>();

            for (String cfgName : names) {
                if (F.isEmpty(cfgName))
                    continue;

                String name = in.getProperty(prefix + "data." + cfgName + ".name");
                String bal = in.getProperty(prefix + "data." + cfgName + ".balancer");
                String aff = in.getProperty(prefix + "data." + cfgName + ".affinity");

                GridClientDataConfiguration dataCfg = new GridClientDataConfiguration();

                dataCfg.setName(F.isEmpty(name) ? null : name);
                dataCfg.setBalancer(resolveBalancer(bal));
                dataCfg.setAffinity(resolveAffinity(aff));

                list.add(dataCfg);
            }

            setDataConfigurations(list);
        }
    }

    /**
     * Resolve load balancer from string definition.
     *
     * @param balancer Load balancer string definition.
     * @return Resolved load balancer.
     * @throws GridClientException If loading failed.
     */
    private static GridClientLoadBalancer resolveBalancer(String balancer) throws GridClientException {
        if (F.isEmpty(balancer) || "random".equals(balancer))
            return new GridClientRandomBalancer();

        if ("roundrobin".equals(balancer))
            return new GridClientRoundRobinBalancer();

        return newInstance(GridClientLoadBalancer.class, balancer);
    }

    /**
     * Resolve data affinity from string definition.
     *
     * @param affinity Data affinity string definition.
     * @return Resolved data affinity.
     * @throws GridClientException If loading failed.
     */
    private static GridClientDataAffinity resolveAffinity(String affinity) throws GridClientException {
        if (F.isEmpty(affinity))
            return null;

        if ("partitioned".equals(affinity))
            return new GridClientPartitionAffinity();

        return newInstance(GridClientDataAffinity.class, affinity);
    }

    /**
     * Constructs new instance of the specified class.
     *
     * @param exp Expected class for the new instance.
     * @param clsName Class name to create new instance for.
     * @param <T> Expected class type for the new instance.
     * @return New instance of specified class.
     * @throws GridClientException If loading failed.
     */
    private static <T> T newInstance(Class<T> exp, String clsName) throws GridClientException {
        Object obj;

        try {
            obj = Class.forName(clsName).newInstance();
        }
        // Catch all for convenience.
        catch (Exception e) {
            throw new GridClientException("Failed to create class instance: " + clsName, e);
        }

        return exp.cast(obj);
    }

    /**
     * Set the daemon flag value. Communication threads will be created as daemons if this flag is set.
     *
     * @param daemon Daemon flag.
     * @return {@code this} for chaining.
     */
    public GridClientConfiguration setDaemon(boolean daemon) {
        this.daemon = daemon;

        return this;
    }

    /**
     * Get the daemon flag.
     *
     * @return Daemon flag.
     */
    public boolean isDaemon() {
        return daemon;
    }
}
