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

import static org.apache.geode.distributed.ConfigurationProperties.BIND_ADDRESS;
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_PROTOCOLS;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_REQUIRE_AUTHENTICATION;
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.LOCATORS;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_ADDRESS;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
import static org.apache.geode.distributed.ConfigurationProperties.TCP_PORT;
import static org.apache.geode.internal.net.InetAddressUtils.toHostString;
import static org.apache.geode.internal.net.InetAddressUtilsWithLogging.validateHost;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;

import org.apache.logging.log4j.Logger;

import org.apache.geode.admin.AdminXmlException;
import org.apache.geode.admin.CacheServerConfig;
import org.apache.geode.admin.CacheVmConfig;
import org.apache.geode.admin.DistributedSystemConfig;
import org.apache.geode.admin.DistributionLocator;
import org.apache.geode.admin.DistributionLocatorConfig;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.DistributionConfigImpl;
import org.apache.geode.internal.logging.InternalLogWriter;
import org.apache.geode.internal.logging.LogWriterImpl;
import org.apache.geode.internal.statistics.StatisticsConfig;
import org.apache.geode.logging.internal.log4j.LogLevel;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.logging.internal.spi.LogConfig;

/**
 * An implementation of the configuration object for an <code>AdminDistributedSystem</code>. After a
 * config has been used to create an <code>AdminDistributedSystem</code> most of the configuration
 * attributes cannot be changed. However, some operations (such as getting information about GemFire
 * managers and distribution locators) are "passed through" to the
 * <code>AdminDistributedSystem</code> associated with this configuration object.
 *
 * @since GemFire 3.5
 */
public class DistributedSystemConfigImpl implements DistributedSystemConfig {

  private static final Logger logger = LogService.getLogger();

  private String entityConfigXMLFile = DEFAULT_ENTITY_CONFIG_XML_FILE;
  private String systemId = DEFAULT_SYSTEM_ID;
  private String mcastAddress = DEFAULT_MCAST_ADDRESS;
  private int mcastPort = DEFAULT_MCAST_PORT;
  private int ackWaitThreshold = DEFAULT_ACK_WAIT_THRESHOLD;
  private int ackSevereAlertThreshold = DEFAULT_ACK_SEVERE_ALERT_THRESHOLD;
  private String locators = DEFAULT_LOCATORS;
  private String bindAddress = DEFAULT_BIND_ADDRESS;
  private String serverBindAddress = DEFAULT_BIND_ADDRESS;
  private String remoteCommand = DEFAULT_REMOTE_COMMAND;
  private boolean disableTcp = DEFAULT_DISABLE_TCP;
  private boolean disableJmx = DEFAULT_DISABLE_JMX;
  private boolean enableNetworkPartitionDetection = DEFAULT_ENABLE_NETWORK_PARTITION_DETECTION;
  private boolean disableAutoReconnect = DEFAULT_DISABLE_AUTO_RECONNECT;
  private int memberTimeout = DEFAULT_MEMBER_TIMEOUT;
  private String membershipPortRange = getMembershipPortRangeString(DEFAULT_MEMBERSHIP_PORT_RANGE);
  private int tcpPort = DEFAULT_TCP_PORT;

  private String logFile = DEFAULT_LOG_FILE;
  private String logLevel = DEFAULT_LOG_LEVEL;
  private int logDiskSpaceLimit = DEFAULT_LOG_DISK_SPACE_LIMIT;
  private int logFileSizeLimit = DEFAULT_LOG_FILE_SIZE_LIMIT;
  private int refreshInterval = DEFAULT_REFRESH_INTERVAL;
  private Properties gfSecurityProperties = new Properties();

  /**
   * Listeners to notify when this DistributedSystemConfig changes
   */
  private Set listeners = new HashSet();

  /**
   * Configs for CacheServers that this system config is aware of
   */
  private Set cacheServerConfigs = new HashSet();

  /**
   * Configs for the managed distribution locators in the distributed system
   */
  private Set locatorConfigs = new HashSet();

  /**
   * The display name of this distributed system
   */
  private String systemName = DEFAULT_NAME;

  /**
   * The admin distributed system object that is configured by this config object.
   *
   * @since GemFire 4.0
   */
  private AdminDistributedSystemImpl system;

  /**
   * The GemFire log writer used by the distributed system
   */
  private InternalLogWriter logWriter;

  /////////////////////// Static Methods ///////////////////////

  /**
   * Filters out all properties that are unique to the admin <code>DistributedSystemConfig</code>
   * that are not present in the internal <code>DistributionConfig</code>.
   *
   * @since GemFire 4.0
   */
  private static Properties filterOutAdminProperties(Properties props) {

    Properties props2 = new Properties();
    for (Enumeration names = props.propertyNames(); names.hasMoreElements();) {
      String name = (String) names.nextElement();
      if (!(ENTITY_CONFIG_XML_FILE_NAME.equals(name) || REFRESH_INTERVAL_NAME.equals(name)
          || REMOTE_COMMAND_NAME.equals(name))) {
        String value = props.getProperty(name);
        if ((name != null) && (value != null)) {
          props2.setProperty(name, value);
        }
      }
    }

    return props2;
  }

