/*
 * 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.geode.distributed.internal;

import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_CIPHERS;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_KEYSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_KEYSTORE_PASSWORD;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_KEYSTORE_TYPE;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_PROTOCOLS;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_REQUIRE_AUTHENTICATION;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_TRUSTSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_TRUSTSTORE_PASSWORD;
import static org.apache.geode.distributed.ConfigurationProperties.GATEWAY_SSL_CIPHERS;
import static org.apache.geode.distributed.ConfigurationProperties.GATEWAY_SSL_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.GATEWAY_SSL_KEYSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.GATEWAY_SSL_KEYSTORE_PASSWORD;
import static org.apache.geode.distributed.ConfigurationProperties.GATEWAY_SSL_KEYSTORE_TYPE;
import static org.apache.geode.distributed.ConfigurationProperties.GATEWAY_SSL_PROTOCOLS;
import static org.apache.geode.distributed.ConfigurationProperties.GATEWAY_SSL_REQUIRE_AUTHENTICATION;
import static org.apache.geode.distributed.ConfigurationProperties.GATEWAY_SSL_TRUSTSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.GATEWAY_SSL_TRUSTSTORE_PASSWORD;
import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_SSL_CIPHERS;
import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_SSL_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_SSL_KEYSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_SSL_KEYSTORE_PASSWORD;
import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_SSL_KEYSTORE_TYPE;
import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_SSL_PROTOCOLS;
import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_SSL_REQUIRE_AUTHENTICATION;
import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_SSL_TRUSTSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_SSL_TRUSTSTORE_PASSWORD;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_SSL_CIPHERS;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_SSL_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_SSL_KEYSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_SSL_KEYSTORE_PASSWORD;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_SSL_KEYSTORE_TYPE;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_SSL_PROTOCOLS;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_SSL_REQUIRE_AUTHENTICATION;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_SSL_TRUSTSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_SSL_TRUSTSTORE_PASSWORD;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_PEER_AUTHENTICATOR;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_PEER_AUTH_INIT;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_UDP_DHALGO;
import static org.apache.geode.distributed.ConfigurationProperties.SERVER_SSL_CIPHERS;
import static org.apache.geode.distributed.ConfigurationProperties.SERVER_SSL_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.SERVER_SSL_KEYSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.SERVER_SSL_KEYSTORE_PASSWORD;
import static org.apache.geode.distributed.ConfigurationProperties.SERVER_SSL_KEYSTORE_TYPE;
import static org.apache.geode.distributed.ConfigurationProperties.SERVER_SSL_PROTOCOLS;
import static org.apache.geode.distributed.ConfigurationProperties.SERVER_SSL_REQUIRE_AUTHENTICATION;
import static org.apache.geode.distributed.ConfigurationProperties.SERVER_SSL_TRUSTSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.SERVER_SSL_TRUSTSTORE_PASSWORD;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_ENABLED_COMPONENTS;
import static org.apache.geode.internal.security.SecurableCommunicationChannel.ALL;
import static org.apache.geode.internal.security.SecurableCommunicationChannel.CLUSTER;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

import org.apache.geode.GemFireConfigException;
import org.apache.geode.GemFireIOException;
import org.apache.geode.InternalGemFireException;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.internal.ConfigSource;
import org.apache.geode.internal.inet.LocalHostUtil;
import org.apache.geode.internal.logging.LogWriterImpl;
import org.apache.geode.internal.process.ProcessLauncherContext;
import org.apache.geode.internal.security.SecurableCommunicationChannel;
import org.apache.geode.security.AuthTokenEnabledComponents;
import org.apache.geode.util.internal.GeodeGlossary;

/**
 * Provides an implementation of <code>DistributionConfig</code> that knows how to read the
 * configuration file.
 * <p>
 * Note that if you add a property to this interface, should should update the
 * {@link #DistributionConfigImpl(DistributionConfig) copy constructor}.
 *
 * @see InternalDistributedSystem
 * @since GemFire 2.1
 */
public class DistributionConfigImpl extends AbstractDistributionConfig implements Serializable {

  private static final long serialVersionUID = 4096393792893825167L;

  /**
   * The name of the distribution manager/shared memory connection
   */
  private String name = DEFAULT_NAME;

  /**
   * The tcp/ip port used for distribution
   */
  private int tcpPort = DEFAULT_TCP_PORT;

  /**
   * The multicast port used for distribution
   */
  private int mcastPort = DEFAULT_MCAST_PORT;

