/*
 * 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.ACK_SEVERE_ALERT_THRESHOLD;
import static org.apache.geode.distributed.ConfigurationProperties.ACK_WAIT_THRESHOLD;
import static org.apache.geode.distributed.ConfigurationProperties.ARCHIVE_DISK_SPACE_LIMIT;
import static org.apache.geode.distributed.ConfigurationProperties.ARCHIVE_FILE_SIZE_LIMIT;
import static org.apache.geode.distributed.ConfigurationProperties.ASYNC_DISTRIBUTION_TIMEOUT;
import static org.apache.geode.distributed.ConfigurationProperties.ASYNC_MAX_QUEUE_SIZE;
import static org.apache.geode.distributed.ConfigurationProperties.ASYNC_QUEUE_TIMEOUT;
import static org.apache.geode.distributed.ConfigurationProperties.BIND_ADDRESS;
import static org.apache.geode.distributed.ConfigurationProperties.CACHE_XML_FILE;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_CONFIGURATION_DIR;
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.CONFLATE_EVENTS;
import static org.apache.geode.distributed.ConfigurationProperties.CONSERVE_SOCKETS;
import static org.apache.geode.distributed.ConfigurationProperties.DELTA_PROPAGATION;
import static org.apache.geode.distributed.ConfigurationProperties.DEPLOY_WORKING_DIR;
import static org.apache.geode.distributed.ConfigurationProperties.DISABLE_AUTO_RECONNECT;
import static org.apache.geode.distributed.ConfigurationProperties.DISABLE_JMX;
import static org.apache.geode.distributed.ConfigurationProperties.DISABLE_TCP;
import static org.apache.geode.distributed.ConfigurationProperties.DISTRIBUTED_SYSTEM_ID;
import static org.apache.geode.distributed.ConfigurationProperties.DISTRIBUTED_TRANSACTIONS;
import static org.apache.geode.distributed.ConfigurationProperties.DURABLE_CLIENT_ID;
import static org.apache.geode.distributed.ConfigurationProperties.DURABLE_CLIENT_TIMEOUT;
import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_CLUSTER_CONFIGURATION;
import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_MANAGEMENT_REST_SERVICE;
import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_NETWORK_PARTITION_DETECTION;
import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_TIME_STATISTICS;
import static org.apache.geode.distributed.ConfigurationProperties.ENFORCE_UNIQUE_HOST;
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.GROUPS;
import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_BIND_ADDRESS;
import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_PORT;
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;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_ACCESS_FILE;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_BIND_ADDRESS;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_HOSTNAME_FOR_CLIENTS;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_HTTP_PORT;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_PASSWORD_FILE;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_PORT;
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.JMX_MANAGER_START;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_UPDATE_RATE;
import static org.apache.geode.distributed.ConfigurationProperties.LOAD_CLUSTER_CONFIGURATION_FROM_DIR;
import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
import static org.apache.geode.distributed.ConfigurationProperties.LOCATOR_WAIT_TIME;
import static org.apache.geode.distributed.ConfigurationProperties.LOCK_MEMORY;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_DISK_SPACE_LIMIT;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_FILE;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_FILE_SIZE_LIMIT;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_LEVEL;
import static org.apache.geode.distributed.ConfigurationProperties.MAX_NUM_RECONNECT_TRIES;
import static org.apache.geode.distributed.ConfigurationProperties.MAX_WAIT_TIME_RECONNECT;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_ADDRESS;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_FLOW_CONTROL;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_RECV_BUFFER_SIZE;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_SEND_BUFFER_SIZE;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_TTL;
import static org.apache.geode.distributed.ConfigurationProperties.MEMBERSHIP_PORT_RANGE;
import static org.apache.geode.distributed.ConfigurationProperties.MEMBER_TIMEOUT;
import static org.apache.geode.distributed.ConfigurationProperties.MEMCACHED_BIND_ADDRESS;
import static org.apache.geode.distributed.ConfigurationProperties.MEMCACHED_PORT;
import static org.apache.geode.distributed.ConfigurationProperties.MEMCACHED_PROTOCOL;
import static org.apache.geode.distributed.ConfigurationProperties.NAME;
import static org.apache.geode.distributed.ConfigurationProperties.OFF_HEAP_MEMORY_SIZE;
import static org.apache.geode.distributed.ConfigurationProperties.REDUNDANCY_ZONE;
import static org.apache.geode.distributed.ConfigurationProperties.REMOTE_LOCATORS;
import static org.apache.geode.distributed.ConfigurationProperties.REMOVE_UNRESPONSIVE_CLIENT;
import static org.apache.geode.distributed.ConfigurationProperties.ROLES;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_AUTH_TOKEN_ENABLED_COMPONENTS;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_CLIENT_ACCESSOR;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_CLIENT_ACCESSOR_PP;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_CLIENT_AUTHENTICATOR;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_CLIENT_AUTH_INIT;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_CLIENT_DHALGO;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_LOG_FILE;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_LOG_LEVEL;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_MANAGER;
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_PEER_VERIFY_MEMBER_TIMEOUT;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_POST_PROCESSOR;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_PREFIX;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_SHIRO_INIT;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_UDP_DHALGO;
import static org.apache.geode.distributed.ConfigurationProperties.SERIALIZABLE_OBJECT_FILTER;
import static org.apache.geode.distributed.ConfigurationProperties.SERVER_BIND_ADDRESS;
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.SOCKET_BUFFER_SIZE;
import static org.apache.geode.distributed.ConfigurationProperties.SOCKET_LEASE_TIME;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_CIPHERS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_CLIENT_PROTOCOLS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_CLUSTER_ALIAS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_DEFAULT_ALIAS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_ENABLED_COMPONENTS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_ENDPOINT_IDENTIFICATION_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_GATEWAY_ALIAS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_JMX_ALIAS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE_PASSWORD;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE_TYPE;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_LOCATOR_ALIAS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_PARAMETER_EXTENSION;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_PROTOCOLS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_REQUIRE_AUTHENTICATION;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_SERVER_ALIAS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_SERVER_PROTOCOLS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_TRUSTSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_TRUSTSTORE_PASSWORD;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_TRUSTSTORE_TYPE;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_USE_DEFAULT_CONTEXT;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_WEB_ALIAS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_WEB_SERVICE_REQUIRE_AUTHENTICATION;
import static org.apache.geode.distributed.ConfigurationProperties.START_DEV_REST_API;
import static org.apache.geode.distributed.ConfigurationProperties.START_LOCATOR;
import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_ARCHIVE_FILE;
import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_SAMPLE_RATE;
import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_SAMPLING_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.TCP_PORT;
import static org.apache.geode.distributed.ConfigurationProperties.THREAD_MONITOR_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.THREAD_MONITOR_INTERVAL;
import static org.apache.geode.distributed.ConfigurationProperties.THREAD_MONITOR_TIME_LIMIT;
import static org.apache.geode.distributed.ConfigurationProperties.UDP_FRAGMENT_SIZE;
import static org.apache.geode.distributed.ConfigurationProperties.UDP_RECV_BUFFER_SIZE;
import static org.apache.geode.distributed.ConfigurationProperties.UDP_SEND_BUFFER_SIZE;
import static org.apache.geode.distributed.ConfigurationProperties.USER_COMMAND_PACKAGES;
import static org.apache.geode.distributed.ConfigurationProperties.USE_CLUSTER_CONFIGURATION;
import static org.apache.geode.distributed.ConfigurationProperties.VALIDATE_SERIALIZABLE_OBJECTS;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.geode.GemFireIOException;
import org.apache.geode.LogWriter;
import org.apache.geode.UnmodifiableException;
import org.apache.geode.annotations.Immutable;
import org.apache.geode.annotations.internal.MakeImmutable;
import org.apache.geode.distributed.ConfigurationProperties;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.distributed.internal.membership.api.MembershipConfig;
import org.apache.geode.internal.Config;
import org.apache.geode.internal.ConfigSource;
import org.apache.geode.internal.logging.LogWriterImpl;
import org.apache.geode.internal.security.SecurableCommunicationChannel;
import org.apache.geode.internal.serialization.filter.SerializableObjectConfig;
import org.apache.geode.internal.statistics.StatisticsConfig;
import org.apache.geode.internal.tcp.Connection;
import org.apache.geode.logging.internal.spi.LogConfig;
import org.apache.geode.logging.internal.spi.LogWriterLevel;
import org.apache.geode.util.internal.GeodeGlossary;

/**
 * Provides accessor (and in some cases mutator) methods for the various GemFire distribution
 * configuration properties. The interface also provides constants for the names of properties and
 * their default values.
 * <p>
 * Descriptions of these properties can be found {@link ConfigurationProperties}.
 *
 * @see Config
 * @since GemFire 2.1
 */