  //////////////////////// Constructors ////////////////////////

  /**
   * Creates a new <code>DistributedSystemConfigImpl</code> based on the configuration stored in a
   * <code>DistributedSystem</code>'s <code>DistributionConfig</code>.
   */
  public DistributedSystemConfigImpl(DistributionConfig distConfig, String remoteCommand) {
    if (distConfig == null) {
      throw new IllegalArgumentException(
          "DistributionConfig must not be null.");
    }

    this.mcastAddress = toHostString(distConfig.getMcastAddress());
    this.mcastPort = distConfig.getMcastPort();
    this.locators = distConfig.getLocators();
    this.membershipPortRange = getMembershipPortRangeString(distConfig.getMembershipPortRange());

    this.systemName = distConfig.getName();

    this.sslEnabled = distConfig.getClusterSSLEnabled();
    this.sslCiphers = distConfig.getClusterSSLCiphers();
    this.sslProtocols = distConfig.getClusterSSLProtocols();
    this.sslAuthenticationRequired = distConfig.getClusterSSLRequireAuthentication();

    this.logFile = distConfig.getLogFile().getPath();
    this.logLevel = LogWriterImpl.levelToString(distConfig.getLogLevel());
    this.logDiskSpaceLimit = distConfig.getLogDiskSpaceLimit();
    this.logFileSizeLimit = distConfig.getLogFileSizeLimit();

    basicSetBindAddress(distConfig.getBindAddress());
    this.tcpPort = distConfig.getTcpPort();

    this.disableTcp = distConfig.getDisableTcp();

    this.remoteCommand = remoteCommand;
    this.serverBindAddress = distConfig.getServerBindAddress();
    this.enableNetworkPartitionDetection = distConfig.getEnableNetworkPartitionDetection();
    this.memberTimeout = distConfig.getMemberTimeout();
    this.refreshInterval = DistributedSystemConfig.DEFAULT_REFRESH_INTERVAL;
    this.gfSecurityProperties = (Properties) distConfig.getSSLProperties().clone();
  }

  /**
   * Zero-argument constructor to be used only by subclasses.
   *
   * @since GemFire 4.0
   */
  protected DistributedSystemConfigImpl() {

  }

  /**
   * Creates a new <code>DistributedSystemConifgImpl</code> whose configuration is specified by the
   * given <code>Properties</code> object.
   */
  protected DistributedSystemConfigImpl(Properties props) {
    this(props, false);
  }

  /**
   * Creates a new <code>DistributedSystemConifgImpl</code> whose configuration is specified by the
   * given <code>Properties</code> object.
   *
   * @param props The configuration properties specified by the caller
   * @param ignoreGemFirePropsFile whether to skip loading distributed system properties from
   *        gemfire.properties file
   *
   * @since GemFire 6.5
   */
  protected DistributedSystemConfigImpl(Properties props, boolean ignoreGemFirePropsFile) {
    this(new DistributionConfigImpl(filterOutAdminProperties(props), ignoreGemFirePropsFile),
        DEFAULT_REMOTE_COMMAND);
    String remoteCommand = props.getProperty(REMOTE_COMMAND_NAME);
    if (remoteCommand != null) {
      this.remoteCommand = remoteCommand;
    }

    String entityConfigXMLFile = props.getProperty(ENTITY_CONFIG_XML_FILE_NAME);
    if (entityConfigXMLFile != null) {
      this.entityConfigXMLFile = entityConfigXMLFile;
    }

    String refreshInterval = props.getProperty(REFRESH_INTERVAL_NAME);
    if (refreshInterval != null) {
      try {
        this.refreshInterval = Integer.parseInt(refreshInterval);
      } catch (NumberFormatException nfEx) {
        throw new IllegalArgumentException(
            String.format("%s is not a valid integer for %s",
                new Object[] {refreshInterval, REFRESH_INTERVAL_NAME}));
      }
    }
  }

  ////////////////////// Instance Methods //////////////////////

  /**
   * Returns the <code>LogWriterI18n</code> to be used when administering the distributed system.
   * Returns null if nothing has been provided via <code>setInternalLogWriter</code>.
   *
   * @since GemFire 4.0
   */
  public InternalLogWriter getInternalLogWriter() {
    // LOG: used only for sharing between IDS, AdminDSImpl and AgentImpl -- to prevent multiple
    // banners, etc.
    synchronized (this) {
      return this.logWriter;
    }
  }