  /**
   * The multicast ttl used for distribution
   */
  private int mcastTtl = DEFAULT_MCAST_TTL;

  private int socketLeaseTime = DEFAULT_SOCKET_LEASE_TIME;
  private int socketBufferSize = DEFAULT_SOCKET_BUFFER_SIZE;
  private boolean conserveSockets = DEFAULT_CONSERVE_SOCKETS;

  /**
   * Comma-delimited list of the application roles performed by this member.
   */
  private String roles = DEFAULT_ROLES;

  /**
   * The multicast address used for distribution
   */
  private InetAddress mcastAddress = DEFAULT_MCAST_ADDRESS;

  /**
   * The address server socket's should listen on
   */
  private String bindAddress = DEFAULT_BIND_ADDRESS;

  /**
   * The address server socket's in a client-server topology should listen on
   */
  private String serverBindAddress = DEFAULT_SERVER_BIND_ADDRESS;

  /**
   * The locations of the distribution locators
   */
  private String locators = DEFAULT_LOCATORS;

  /**
   * The amount of time to wait for a locator to appear when starting up
   */
  private int locatorWaitTime;

  /**
   * The name of the log file
   */
  private File logFile = DEFAULT_LOG_FILE;

  private File deployWorkingDir = new File(System.getProperty("user.dir"));

  /**
   * The level at which log messages are logged
   *
   * @see LogWriterImpl#levelNameToCode(String)
   */
  protected int logLevel = DEFAULT_LOG_LEVEL;

  /**
   * bind-address and host of locator to start
   */
  private String startLocator = DEFAULT_START_LOCATOR;

  /**
   * port of locator to start. use bind-address as host name
   */
  private int startLocatorPort;

  /**
   * Is statistic sampling enabled?
   */
  protected boolean statisticSamplingEnabled = DEFAULT_STATISTIC_SAMPLING_ENABLED;

  /**
   * The rate (in milliseconds) at which statistics are sampled
   */
  protected int statisticSampleRate = DEFAULT_STATISTIC_SAMPLE_RATE;

  /**
   * The name of the file to which statistics should be archived
   */
  File statisticArchiveFile = DEFAULT_STATISTIC_ARCHIVE_FILE;

  /**
   * The amount of time to wait for a ACK message
   */
  private int ackWaitThreshold = DEFAULT_ACK_WAIT_THRESHOLD;

  /**
   * The amount of time to wait for a ACK message after the ackWaitThreshold before shunning members
   * that haven't responded. If zero, this feature is disabled.
   */
  private int ackForceDisconnectThreshold = DEFAULT_ACK_SEVERE_ALERT_THRESHOLD;

  /**
   * The name of an XML file used to initialize the cache
   */
  private File cacheXmlFile = Boolean.getBoolean(InternalLocator.FORCE_LOCATOR_DM_TYPE)
      ? new File("") : DEFAULT_CACHE_XML_FILE;

  protected int archiveDiskSpaceLimit = DEFAULT_ARCHIVE_DISK_SPACE_LIMIT;
  protected int archiveFileSizeLimit = DEFAULT_ARCHIVE_FILE_SIZE_LIMIT;
  protected int logDiskSpaceLimit = DEFAULT_LOG_DISK_SPACE_LIMIT;
  protected int logFileSizeLimit = DEFAULT_LOG_FILE_SIZE_LIMIT;

  @Deprecated
  private boolean clusterSSLEnabled = DEFAULT_SSL_ENABLED;
  @Deprecated
  private String clusterSSLProtocols = DEFAULT_SSL_PROTOCOLS;
  @Deprecated
  private String clusterSSLCiphers = DEFAULT_SSL_CIPHERS;
  @Deprecated
  private boolean clusterSSLRequireAuthentication = DEFAULT_SSL_REQUIRE_AUTHENTICATION;
  @Deprecated
  private String clusterSSLKeyStore = DEFAULT_SSL_KEYSTORE;
  @Deprecated
  private String clusterSSLKeyStoreType = DEFAULT_CLUSTER_SSL_KEYSTORE_TYPE;
  @Deprecated
  private String clusterSSLKeyStorePassword = DEFAULT_SSL_KEYSTORE_PASSWORD;
  @Deprecated
  private String clusterSSLTrustStore = DEFAULT_SSL_TRUSTSTORE;
  @Deprecated
  private String clusterSSLTrustStorePassword = DEFAULT_SSL_TRUSTSTORE_PASSWORD;