public interface DistributionConfig
    extends Config, LogConfig, StatisticsConfig, SerializableObjectConfig {

  /**
   * The static String definition of the prefix used to defined ssl-* properties
   */
  String SSL_PREFIX = "ssl-";

  /**
   * Returns the value of the {@link ConfigurationProperties#NAME} property Gets the member's name.
   * A name is optional and by default empty. If set it must be unique in the ds. When set its used
   * by tools to help identify the member.
   * <p>
   * The default value is: {@link #DEFAULT_NAME}.
   *
   * @return the system's name.
   */
  @Override
  @ConfigAttributeGetter(name = NAME)
  String getName();

  /**
   * Sets the member's name.
   * <p>
   * The name can not be changed while the system is running.
   *
   * @throws IllegalArgumentException if the specified value is not acceptable.
   * @throws UnmodifiableException if this attribute can not be modified.
   * @throws GemFireIOException if the set failure is caused by an error when
   *         writing to the system's configuration file.
   */
  @ConfigAttributeSetter(name = NAME)
  void setName(String value);

  /**
   * The "name" property, representing the system's name
   */
  @ConfigAttribute(type = String.class)
  String NAME_NAME = NAME;

  /**
   * The default system name.
   * <p>
   * Actual value of this constant is <code>""</code>.
   */
  String DEFAULT_NAME = MembershipConfig.DEFAULT_NAME;

  /**
   * Returns the value of the {@link ConfigurationProperties#MCAST_PORT}</a> property
   */
  @ConfigAttributeGetter(name = MCAST_PORT_NAME)
  int getMcastPort();

  /**
   * Sets the value of the {@link ConfigurationProperties#MCAST_PORT} property
   */
  @ConfigAttributeSetter(name = MCAST_PORT_NAME)
  void setMcastPort(int value);

  /**
   * The default value of the {@link ConfigurationProperties#MCAST_PORT} property
   */
  int DEFAULT_MCAST_PORT = MembershipConfig.DEFAULT_MCAST_PORT;

  /**
   * The minimum {@link ConfigurationProperties#MCAST_PORT}.
   * <p>
   * Actual value of this constant is <code>0</code>.
   */
  int MIN_MCAST_PORT = 0;

  /**
   * The maximum {@link ConfigurationProperties#MCAST_PORT}.
   * <p>
   * Actual value of this constant is <code>65535</code>.
   */
  int MAX_MCAST_PORT = 65535;

  /**
   * The name of the {@link ConfigurationProperties#MCAST_PORT} property
   */
  @ConfigAttribute(type = Integer.class, min = MIN_MCAST_PORT, max = MAX_MCAST_PORT)
  String MCAST_PORT_NAME = MCAST_PORT;

  /**
   * Returns the value of the {@link ConfigurationProperties#TCP_PORT} property
   */
  @ConfigAttributeGetter(name = TCP_PORT)
  int getTcpPort();

  /**
   * Sets the value of the {@link ConfigurationProperties#TCP_PORT} property
   */
  @ConfigAttributeSetter(name = TCP_PORT)
  void setTcpPort(int value);

  /**
   * The default value of the {@link ConfigurationProperties#TCP_PORT} property
   */
  int DEFAULT_TCP_PORT = 0;

  /**
   * The minimum {@link ConfigurationProperties#TCP_PORT}.
   * <p>
   * Actual value of this constant is <code>0</code>.
   */
  int MIN_TCP_PORT = 0;

  /**
   * The maximum {@link ConfigurationProperties#TCP_PORT}.
   * <p>
   * Actual value of this constant is <code>65535</code>.
   */
  int MAX_TCP_PORT = 65535;

  /**
   * The name of the {@link ConfigurationProperties#TCP_PORT} property
   */
  @ConfigAttribute(type = Integer.class, min = MIN_TCP_PORT, max = MAX_TCP_PORT)
  String TCP_PORT_NAME = TCP_PORT;

  /**
   * Returns the value of the {@link ConfigurationProperties#MCAST_ADDRESS} property
   */
  @ConfigAttributeGetter(name = MCAST_ADDRESS)
  InetAddress getMcastAddress();

  /**
   * Sets the value of the {@link ConfigurationProperties#MCAST_ADDRESS} property
   */
  @ConfigAttributeSetter(name = MCAST_ADDRESS)
  void setMcastAddress(InetAddress value);

  /**
   * The name of the {@link ConfigurationProperties#MCAST_ADDRESS} property
   */
  @ConfigAttribute(type = InetAddress.class)
  String MCAST_ADDRESS_NAME = MCAST_ADDRESS;

  /**
   * The default value of the {@link ConfigurationProperties#MCAST_ADDRESS} property. Current value
   * is <code>239.192.81.1</code>
   */
  InetAddress DEFAULT_MCAST_ADDRESS = _getDefaultMcastAddress();

  static InetAddress _getDefaultMcastAddress() {
    // Default MCast address can be just IPv4 address.
    // On IPv6 machines, JGroups converts IPv4 address to equivalent IPv6 address.
    try {
      String ipLiteral = MembershipConfig.DEFAULT_MCAST_ADDRESS;
      return InetAddress.getByName(ipLiteral);
    } catch (UnknownHostException ex) {
      // this should never happen
      throw new Error(
          String.format("Unexpected problem getting inetAddress: %s",
              ex),
          ex);
    }
  }

  /**
   * Returns the value of the {@link ConfigurationProperties#MCAST_TTL} property
   */
  @ConfigAttributeGetter(name = MCAST_TTL)
  int getMcastTtl();

  /**
   * Sets the value of the {@link ConfigurationProperties#MCAST_TTL} property
   */
  @ConfigAttributeSetter(name = MCAST_TTL)
  void setMcastTtl(int value);

  /**
   * The default value of the {@link ConfigurationProperties#MCAST_TTL} property
   */
  int DEFAULT_MCAST_TTL = MembershipConfig.DEFAULT_MCAST_TTL;

  /**
   * The minimum {@link ConfigurationProperties#MCAST_TTL}.
   * <p>
   * Actual value of this constant is <code>0</code>.
   */
  int MIN_MCAST_TTL = 0;

  /**
   * The maximum {@link ConfigurationProperties#MCAST_TTL}.
   * <p>
   * Actual value of this constant is <code>255</code>.
   */
  int MAX_MCAST_TTL = 255;

  /**
   * The name of the {@link ConfigurationProperties#MCAST_TTL} property
   */
  @ConfigAttribute(type = Integer.class, min = MIN_MCAST_TTL, max = MAX_MCAST_TTL)
  String MCAST_TTL_NAME = MCAST_TTL;

  /**
   * Returns the value of the {@link ConfigurationProperties#BIND_ADDRESS} property
   */
  @ConfigAttributeGetter(name = BIND_ADDRESS)
  String getBindAddress();

  /**
   * Sets the value of the {@link ConfigurationProperties#BIND_ADDRESS} property
   */
  @ConfigAttributeSetter(name = BIND_ADDRESS)
  void setBindAddress(String value);

  /**
   * The name of the {@link ConfigurationProperties#BIND_ADDRESS} property
   */
  @ConfigAttribute(type = String.class)
  String BIND_ADDRESS_NAME = BIND_ADDRESS;

  /**
   * The default value of the {@link ConfigurationProperties#BIND_ADDRESS} property. Current value
   * is an empty string <code>""</code>
   */
  String DEFAULT_BIND_ADDRESS = MembershipConfig.DEFAULT_BIND_ADDRESS;

  /**
   * Returns the value of the {@link ConfigurationProperties#SERVER_BIND_ADDRESS} property
   */
  @ConfigAttributeGetter(name = SERVER_BIND_ADDRESS)
  String getServerBindAddress();

  /**
   * Sets the value of the {@link ConfigurationProperties#SERVER_BIND_ADDRESS} property
   */
  @ConfigAttributeSetter(name = SERVER_BIND_ADDRESS)
  void setServerBindAddress(String value);

  /**
   * The name of the {@link ConfigurationProperties#SERVER_BIND_ADDRESS} property
   */
  @ConfigAttribute(type = String.class)
  String SERVER_BIND_ADDRESS_NAME = SERVER_BIND_ADDRESS;

  /**
   * The default value of the {@link ConfigurationProperties#SERVER_BIND_ADDRESS} property. Current
   * value is an empty string <code>""</code>
   */
  String DEFAULT_SERVER_BIND_ADDRESS = "";

  /**
   * Returns the value of the {@link ConfigurationProperties#LOCATORS} property
   */
  @ConfigAttributeGetter(name = LOCATORS)
  String getLocators();

  /**
   * Sets the system's locator list. A locator list is optional and by default empty. Its used to by
   * the system to locator other system nodes and to publish itself so it can be located by others.
   *
   * @param value must be of the form <code>hostName[portNum]</code>. Multiple elements are allowed
   *        and must be separated by a comma.
   *
   * @throws IllegalArgumentException if the specified value is not acceptable.
   * @throws UnmodifiableException if this attribute can not be modified.
   * @throws GemFireIOException if the set failure is caused by an error when
   *         writing to the system's configuration file.
   */
  @ConfigAttributeSetter(name = LOCATORS)
  void setLocators(String value);

  /**
   * The name of the {@link ConfigurationProperties#LOCATORS} property
   */
  @ConfigAttribute(type = String.class)
  String LOCATORS_NAME = LOCATORS;

  /**
   * The default value of the {@link ConfigurationProperties#LOCATORS} property
   */
  String DEFAULT_LOCATORS = MembershipConfig.DEFAULT_LOCATORS;

  /**
   * Locator wait time - how long to wait for a locator to start before giving up & throwing a
   * GemFireConfigException
   */
  @ConfigAttribute(type = Integer.class)
  String LOCATOR_WAIT_TIME_NAME = LOCATOR_WAIT_TIME;

  int DEFAULT_LOCATOR_WAIT_TIME = MembershipConfig.DEFAULT_LOCATOR_WAIT_TIME;

  @ConfigAttributeGetter(name = LOCATOR_WAIT_TIME)
  int getLocatorWaitTime();

  @ConfigAttributeSetter(name = LOCATOR_WAIT_TIME)
  void setLocatorWaitTime(int seconds);

  /**
   * returns the value of the {@link ConfigurationProperties#START_LOCATOR} property
   */
  @ConfigAttributeGetter(name = START_LOCATOR)
  String getStartLocator();

  /**
   * Sets the {@link ConfigurationProperties#START_LOCATOR} property. This is a string in the form
   * bindAddress[port] and, if set, tells the distributed system to start a locator prior to
   * connecting
   *
   * @param value must be of the form <code>hostName[portNum]</code>
   */
  @ConfigAttributeSetter(name = START_LOCATOR)
  void setStartLocator(String value);

  /**
   * The name of the {@link ConfigurationProperties#START_LOCATOR} property
   */
  @ConfigAttribute(type = String.class)
  String START_LOCATOR_NAME = START_LOCATOR;
  /**
   * The default value of the {@link ConfigurationProperties#START_LOCATOR} property
   */
  String DEFAULT_START_LOCATOR = MembershipConfig.DEFAULT_START_LOCATOR;

  /**
   * Returns the value of the {@link ConfigurationProperties#DEPLOY_WORKING_DIR} property
   */
  @ConfigAttributeGetter(name = DEPLOY_WORKING_DIR)
  File getDeployWorkingDir();

  /**
   * Sets the system's deploy working directory.
   *
   * @throws IllegalArgumentException if the specified value is not acceptable.
   * @throws UnmodifiableException if this attribute can not be modified.
   * @throws GemFireIOException if the set failure is caused by an error when
   *         writing to the system's configuration file.
   */
  @ConfigAttributeSetter(name = DEPLOY_WORKING_DIR)
  void setDeployWorkingDir(File value);

  /**
   * The name of the {@link ConfigurationProperties#DEPLOY_WORKING_DIR} property.
   */
  @ConfigAttribute(type = File.class)
  String DEPLOY_WORKING_DIR_NAME = DEPLOY_WORKING_DIR;

  /**
   * Default will be the current working directory as determined by
   * <code>System.getProperty("user.dir")</code>.
   */
  File DEFAULT_DEPLOY_WORKING_DIR = new File(System.getProperty("user.dir"));

  /**
   * Returns the value of the {@link ConfigurationProperties#USER_COMMAND_PACKAGES} property
   */
  @ConfigAttributeGetter(name = USER_COMMAND_PACKAGES)
  String getUserCommandPackages();

  /**
   * Sets the system's user command path.
   *
   * @throws IllegalArgumentException if the specified value is not acceptable.
   * @throws UnmodifiableException if this attribute can not be modified.
   * @throws GemFireIOException if the set failure is caused by an error when
   *         writing to the system's configuration file.
   */
  @ConfigAttributeSetter(name = USER_COMMAND_PACKAGES)
  void setUserCommandPackages(String value);

  /**
   * The name of the {@link ConfigurationProperties#USER_COMMAND_PACKAGES} property.
   */
  @ConfigAttribute(type = String.class)
  String USER_COMMAND_PACKAGES_NAME = USER_COMMAND_PACKAGES;

  /**
   * The default value of the {@link ConfigurationProperties#USER_COMMAND_PACKAGES} property
   */
  String DEFAULT_USER_COMMAND_PACKAGES = "";

  /**
   * Returns the value of the {@link ConfigurationProperties#LOG_FILE} property
   *
   * @return <code>null</code> if logging information goes to standard out
   */
  @Override
  @ConfigAttributeGetter(name = LOG_FILE)
  File getLogFile();

  /**
   * Sets the system's log file.
   * <p>
   * Non-absolute log files are relative to the system directory.
   * <p>
   * The system log file can not be changed while the system is running.
   *
   * @throws IllegalArgumentException if the specified value is not acceptable.
   * @throws UnmodifiableException if this attribute can not be modified.
   * @throws GemFireIOException if the set failure is caused by an error when
   *         writing to the system's configuration file.
   */
  @ConfigAttributeSetter(name = LOG_FILE)
  void setLogFile(File value);

  /**
   * The name of the {@link ConfigurationProperties#LOG_FILE} property
   */
  @ConfigAttribute(type = File.class)
  String LOG_FILE_NAME = LOG_FILE;

  /**
   * The default {@link ConfigurationProperties#LOG_FILE}.
   * <p>
   * Actual value of this constant is <code>""</code> which directs log message to standard output.
   */
  File DEFAULT_LOG_FILE = new File("");

  /**
   * Returns the value of the {@link ConfigurationProperties#LOG_LEVEL} property
   *
   * @see LogWriterImpl
   */
  @Override
  @ConfigAttributeGetter(name = LOG_LEVEL)
  int getLogLevel();

  /**
   * Sets the value of the {@link ConfigurationProperties#LOG_LEVEL} property
   *
   * @see LogWriterImpl
   */
  @ConfigAttributeSetter(name = LOG_LEVEL)
  void setLogLevel(int value);

  /**
   * The default {@link ConfigurationProperties#LOG_LEVEL}.
   * <p>
   * Actual value of this constant is {@link LogWriterLevel#CONFIG#intLevel()}.
   */
  int DEFAULT_LOG_LEVEL = LogWriterLevel.CONFIG.intLevel();
  /**
   * The minimum {@link ConfigurationProperties#LOG_LEVEL}.
   * <p>
   * Actual value of this constant is {@link LogWriterLevel#ALL#intLevel()}.
   */
  int MIN_LOG_LEVEL = LogWriterLevel.ALL.intLevel();
  /**
   * The maximum {@link ConfigurationProperties#LOG_LEVEL}.
   * <p>
   * Actual value of this constant is {@link LogWriterLevel#NONE#intLevel()}.
   */
  int MAX_LOG_LEVEL = LogWriterLevel.NONE.intLevel();

  /**
   * The name of the {@link ConfigurationProperties#LOG_LEVEL} property
   */
  // type is String because the config file contains "config", "debug", "fine" etc, not a code, but
  // the setter/getter accepts int
  @ConfigAttribute(type = String.class)
  String LOG_LEVEL_NAME = LOG_LEVEL;

  /**
   * Returns the value of the {@link ConfigurationProperties#STATISTIC_SAMPLING_ENABLED} property
   */
  @Override
  @ConfigAttributeGetter(name = STATISTIC_SAMPLING_ENABLED)
  boolean getStatisticSamplingEnabled();

  /**
   * Sets {@link ConfigurationProperties#STATISTIC_SAMPLING_ENABLED}
   */
  @ConfigAttributeSetter(name = STATISTIC_SAMPLING_ENABLED)
  void setStatisticSamplingEnabled(boolean newValue);

  /**
   * The name of the {@link ConfigurationProperties#STATISTIC_SAMPLING_ENABLED} property
   */
  @ConfigAttribute(type = Boolean.class)