  /**
   * Sets the <code>LogWriterI18n</code> to be used when administering the distributed system.
   */
  public void setInternalLogWriter(InternalLogWriter logWriter) {
    // LOG: used only for sharing between IDS, AdminDSImpl and AgentImpl -- to prevent multiple
    // banners, etc.
    synchronized (this) {
      this.logWriter = logWriter;
    }
  }

  public LogConfig createLogConfig() {
    return new LogConfig() {
      @Override
      public int getLogLevel() {
        return LogLevel.getLogWriterLevel(DistributedSystemConfigImpl.this.getLogLevel());
      }

      @Override
      public File getLogFile() {
        return new File(DistributedSystemConfigImpl.this.getLogFile());
      }

      @Override
      public File getSecurityLogFile() {
        return null;
      }

      @Override
      public int getSecurityLogLevel() {
        return LogLevel.getLogWriterLevel(DistributedSystemConfigImpl.this.getLogLevel());
      }

      @Override
      public int getLogFileSizeLimit() {
        return DistributedSystemConfigImpl.this.getLogFileSizeLimit();
      }

      @Override
      public int getLogDiskSpaceLimit() {
        return DistributedSystemConfigImpl.this.getLogDiskSpaceLimit();
      }

      @Override
      public String getName() {
        return DistributedSystemConfigImpl.this.getSystemName();
      }

      @Override
      public String toLoggerString() {
        return DistributedSystemConfigImpl.this.toString();
      }

      @Override
      public boolean isLoner() {
        return false;
      }
    };
  }

  public StatisticsConfig createStatisticsConfig() {
    return new StatisticsConfig() {

      @Override
      public File getStatisticArchiveFile() {
        return null;
      }

      @Override
      public int getArchiveFileSizeLimit() {
        return 0;
      }

      @Override
      public int getArchiveDiskSpaceLimit() {
        return 0;
      }

      @Override
      public int getStatisticSampleRate() {
        return 0;
      }

      @Override
      public boolean getStatisticSamplingEnabled() {
        return false;
      }
    };
  }

  /**
   * Marks this config object as "read only". Attempts to modify a config object will result in a
   * {@link IllegalStateException} being thrown.
   *
   * @since GemFire 4.0
   */
  void setDistributedSystem(AdminDistributedSystemImpl system) {
    this.system = system;
  }

  /**
   * Checks to see if this config object is "read only". If it is, then an
   * {@link IllegalStateException} is thrown.
   *
   * @since GemFire 4.0
   */
  protected void checkReadOnly() {
    if (this.system != null) {
      throw new IllegalStateException(
          "A DistributedSystemConfig object cannot be modified after it has been used to create an AdminDistributedSystem.");
    }
  }

  @Override
  public String getEntityConfigXMLFile() {
    return this.entityConfigXMLFile;
  }

  @Override
  public void setEntityConfigXMLFile(String xmlFile) {
    checkReadOnly();
    this.entityConfigXMLFile = xmlFile;
    configChanged();
  }

  /**
   * Parses the XML configuration file that describes managed entities.
   *
   * @throws AdminXmlException If a problem is encountered while parsing the XML file.
   */
  private void parseEntityConfigXMLFile() {
    String fileName = this.entityConfigXMLFile;
    File xmlFile = new File(fileName);
    if (!xmlFile.exists()) {
      if (DEFAULT_ENTITY_CONFIG_XML_FILE.equals(fileName)) {
        // Default doesn't exist, no big deal
        return;
      } else {
        throw new AdminXmlException(
            String.format("Entity configuration XML file %s does not exist",
                fileName));
      }
    }

    try {
      InputStream is = new FileInputStream(xmlFile);
      try {
        ManagedEntityConfigXmlParser.parse(is, this);
      } finally {
        is.close();
      }
    } catch (IOException ex) {
      throw new AdminXmlException(
          String.format("While parsing %s", fileName),
          ex);
    }
  }

  @Override
  public String getSystemId() {
    return this.systemId;
  }

  @Override
  public void setSystemId(String systemId) {
    checkReadOnly();
    this.systemId = systemId;
    configChanged();
  }

  /**
   * Returns the multicast address for the system
   */
  @Override
  public String getMcastAddress() {
    return this.mcastAddress;
  }

  @Override
  public void setMcastAddress(String mcastAddress) {
    checkReadOnly();
    this.mcastAddress = mcastAddress;
    configChanged();
  }

  /**
   * Returns the multicast port for the system
   */
  @Override
  public int getMcastPort() {
    return this.mcastPort;
  }

  @Override
  public void setMcastPort(int mcastPort) {
    checkReadOnly();
    this.mcastPort = mcastPort;
    configChanged();
  }

  @Override
  public int getAckWaitThreshold() {
    return this.ackWaitThreshold;
  }