  private String clusterSSLAlias = DEFAULT_SSL_ALIAS;

  /**
   * multicast send buffer size, in bytes
   */
  private int mcastSendBufferSize = DEFAULT_MCAST_SEND_BUFFER_SIZE;
  /**
   * multicast receive buffer size, in bytes
   */
  private int mcastRecvBufferSize = DEFAULT_MCAST_RECV_BUFFER_SIZE;
  /**
   * flow-of-control parameters for multicast messaging
   */
  private FlowControlParams mcastFlowControl = DEFAULT_MCAST_FLOW_CONTROL;

  /**
   * datagram socket send buffer size, in bytes
   */
  private int udpSendBufferSize = DEFAULT_UDP_SEND_BUFFER_SIZE;
  /**
   * datagram socket receive buffer size, in bytes
   */
  private int udpRecvBufferSize = DEFAULT_UDP_RECV_BUFFER_SIZE;
  /**
   * max datagram message size, in bytes. This should be < 64k
   */
  private int udpFragmentSize = DEFAULT_UDP_FRAGMENT_SIZE;

  /**
   * whether tcp/ip sockets should be disabled
   */
  protected boolean disableTcp = DEFAULT_DISABLE_TCP;

  /**
   * whether JMX should be disabled
   */
  protected boolean disableJmx = DEFAULT_DISABLE_JMX;

  /**
   * whether time statistics should be enabled for the distributed system
   */
  protected boolean enableTimeStatistics = DEFAULT_ENABLE_TIME_STATISTICS;

  /**
   * member contact timeout, in milliseconds, for failure detection
   */
  protected int memberTimeout = DEFAULT_MEMBER_TIMEOUT;

  /**
   * the Jgroups port ranges allowed
   */
  private int[] membershipPortRange = DEFAULT_MEMBERSHIP_PORT_RANGE;

  /**
   * Max wait time for the member before reconnecting to the DS in case of required role loss.
   */
  private int maxWaitTimeForReconnect = DEFAULT_MAX_WAIT_TIME_FOR_RECONNECT;
  /**
   * Max number of tries allowed for reconnect in case of required role loss.
   */
  private int maxNumReconnectTries = DEFAULT_MAX_NUM_RECONNECT_TRIES;

  private int asyncDistributionTimeout = DEFAULT_ASYNC_DISTRIBUTION_TIMEOUT;
  private int asyncQueueTimeout = DEFAULT_ASYNC_QUEUE_TIMEOUT;
  private int asyncMaxQueueSize = DEFAULT_ASYNC_MAX_QUEUE_SIZE;

  /**
   * @since GemFire 5.7
   */
  private String clientConflation = CLIENT_CONFLATION_PROP_VALUE_DEFAULT;

  /**
   * The id of the durable client
   */
  private String durableClientId = DEFAULT_DURABLE_CLIENT_ID;

  /**
   * The timeout of the durable client
   */
  private int durableClientTimeout = DEFAULT_DURABLE_CLIENT_TIMEOUT;

  /**
   * The client authentication initialization method name
   */
  private String securityClientAuthInit = DEFAULT_SECURITY_CLIENT_AUTH_INIT;

  /**
   * The client authenticating method name
   */
  private String securityClientAuthenticator = DEFAULT_SECURITY_CLIENT_AUTHENTICATOR;

  /**
   * The security manager class name
   */
  private String securityManager = DEFAULT_SECURITY_MANAGER;

  /**
   * The post processor class name
   */
  private String postProcessor = DEFAULT_SECURITY_POST_PROCESSOR;

  /**
   * The client Diffie-Hellman method name
   */
  private String securityClientDHAlgo = DEFAULT_SECURITY_CLIENT_DHALGO;

  /**
   * The udp Diffie-Hellman method name
   */
  private String securityUDPDHAlgo = DEFAULT_SECURITY_UDP_DHALGO;

  /**
   * The peer authentication initialization method name
   */
  private String securityPeerAuthInit = DEFAULT_SECURITY_PEER_AUTH_INIT;

  /**
   * The peer authenticating method name
   */
  private String securityPeerAuthenticator = DEFAULT_SECURITY_PEER_AUTHENTICATOR;

  /**
   * The client authorization method name
   */
  private String securityClientAccessor = DEFAULT_SECURITY_CLIENT_ACCESSOR;

  /**
   * The post-processing client authorization method name
   */
  private String securityClientAccessorPP = DEFAULT_SECURITY_CLIENT_ACCESSOR_PP;