  @Override
  public void setAckWaitThreshold(int seconds) {
    checkReadOnly();
    this.ackWaitThreshold = seconds;
    configChanged();
  }

  @Override
  public int getAckSevereAlertThreshold() {
    return this.ackSevereAlertThreshold;
  }

  @Override
  public void setAckSevereAlertThreshold(int seconds) {
    checkReadOnly();
    this.ackSevereAlertThreshold = seconds;
    configChanged();
  }

  /**
   * Returns the comma-delimited list of locators for the system
   */
  @Override
  public String getLocators() {
    return this.locators;
  }

  @Override
  public void setLocators(String locators) {
    checkReadOnly();
    if (locators == null) {
      this.locators = "";
    } else {
      this.locators = locators;
    }
    configChanged();
  }

  /**
   * Returns the value for membership-port-range
   *
   * @return the value for the Distributed System property membership-port-range
   */
  @Override
  public String getMembershipPortRange() {
    return this.membershipPortRange;
  }

  /**
   * Sets the Distributed System property membership-port-range
   *
   * @param membershipPortRangeStr the value for membership-port-range given as two numbers
   *        separated by a minus sign.
   */
  @Override
  public void setMembershipPortRange(String membershipPortRangeStr) {
    /*
     * FIXME: Setting attributes in DistributedSystemConfig has no effect on DistributionConfig
     * which is actually used for connection with DS. This is true for all such attributes. Should
     * be addressed in the Admin Revamp if we want these 'set' calls to affect anything. Then we can
     * use the validation code in DistributionConfigImpl code.
     */
    checkReadOnly();
    if (membershipPortRangeStr == null) {
      this.membershipPortRange = getMembershipPortRangeString(DEFAULT_MEMBERSHIP_PORT_RANGE);
    } else {
      try {
        if (validateMembershipRange(membershipPortRangeStr)) {
          this.membershipPortRange = membershipPortRangeStr;
        } else {
          throw new IllegalArgumentException(
              String.format(
                  "The value specified %s is invalid for the property : %s. This range should be specified as min-max.",

                  new Object[] {membershipPortRangeStr, MEMBERSHIP_PORT_RANGE_NAME}));
        }
      } catch (Exception e) {
        if (logger.isDebugEnabled()) {
          logger.debug(e.getMessage(), e);
        }
      }
    }
  }

  @Override
  public void setTcpPort(int port) {
    checkReadOnly();
    this.tcpPort = port;
    configChanged();
  }

  @Override
  public int getTcpPort() {
    return this.tcpPort;
  }

  /**
   * Validates the given string - which is expected in the format as two numbers separated by a
   * minus sign - in to an integer array of length 2 with first element as lower end & second
   * element as upper end of the range.
   *
   * @param membershipPortRange membership-port-range given as two numbers separated by a minus
   *        sign.
   * @return true if the membership-port-range string is valid, false otherwise
   */
  private boolean validateMembershipRange(String membershipPortRange) {
    int[] range = null;
    if (membershipPortRange != null && membershipPortRange.trim().length() > 0) {
      String[] splitted = membershipPortRange.split("-");
      range = new int[2];
      range[0] = Integer.parseInt(splitted[0].trim());
      range[1] = Integer.parseInt(splitted[1].trim());
      // NumberFormatException if any could be thrown

      if (range[0] < 0 || range[0] >= range[1] || range[1] < 0 || range[1] > 65535) {
        range = null;
      }
    }
    return range != null;
  }

  /**
   * @return the String representation of membershipPortRange with lower & upper limits of the port
   *         range separated by '-' e.g. 1-65535
   */
  private static String getMembershipPortRangeString(int[] membershipPortRange) {
    String membershipPortRangeString = "";
    if (membershipPortRange != null && membershipPortRange.length == 2) {
      membershipPortRangeString = membershipPortRange[0] + "-" + membershipPortRange[1];
    }

    return membershipPortRangeString;
  }

  @Override
  public String getBindAddress() {
    return this.bindAddress;
  }

  @Override
  public void setBindAddress(String bindAddress) {
    checkReadOnly();
    basicSetBindAddress(bindAddress);
    configChanged();
  }

  @Override
  public String getServerBindAddress() {
    return this.serverBindAddress;
  }

  @Override
  public void setServerBindAddress(String bindAddress) {
    checkReadOnly();
    basicSetServerBindAddress(bindAddress);
    configChanged();
  }

  @Override
  public boolean getDisableTcp() {
    return this.disableTcp;
  }

  @Override
  public void setDisableTcp(boolean flag) {
    checkReadOnly();
    disableTcp = flag;
    configChanged();
  }

  @Override
  public boolean getDisableJmx() {
    return disableJmx;
  }

  @Override
  public void setDisableJmx(boolean flag) {
    checkReadOnly();
    disableJmx = flag;
    configChanged();
  }

  @Override
  public void setEnableNetworkPartitionDetection(boolean newValue) {
    checkReadOnly();
    this.enableNetworkPartitionDetection = newValue;
    configChanged();
  }

  @Override
  public boolean getEnableNetworkPartitionDetection() {
    return this.enableNetworkPartitionDetection;
  }

  @Override
  public void setDisableAutoReconnect(boolean newValue) {
    checkReadOnly();
    this.disableAutoReconnect = newValue;
    configChanged();
  }

  @Override
  public boolean getDisableAutoReconnect() {
    return this.disableAutoReconnect;
  }

  @Override
  public int getMemberTimeout() {
    return this.memberTimeout;
  }

  @Override
  public void setMemberTimeout(int value) {
    checkReadOnly();
    this.memberTimeout = value;
    configChanged();
  }

  private void basicSetBindAddress(String bindAddress) {
    if (!validateBindAddress(bindAddress)) {
      throw new IllegalArgumentException(
          String.format("Invalid bind address: %s",
              bindAddress));
    }
    this.bindAddress = bindAddress;
  }

  private void basicSetServerBindAddress(String bindAddress) {
    if (!validateBindAddress(bindAddress)) {
      throw new IllegalArgumentException(
          String.format("Invalid bind address: %s",
              bindAddress));
    }
    this.serverBindAddress = bindAddress;
  }

  /**
   * Returns the remote command setting to use for remote administration
   */
  @Override
  public String getRemoteCommand() {
    return this.remoteCommand;
  }

  /**
   * Sets the remote command for this config object. This attribute may be modified after this
   * config object has been used to create an admin distributed system.
   */
  @Override
  public void setRemoteCommand(String remoteCommand) {
    if (!ALLOW_ALL_REMOTE_COMMANDS) {
      checkRemoteCommand(remoteCommand);
    }
    this.remoteCommand = remoteCommand;
    configChanged();
  }