  /**
   * The level at which security related log messages are logged
   *
   * @see LogWriterImpl#levelNameToCode(String)
   */
  private int securityLogLevel = DEFAULT_LOG_LEVEL;

  /**
   * whether network partition detection algorithms are enabled
   */
  private boolean enableNetworkPartitionDetection = DEFAULT_ENABLE_NETWORK_PARTITION_DETECTION;

  /**
   * whether auto reconnect after network partition is disabled
   */
  private boolean disableAutoReconnect = DEFAULT_DISABLE_AUTO_RECONNECT;

  /**
   * The security log file
   */
  private File securityLogFile = DEFAULT_SECURITY_LOG_FILE;

  /**
   * The p2p membership check timeout
   */
  private int securityPeerMembershipTimeout = DEFAULT_SECURITY_PEER_VERIFYMEMBER_TIMEOUT;

  /**
   * The member security credentials
   */
  private final Properties security = new Properties();

  /**
   * The User defined properties to be used for cache.xml replacements
   */
  private final Properties userDefinedProps = new Properties();
  /**
   * Prefix to use for properties that are put as JVM java properties for use with layers (e.g.
   * jgroups membership) that do not have a <code>DistributionConfig</code> object.
   */
  public static final String SECURITY_SYSTEM_PREFIX = GeodeGlossary.GEMFIRE_PREFIX + "sys.";

  /**
   * whether to remove unresponsive client or not
   */
  private boolean removeUnresponsiveClient = DEFAULT_REMOVE_UNRESPONSIVE_CLIENT;

  /**
   * Is delta propagation enabled or not
   **/
  private boolean deltaPropagation = DEFAULT_DELTA_PROPAGATION;

  private Map props;

  private int distributedSystemId = DistributionConfig.DEFAULT_DISTRIBUTED_SYSTEM_ID;

  /**
   * The locations of the remote distribution locators
   */
  private String remoteLocators = DEFAULT_REMOTE_LOCATORS;

  private boolean enforceUniqueHost = DistributionConfig.DEFAULT_ENFORCE_UNIQUE_HOST;

  private String redundancyZone = DistributionConfig.DEFAULT_REDUNDANCY_ZONE;

  /**
   * holds the ssl properties specified in gfsecurity.properties
   */
  private Properties sslProperties = new Properties();

  /**
   * holds the ssl properties specified in gfsecurity.properties
   */
  private Properties clusterSSLProperties = new Properties();

  private String groups = DEFAULT_GROUPS;

  private boolean enableSharedConfiguration =
      DistributionConfig.DEFAULT_ENABLE_CLUSTER_CONFIGURATION;
  private boolean enableManagementRestService =
      DistributionConfig.DEFAULT_ENABLE_MANAGEMENT_REST_SERVICE;
  private boolean useSharedConfiguration = DistributionConfig.DEFAULT_USE_CLUSTER_CONFIGURATION;
  private boolean loadSharedConfigurationFromDir =
      DistributionConfig.DEFAULT_LOAD_CLUSTER_CONFIG_FROM_DIR;
  private String clusterConfigDir = "";


  private int httpServicePort = DEFAULT_HTTP_SERVICE_PORT;

  private String httpServiceBindAddress = DEFAULT_HTTP_SERVICE_BIND_ADDRESS;

  private boolean startDevRestApi = DEFAULT_START_DEV_REST_API;

  /**
   * port on which GemFireMemcachedServer server is started
   */
  private int memcachedPort;

  /**
   * protocol for GemFireMemcachedServer
   */
  private String memcachedProtocol = DEFAULT_MEMCACHED_PROTOCOL;

  /**
   * Bind address for GemFireMemcachedServer
   */
  private String memcachedBindAddress = DEFAULT_MEMCACHED_BIND_ADDRESS;

  /**
   * Are distributed transactions enabled or not
   */
  private boolean distributedTransactions = DEFAULT_DISTRIBUTED_TRANSACTIONS;