  private static final boolean ALLOW_ALL_REMOTE_COMMANDS =
      Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "admin.ALLOW_ALL_REMOTE_COMMANDS");
  private static final String[] LEGAL_REMOTE_COMMANDS = {"rsh", "ssh"};
  private static final String ILLEGAL_REMOTE_COMMAND_RSH_OR_SSH =
      "Allowed remote commands include \"rsh {HOST} {CMD}\" or \"ssh {HOST} {CMD}\" with valid rsh or ssh switches. Invalid: ";

  private void checkRemoteCommand(final String remoteCommand) {
    if (remoteCommand == null || remoteCommand.isEmpty()) {
      return;
    }
    final String command = remoteCommand.toLowerCase().trim();
    if (!command.contains("{host}") || !command.contains("{cmd}")) {
      throw new IllegalArgumentException(ILLEGAL_REMOTE_COMMAND_RSH_OR_SSH + remoteCommand);
    }

    final StringTokenizer tokenizer = new StringTokenizer(command, " ");
    final ArrayList<String> array = new ArrayList<String>();
    for (int i = 0; tokenizer.hasMoreTokens(); i++) {
      String string = tokenizer.nextToken();
      if (i == 0) {
        // first element must be rsh or ssh
        boolean found = false;
        for (int j = 0; j < LEGAL_REMOTE_COMMANDS.length; j++) {
          if (string.contains(LEGAL_REMOTE_COMMANDS[j])) {
            // verify command is at end of string
            if (!(string.endsWith(LEGAL_REMOTE_COMMANDS[j])
                || string.endsWith(LEGAL_REMOTE_COMMANDS[j] + ".exe"))) {
              throw new IllegalArgumentException(ILLEGAL_REMOTE_COMMAND_RSH_OR_SSH + remoteCommand);
            }
            found = true;
          }
        }
        if (!found) {
          throw new IllegalArgumentException(ILLEGAL_REMOTE_COMMAND_RSH_OR_SSH + remoteCommand);
        }
      } else {
        final boolean isSwitch = string.startsWith("-");
        final boolean isHostOrCmd = string.equals("{host}") || string.equals("{cmd}");

        // additional elements must be switches or values-for-switches or {host} or user@{host} or
        // {cmd}
        if (!isSwitch && !isHostOrCmd) {
          final String previous =
              array.isEmpty() ? null : array.get(array.size() - 1);
          final boolean isValueForSwitch = previous != null && previous.startsWith("-");
          final boolean isHostWithUser = string.contains("@") && string.endsWith("{host}");

          if (!(isValueForSwitch || isHostWithUser)) {
            throw new IllegalArgumentException(ILLEGAL_REMOTE_COMMAND_RSH_OR_SSH + remoteCommand);
          }
        }
      }
      array.add(string);
    }
  }

  @Override
  public String getSystemName() {
    return this.systemName;
  }

  @Override
  public void setSystemName(final String systemName) {
    checkReadOnly();
    this.systemName = systemName;
    configChanged();
  }

  /**
   * Returns an array of configurations for statically known CacheServers
   *
   * @since GemFire 4.0
   */
  @Override
  public CacheServerConfig[] getCacheServerConfigs() {
    return (CacheServerConfig[]) this.cacheServerConfigs
        .toArray(new CacheServerConfig[0]);
  }

  @Override
  public CacheVmConfig[] getCacheVmConfigs() {
    return (CacheVmConfig[]) this.cacheServerConfigs
        .toArray(new CacheVmConfig[0]);
  }

  /**
   * Creates the configuration for a CacheServer
   *
   * @since GemFire 4.0
   */
  @Override
  public CacheServerConfig createCacheServerConfig() {
    CacheServerConfig config = new CacheServerConfigImpl();
    addCacheServerConfig(config);
    return config;
  }

  @Override
  public CacheVmConfig createCacheVmConfig() {
    return (CacheVmConfig) createCacheServerConfig();
  }

  /**
   * Adds the configuration for a CacheServer
   *
   * @since GemFire 4.0
   */
  private void addCacheServerConfig(CacheServerConfig managerConfig) {
    checkReadOnly();

    if (managerConfig == null)
      return;
    for (Iterator iter = this.cacheServerConfigs.iterator(); iter.hasNext();) {
      CacheServerConfigImpl impl = (CacheServerConfigImpl) iter.next();
      if (impl.equals(managerConfig)) {
        return;
      }
    }
    this.cacheServerConfigs.add(managerConfig);
    configChanged();
  }

  /**
   * Removes the configuration for a CacheServer
   *
   * @since GemFire 4.0
   */
  @Override
  public void removeCacheServerConfig(CacheServerConfig managerConfig) {
    removeCacheVmConfig((CacheVmConfig) managerConfig);
  }

  @Override
  public void removeCacheVmConfig(CacheVmConfig managerConfig) {
    checkReadOnly();
    this.cacheServerConfigs.remove(managerConfig);
    configChanged();
  }

  /**
   * Returns the configurations of all managed distribution locators
   */
  @Override
  public DistributionLocatorConfig[] getDistributionLocatorConfigs() {
    if (this.system != null) {
      DistributionLocator[] locators = this.system.getDistributionLocators();
      DistributionLocatorConfig[] configs = new DistributionLocatorConfig[locators.length];
      for (int i = 0; i < locators.length; i++) {
        configs[i] = locators[i].getConfig();
      }
      return configs;

    } else {
      Object[] array = new DistributionLocatorConfig[this.locatorConfigs.size()];
      return (DistributionLocatorConfig[]) this.locatorConfigs.toArray(array);
    }
  }

  /**
   * Creates the configuration for a DistributionLocator
   */
  @Override
  public DistributionLocatorConfig createDistributionLocatorConfig() {
    checkReadOnly();
    DistributionLocatorConfig config = new DistributionLocatorConfigImpl();
    addDistributionLocatorConfig(config);
    return config;
  }

  /**
   * Adds the configuration for a DistributionLocator
   */
  private void addDistributionLocatorConfig(DistributionLocatorConfig config) {
    checkReadOnly();
    this.locatorConfigs.add(config);
    configChanged();
  }

  /**
   * Removes the configuration for a DistributionLocator
   */
  @Override
  public void removeDistributionLocatorConfig(DistributionLocatorConfig config) {
    checkReadOnly();
    this.locatorConfigs.remove(config);
    configChanged();
  }

  /**
   * Validates the bind address. The address may be a host name or IP address, but it must not be
   * empty and must be usable for creating an InetAddress. Cannot have a leading '/' (which
   * InetAddress.toString() produces).
   *
   * @param bindAddress host name or IP address to validate
   */
  public static boolean validateBindAddress(String bindAddress) {
    if (bindAddress == null || bindAddress.length() == 0) {
      return true;
    }
    if (validateHost(bindAddress) == null) {
      return false;
    }
    return true;
  }

  public synchronized void configChanged() {
    ConfigListener[] clients = null;
    synchronized (this.listeners) {
      clients = (ConfigListener[]) listeners.toArray(new ConfigListener[this.listeners.size()]);
    }
    for (int i = 0; i < clients.length; i++) {
      try {
        clients[i].configChanged(this);
      } catch (Exception e) {
        logger.warn(e.getMessage(), e);
      }
    }
  }

  /**
   * Registers listener for notification of changes in this config.
   */
  @Override
  public void addListener(ConfigListener listener) {
    synchronized (this.listeners) {
      this.listeners.add(listener);
    }
  }

  /**
   * Removes previously registered listener of this config.
   */
  @Override
  public void removeListener(ConfigListener listener) {
    synchronized (this.listeners) {
      this.listeners.remove(listener);
    }
  }

  // -------------------------------------------------------------------------
  // SSL support...
  // -------------------------------------------------------------------------
  private boolean sslEnabled = DistributionConfig.DEFAULT_SSL_ENABLED;
  private String sslProtocols = DistributionConfig.DEFAULT_SSL_PROTOCOLS;
  private String sslCiphers = DistributionConfig.DEFAULT_SSL_CIPHERS;
  private boolean sslAuthenticationRequired = DistributionConfig.DEFAULT_SSL_REQUIRE_AUTHENTICATION;
  private Properties sslProperties = new Properties();

  @Override
  public boolean isSSLEnabled() {
    return this.sslEnabled;
  }

  @Override
  public void setSSLEnabled(boolean enabled) {
    checkReadOnly();
    this.sslEnabled = enabled;
    configChanged();
  }

  @Override
  public String getSSLProtocols() {
    return this.sslProtocols;
  }

  @Override
  public void setSSLProtocols(String protocols) {
    checkReadOnly();
    this.sslProtocols = protocols;
    configChanged();
  }

  @Override
  public String getSSLCiphers() {
    return this.sslCiphers;
  }

  @Override
  public void setSSLCiphers(String ciphers) {
    checkReadOnly();
    this.sslCiphers = ciphers;
    configChanged();
  }

  @Override
  public boolean isSSLAuthenticationRequired() {
    return this.sslAuthenticationRequired;
  }

  @Override
  public void setSSLAuthenticationRequired(boolean authRequired) {
    checkReadOnly();
    this.sslAuthenticationRequired = authRequired;
    configChanged();
  }

  @Override
  public Properties getSSLProperties() {
    return this.sslProperties;
  }

  @Override
  public void setSSLProperties(Properties sslProperties) {
    checkReadOnly();
    this.sslProperties = sslProperties;
    if (this.sslProperties == null) {
      this.sslProperties = new Properties();
    }
    configChanged();
  }

  @Override
  public void addSSLProperty(String key, String value) {
    checkReadOnly();
    this.sslProperties.put(key, value);
    configChanged();
  }

  @Override
  public void removeSSLProperty(String key) {
    checkReadOnly();
    this.sslProperties.remove(key);
    configChanged();
  }

  /**
   * @return the gfSecurityProperties
   * @since GemFire 6.6.3
   */
  public Properties getGfSecurityProperties() {
    return gfSecurityProperties;
  }

  @Override
  public String getLogFile() {
    return this.logFile;
  }

  @Override
  public void setLogFile(String logFile) {
    checkReadOnly();
    this.logFile = logFile;
    configChanged();
  }

  @Override
  public String getLogLevel() {
    return this.logLevel;
  }

  @Override
  public void setLogLevel(String logLevel) {
    checkReadOnly();
    this.logLevel = logLevel;
    configChanged();
  }

  @Override
  public int getLogDiskSpaceLimit() {
    return this.logDiskSpaceLimit;
  }

  @Override
  public void setLogDiskSpaceLimit(int limit) {
    checkReadOnly();
    this.logDiskSpaceLimit = limit;
    configChanged();
  }

  @Override
  public int getLogFileSizeLimit() {
    return this.logFileSizeLimit;
  }

  @Override
  public void setLogFileSizeLimit(int limit) {
    checkReadOnly();
    this.logFileSizeLimit = limit;
    configChanged();
  }

  /**
   * Returns the refreshInterval in seconds
   */
  @Override
  public int getRefreshInterval() {
    return this.refreshInterval;
  }

  /**
   * Sets the refreshInterval in seconds
   */
  @Override
  public void setRefreshInterval(int timeInSecs) {
    checkReadOnly();
    this.refreshInterval = timeInSecs;
    configChanged();
  }

  /**
   * Makes sure that the mcast port and locators are correct and consistent.
   *
   * @throws IllegalArgumentException If configuration is not valid
   */
  @Override
  public void validate() {
    if (this.getMcastPort() < MIN_MCAST_PORT || this.getMcastPort() > MAX_MCAST_PORT) {
      throw new IllegalArgumentException(
          String.format("mcastPort must be an integer inclusively between %s and %s",

              new Object[] {Integer.valueOf(MIN_MCAST_PORT), Integer.valueOf(MAX_MCAST_PORT)}));
    }

    LogLevel.getLogWriterLevel(this.logLevel);

    if (this.logFileSizeLimit < MIN_LOG_FILE_SIZE_LIMIT
        || this.logFileSizeLimit > MAX_LOG_FILE_SIZE_LIMIT) {
      throw new IllegalArgumentException(
          String.format("LogFileSizeLimit must be an integer between %s and %s",
              new Object[] {Integer.valueOf(MIN_LOG_FILE_SIZE_LIMIT),
                  Integer.valueOf(MAX_LOG_FILE_SIZE_LIMIT)}));
    }

    if (this.logDiskSpaceLimit < MIN_LOG_DISK_SPACE_LIMIT
        || this.logDiskSpaceLimit > MAX_LOG_DISK_SPACE_LIMIT) {
      throw new IllegalArgumentException(
          String.format("LogDiskSpaceLimit must be an integer between %s and %s",
              new Object[] {Integer.valueOf(MIN_LOG_DISK_SPACE_LIMIT),
                  Integer.valueOf(MAX_LOG_DISK_SPACE_LIMIT)}));
    }

    parseEntityConfigXMLFile();
  }

  /**
   * Makes a deep copy of this config object.
   */
  @Override
  public Object clone() throws CloneNotSupportedException {
    DistributedSystemConfigImpl other = (DistributedSystemConfigImpl) super.clone();
    other.system = null;
    other.cacheServerConfigs = new HashSet();
    other.locatorConfigs = new HashSet();

    DistributionLocatorConfig[] myLocators = this.getDistributionLocatorConfigs();
    for (int i = 0; i < myLocators.length; i++) {
      DistributionLocatorConfig locator = myLocators[i];
      other.addDistributionLocatorConfig((DistributionLocatorConfig) locator.clone());
    }

    CacheServerConfig[] myCacheServers = this.getCacheServerConfigs();
    for (int i = 0; i < myCacheServers.length; i++) {
      CacheServerConfig locator = myCacheServers[i];
      other.addCacheServerConfig((CacheServerConfig) locator.clone());
    }

    return other;
  }

  @Override
  public String toString() {
    StringBuffer buf = new StringBuffer(1000);
    String lf = System.getProperty("line.separator");
    if (lf == null)
      lf = ",";

    buf.append("DistributedSystemConfig(");
    buf.append(lf);
    buf.append("  system-name=");
    buf.append(String.valueOf(this.systemName));
    buf.append(lf);
    buf.append("  " + MCAST_ADDRESS + "=");
    buf.append(String.valueOf(this.mcastAddress));
    buf.append(lf);
    buf.append("  " + MCAST_PORT + "=");
    buf.append(String.valueOf(this.mcastPort));
    buf.append(lf);
    buf.append("  " + LOCATORS + "=");
    buf.append(String.valueOf(this.locators));
    buf.append(lf);
    buf.append("  " + MEMBERSHIP_PORT_RANGE_NAME + "=");
    buf.append(getMembershipPortRange());
    buf.append(lf);
    buf.append("  " + BIND_ADDRESS + "=");
    buf.append(String.valueOf(this.bindAddress));
    buf.append(lf);
    buf.append("  " + TCP_PORT + "=" + this.tcpPort);
    buf.append(lf);
    buf.append("  " + DISABLE_TCP + "=");
    buf.append(String.valueOf(this.disableTcp));
    buf.append(lf);
    buf.append("  " + DISABLE_JMX + "=");
    buf.append(disableJmx);
    buf.append(lf);
    buf.append("  " + DISABLE_AUTO_RECONNECT + "=");
    buf.append(String.valueOf(this.disableAutoReconnect));
    buf.append(lf);
    buf.append("  " + REMOTE_COMMAND_NAME + "=");
    buf.append(String.valueOf(this.remoteCommand));
    buf.append(lf);
    buf.append("  " + CLUSTER_SSL_ENABLED + "=");
    buf.append(String.valueOf(this.sslEnabled));
    buf.append(lf);
    buf.append("  " + CLUSTER_SSL_CIPHERS + "=");
    buf.append(String.valueOf(this.sslCiphers));
    buf.append(lf);
    buf.append("  " + CLUSTER_SSL_PROTOCOLS + "=");
    buf.append(String.valueOf(this.sslProtocols));
    buf.append(lf);
    buf.append("  " + CLUSTER_SSL_REQUIRE_AUTHENTICATION + "=");
    buf.append(String.valueOf(this.sslAuthenticationRequired));
    buf.append(lf);
    buf.append("  " + LOG_FILE_NAME + "=");
    buf.append(String.valueOf(this.logFile));
    buf.append(lf);
    buf.append("  " + LOG_LEVEL_NAME + "=");
    buf.append(String.valueOf(this.logLevel));
    buf.append(lf);
    buf.append("  " + LOG_DISK_SPACE_LIMIT_NAME + "=");
    buf.append(String.valueOf(this.logDiskSpaceLimit));
    buf.append(lf);
    buf.append("  " + LOG_FILE_SIZE_LIMIT_NAME + "=");
    buf.append(String.valueOf(this.logFileSizeLimit));
    buf.append(lf);
    buf.append("  " + REFRESH_INTERVAL_NAME + "=");
    buf.append(String.valueOf(this.refreshInterval));
    buf.append(")");
    return buf.toString();
  }
}