  private boolean jmxManager =
      Boolean.getBoolean(InternalLocator.FORCE_LOCATOR_DM_TYPE) || DEFAULT_JMX_MANAGER;
  private boolean jmxManagerStart = DEFAULT_JMX_MANAGER_START;
  private int jmxManagerPort = DEFAULT_JMX_MANAGER_PORT;
  private String jmxManagerBindAddress = DEFAULT_JMX_MANAGER_BIND_ADDRESS;
  private String jmxManagerHostnameForClients = DEFAULT_JMX_MANAGER_HOSTNAME_FOR_CLIENTS;
  private String jmxManagerPasswordFile = DEFAULT_JMX_MANAGER_PASSWORD_FILE;
  private String jmxManagerAccessFile = DEFAULT_JMX_MANAGER_ACCESS_FILE;
  private int jmxManagerHttpPort = DEFAULT_HTTP_SERVICE_PORT;
  private int jmxManagerUpdateRate = DEFAULT_JMX_MANAGER_UPDATE_RATE;

  @Deprecated
  private boolean jmxManagerSSLEnabled = DEFAULT_JMX_MANAGER_SSL_ENABLED;
  @Deprecated
  private boolean jmxManagerSslRequireAuthentication =
      DEFAULT_JMX_MANAGER_SSL_REQUIRE_AUTHENTICATION;
  @Deprecated
  private String jmxManagerSslProtocols = DEFAULT_JMX_MANAGER_SSL_PROTOCOLS;
  @Deprecated
  private String jmxManagerSslCiphers = DEFAULT_JMX_MANAGER_SSL_CIPHERS;
  @Deprecated
  private Properties jmxManagerSslProperties = new Properties();
  @Deprecated
  private String jmxManagerSSLKeyStore = DEFAULT_JMX_MANAGER_SSL_KEYSTORE;
  @Deprecated
  private String jmxManagerSSLKeyStoreType = DEFAULT_JMX_MANAGER_SSL_KEYSTORE_TYPE;
  @Deprecated
  private String jmxManagerSSLKeyStorePassword = DEFAULT_JMX_MANAGER_SSL_KEYSTORE_PASSWORD;
  @Deprecated
  private String jmxManagerSSLTrustStore = DEFAULT_JMX_MANAGER_SSL_TRUSTSTORE;
  @Deprecated
  private String jmxManagerSSLTrustStorePassword = DEFAULT_JMX_MANAGER_SSL_TRUSTSTORE_PASSWORD;

  private String jmxManagerSSLAlias = DEFAULT_SSL_ALIAS;

  @Deprecated
  private boolean serverSSLEnabled = DEFAULT_SERVER_SSL_ENABLED;
  @Deprecated
  private boolean serverSslRequireAuthentication = DEFAULT_SERVER_SSL_REQUIRE_AUTHENTICATION;
  @Deprecated
  private String serverSslProtocols = DEFAULT_SERVER_SSL_PROTOCOLS;
  @Deprecated
  private String serverSslCiphers = DEFAULT_SERVER_SSL_CIPHERS;
  @Deprecated
  private Properties serverSslProperties = new Properties();
  @Deprecated
  private String serverSSLKeyStore = DEFAULT_SERVER_SSL_KEYSTORE;
  @Deprecated
  private String serverSSLKeyStoreType = DEFAULT_SERVER_SSL_KEYSTORE_TYPE;
  @Deprecated
  private String serverSSLKeyStorePassword = DEFAULT_SERVER_SSL_KEYSTORE_PASSWORD;
  @Deprecated
  private String serverSSLTrustStore = DEFAULT_SERVER_SSL_TRUSTSTORE;
  @Deprecated
  private String serverSSLTrustStorePassword = DEFAULT_SERVER_SSL_TRUSTSTORE_PASSWORD;

  private String serverSSLAlias = DEFAULT_SSL_ALIAS;

  @Deprecated
  private boolean gatewaySSLEnabled = DEFAULT_GATEWAY_SSL_ENABLED;
  @Deprecated
  private boolean gatewaySslRequireAuthentication = DEFAULT_GATEWAY_SSL_REQUIRE_AUTHENTICATION;
  @Deprecated
  private String gatewaySslProtocols = DEFAULT_GATEWAY_SSL_PROTOCOLS;
  @Deprecated
  private String gatewaySslCiphers = DEFAULT_GATEWAY_SSL_CIPHERS;
  @Deprecated
  private Properties gatewaySslProperties = new Properties();
  @Deprecated
  private String gatewaySSLKeyStore = DEFAULT_GATEWAY_SSL_KEYSTORE;
  @Deprecated
  private String gatewaySSLKeyStoreType = DEFAULT_GATEWAY_SSL_KEYSTORE_TYPE;
  @Deprecated
  private String gatewaySSLKeyStorePassword = DEFAULT_GATEWAY_SSL_KEYSTORE_PASSWORD;
  @Deprecated
  private String gatewaySSLTrustStore = DEFAULT_GATEWAY_SSL_TRUSTSTORE;
  @Deprecated
  private String gatewaySSLTrustStorePassword = DEFAULT_GATEWAY_SSL_TRUSTSTORE_PASSWORD;

  private String gatewaySSLAlias = DEFAULT_SSL_ALIAS;

  @Deprecated
  private boolean httpServiceSSLEnabled = DEFAULT_HTTP_SERVICE_SSL_ENABLED;
  @Deprecated
  private boolean httpServiceSSLRequireAuthentication =
      DEFAULT_HTTP_SERVICE_SSL_REQUIRE_AUTHENTICATION;
  @Deprecated
  private String httpServiceSSLProtocols = DEFAULT_HTTP_SERVICE_SSL_PROTOCOLS;
  @Deprecated
  private String httpServiceSSLCiphers = DEFAULT_HTTP_SERVICE_SSL_CIPHERS;
  @Deprecated
  private Properties httpServiceSSLProperties = new Properties();
  @Deprecated
  private String httpServiceSSLKeyStore = DEFAULT_HTTP_SERVICE_SSL_KEYSTORE;
  @Deprecated
  private String httpServiceSSLKeyStoreType = DEFAULT_HTTP_SERVICE_SSL_KEYSTORE_TYPE;
  @Deprecated
  private String httpServiceSSLKeyStorePassword = DEFAULT_HTTP_SERVICE_SSL_KEYSTORE_PASSWORD;
  @Deprecated
  private String httpServiceSSLTrustStore = DEFAULT_HTTP_SERVICE_SSL_TRUSTSTORE;
  @Deprecated
  private String httpServiceSSLTrustStorePassword = DEFAULT_HTTP_SERVICE_SSL_TRUSTSTORE_PASSWORD;

  private String httpServiceSSLAlias = DEFAULT_SSL_ALIAS;

  private Boolean sslEndPointIdentificationEnabled = null;

  private SecurableCommunicationChannel[] securableCommunicationChannels =
      DEFAULT_SSL_ENABLED_COMPONENTS;
  private String[] securityAuthTokenEnabledComponents =
      DEFAULT_SECURITY_AUTH_TOKEN_ENABLED_COMPONENTS;

  private boolean sslUseDefaultSSLContext = DEFAULT_SSL_USE_DEFAULT_CONTEXT;
  private String sslProtocols = DEFAULT_SSL_PROTOCOLS;
  private String sslClientProtocols = DEFAULT_SSL_CLIENT_PROTOCOLS;
  private String sslServerProtocols = DEFAULT_SSL_SERVER_PROTOCOLS;
  private String sslCiphers = DEFAULT_SSL_CIPHERS;
  private boolean sslRequireAuthentication = DEFAULT_SSL_REQUIRE_AUTHENTICATION;
  private String sslKeyStore = DEFAULT_SSL_KEYSTORE;
  private String sslKeyStoreType = DEFAULT_CLUSTER_SSL_KEYSTORE_TYPE;
  private String sslKeyStorePassword = DEFAULT_SSL_KEYSTORE_PASSWORD;
  private String sslTrustStore = DEFAULT_SSL_TRUSTSTORE;
  private String sslTrustStorePassword = DEFAULT_SSL_TRUSTSTORE_PASSWORD;
  private String sslTrustStoreType = DEFAULT_CLUSTER_SSL_KEYSTORE_TYPE;
  private boolean sslWebServiceRequireAuthentication =
      DEFAULT_SSL_WEB_SERVICE_REQUIRE_AUTHENTICATION;

  private String locatorSSLAlias = DEFAULT_SSL_ALIAS;

  private String sslDefaultAlias = DEFAULT_SSL_ALIAS;

  /**
   * The SSL Parameter Extension class name
   */
  private String sslParameterExtension = DEFAULT_SSL_PARAMETER_EXTENSION;

  private Map<String, ConfigSource> sourceMap =
      Collections.synchronizedMap(new HashMap<>());

  private String userCommandPackages = DEFAULT_USER_COMMAND_PACKAGES;

  private boolean validateSerializableObjects = DEFAULT_VALIDATE_SERIALIZABLE_OBJECTS;
  private String serializableObjectFilter = DEFAULT_SERIALIZABLE_OBJECT_FILTER;

  /**
   * "off-heap-memory-size" with value of "" or "<size>[g|m]"
   */
  protected String offHeapMemorySize = DEFAULT_OFF_HEAP_MEMORY_SIZE;

  /**
   * Whether pages should be locked into memory or allowed to swap to disk
   */
  private boolean lockMemory = DEFAULT_LOCK_MEMORY;

  private String shiroInit = "";

  /**
   * Is thread monitoring enabled
   */
  private boolean threadMonitorEnabled = DEFAULT_THREAD_MONITOR_ENABLED;

  /**
   * the thread monitoring interval
   */
  private int threadMonitorInterval = DEFAULT_THREAD_MONITOR_INTERVAL;

  /**
   * the thread monitoring time limit after which the monitored thread is considered stuck
   */
  private int threadMonitorTimeLimit = DEFAULT_THREAD_MONITOR_TIME_LIMIT;

  /**
   * Create a new <code>DistributionConfigImpl</code> from the contents of another
   * <code>DistributionConfig</code>.
   */
  public DistributionConfigImpl(DistributionConfig other) {
    name = other.getName();
    tcpPort = other.getTcpPort();
    mcastPort = other.getMcastPort();
    mcastTtl = other.getMcastTtl();
    socketLeaseTime = other.getSocketLeaseTime();
    socketBufferSize = other.getSocketBufferSize();
    conserveSockets = other.getConserveSockets();
    roles = other.getRoles();
    mcastAddress = other.getMcastAddress();
    bindAddress = other.getBindAddress();
    serverBindAddress = other.getServerBindAddress();
    locators = ((DistributionConfigImpl) other).locators;
    locatorWaitTime = other.getLocatorWaitTime();
    remoteLocators = other.getRemoteLocators();
    startLocator = other.getStartLocator();
    startLocatorPort = ((DistributionConfigImpl) other).startLocatorPort;
    deployWorkingDir = other.getDeployWorkingDir();
    logFile = other.getLogFile();
    logLevel = other.getLogLevel();
    statisticSamplingEnabled = other.getStatisticSamplingEnabled();
    threadMonitorEnabled = other.getThreadMonitorEnabled();
    threadMonitorInterval = other.getThreadMonitorInterval();
    threadMonitorTimeLimit = other.getThreadMonitorTimeLimit();
    statisticSampleRate = other.getStatisticSampleRate();
    statisticArchiveFile = other.getStatisticArchiveFile();
    ackWaitThreshold = other.getAckWaitThreshold();
    ackForceDisconnectThreshold = other.getAckSevereAlertThreshold();
    cacheXmlFile = other.getCacheXmlFile();
    archiveDiskSpaceLimit = other.getArchiveDiskSpaceLimit();
    archiveFileSizeLimit = other.getArchiveFileSizeLimit();
    logDiskSpaceLimit = other.getLogDiskSpaceLimit();
    logFileSizeLimit = other.getLogFileSizeLimit();
    clusterSSLEnabled = other.getClusterSSLEnabled();
    clusterSSLProtocols = other.getClusterSSLProtocols();
    clusterSSLCiphers = other.getClusterSSLCiphers();
    clusterSSLRequireAuthentication = other.getClusterSSLRequireAuthentication();
    clusterSSLKeyStore = other.getClusterSSLKeyStore();
    clusterSSLKeyStoreType = other.getClusterSSLKeyStoreType();
    clusterSSLKeyStorePassword = other.getClusterSSLKeyStorePassword();
    clusterSSLTrustStore = other.getClusterSSLTrustStore();
    clusterSSLTrustStorePassword = other.getClusterSSLTrustStorePassword();
    asyncDistributionTimeout = other.getAsyncDistributionTimeout();
    asyncQueueTimeout = other.getAsyncQueueTimeout();
    asyncMaxQueueSize = other.getAsyncMaxQueueSize();
    modifiable = true;
    // the following were added after version 4.1.2
    mcastSendBufferSize = other.getMcastSendBufferSize();
    mcastRecvBufferSize = other.getMcastRecvBufferSize();
    mcastFlowControl = other.getMcastFlowControl();
    udpSendBufferSize = other.getUdpSendBufferSize();
    udpRecvBufferSize = other.getUdpRecvBufferSize();
    udpFragmentSize = other.getUdpFragmentSize();
    disableTcp = other.getDisableTcp();
    disableJmx = other.getDisableJmx();
    enableTimeStatistics = other.getEnableTimeStatistics();
    memberTimeout = other.getMemberTimeout();
    membershipPortRange = other.getMembershipPortRange();
    maxWaitTimeForReconnect = other.getMaxWaitTimeForReconnect();
    maxNumReconnectTries = other.getMaxNumReconnectTries();
    clientConflation = other.getClientConflation();
    durableClientId = other.getDurableClientId();
    durableClientTimeout = other.getDurableClientTimeout();

    enableNetworkPartitionDetection = other.getEnableNetworkPartitionDetection();
    disableAutoReconnect = other.getDisableAutoReconnect();

    securityClientAuthInit = other.getSecurityClientAuthInit();
    securityClientAuthenticator = other.getSecurityClientAuthenticator();
    securityClientDHAlgo = other.getSecurityClientDHAlgo();
    securityUDPDHAlgo = other.getSecurityUDPDHAlgo();
    securityPeerAuthInit = other.getSecurityPeerAuthInit();
    securityPeerAuthenticator = other.getSecurityPeerAuthenticator();
    securityClientAccessor = other.getSecurityClientAccessor();
    securityClientAccessorPP = other.getSecurityClientAccessorPP();
    securityPeerMembershipTimeout = other.getSecurityPeerMembershipTimeout();
    securityLogLevel = other.getSecurityLogLevel();
    securityLogFile = other.getSecurityLogFile();
    security.putAll(other.getSecurityProps());
    removeUnresponsiveClient = other.getRemoveUnresponsiveClient();
    deltaPropagation = other.getDeltaPropagation();
    distributedSystemId = other.getDistributedSystemId();
    redundancyZone = other.getRedundancyZone();
    enforceUniqueHost = other.getEnforceUniqueHost();
    sslProperties = other.getSSLProperties();
    clusterSSLProperties = other.getClusterSSLProperties();
    jmxManagerSslProperties = other.getJmxSSLProperties();
    // Similar to this.security, assigning userDefinedProps
    userDefinedProps.putAll(other.getUserDefinedProps());

    // following added for 7.0
    groups = other.getGroups();
    jmxManager = other.getJmxManager();
    jmxManagerStart = other.getJmxManagerStart();
    jmxManagerSSLEnabled = other.getJmxManagerSSLEnabled();
    jmxManagerSslRequireAuthentication = other.getJmxManagerSSLRequireAuthentication();
    jmxManagerSslProtocols = other.getJmxManagerSSLProtocols();
    jmxManagerSslCiphers = other.getJmxManagerSSLCiphers();
    jmxManagerSSLKeyStore = other.getJmxManagerSSLKeyStore();
    jmxManagerSSLKeyStoreType = other.getJmxManagerSSLKeyStoreType();
    jmxManagerSSLKeyStorePassword = other.getJmxManagerSSLKeyStorePassword();
    jmxManagerSSLTrustStore = other.getJmxManagerSSLTrustStore();
    jmxManagerSSLTrustStorePassword = other.getJmxManagerSSLTrustStorePassword();
    jmxManagerSslProperties = other.getJmxSSLProperties();
    jmxManagerPort = other.getJmxManagerPort();
    jmxManagerBindAddress = other.getJmxManagerBindAddress();
    jmxManagerHostnameForClients = other.getJmxManagerHostnameForClients();
    jmxManagerPasswordFile = other.getJmxManagerPasswordFile();
    jmxManagerAccessFile = other.getJmxManagerAccessFile();
    jmxManagerHttpPort = other.getJmxManagerHttpPort();
    jmxManagerUpdateRate = other.getJmxManagerUpdateRate();
    memcachedPort = other.getMemcachedPort();
    memcachedProtocol = other.getMemcachedProtocol();
    memcachedBindAddress = other.getMemcachedBindAddress();
    userCommandPackages = other.getUserCommandPackages();

    // following added for 8.0
    enableSharedConfiguration = other.getEnableClusterConfiguration();
    loadSharedConfigurationFromDir = other.getLoadClusterConfigFromDir();
    clusterConfigDir = other.getClusterConfigDir();
    useSharedConfiguration = other.getUseSharedConfiguration();
    serverSSLEnabled = other.getServerSSLEnabled();
    serverSslRequireAuthentication = other.getServerSSLRequireAuthentication();
    serverSslProtocols = other.getServerSSLProtocols();
    serverSslCiphers = other.getServerSSLCiphers();
    serverSSLKeyStore = other.getServerSSLKeyStore();
    serverSSLKeyStoreType = other.getServerSSLKeyStoreType();
    serverSSLKeyStorePassword = other.getServerSSLKeyStorePassword();
    serverSSLTrustStore = other.getServerSSLTrustStore();
