/*
 * 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;

import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.lowerCase;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_FILE;
import static org.apache.geode.distributed.ConfigurationProperties.NAME;
import static org.apache.geode.internal.lang.StringUtils.wrap;
import static org.apache.geode.internal.lang.SystemUtils.CURRENT_DIRECTORY;
import static org.apache.geode.internal.util.IOUtils.tryGetCanonicalPathElseGetAbsolutePath;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import joptsimple.OptionException;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.logging.log4j.Logger;

import org.apache.geode.annotations.Immutable;
import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.client.internal.locator.LocatorStatusRequest;
import org.apache.geode.cache.client.internal.locator.LocatorStatusResponse;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.DistributionConfigImpl;
import org.apache.geode.distributed.internal.InternalLocator;
import org.apache.geode.distributed.internal.tcpserver.TcpClient;
import org.apache.geode.internal.DistributionLocator;
import org.apache.geode.internal.GemFireVersion;
import org.apache.geode.internal.lang.ObjectUtils;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.net.SocketCreator;
import org.apache.geode.internal.process.ConnectionFailedException;
import org.apache.geode.internal.process.ControlNotificationHandler;
import org.apache.geode.internal.process.ControllableProcess;
import org.apache.geode.internal.process.FileAlreadyExistsException;
import org.apache.geode.internal.process.MBeanInvocationFailedException;
import org.apache.geode.internal.process.PidUnavailableException;
import org.apache.geode.internal.process.ProcessController;
import org.apache.geode.internal.process.ProcessControllerFactory;
import org.apache.geode.internal.process.ProcessControllerParameters;
import org.apache.geode.internal.process.ProcessLauncherContext;
import org.apache.geode.internal.process.ProcessType;
import org.apache.geode.internal.process.ProcessUtils;
import org.apache.geode.internal.process.UnableToControlProcessException;
import org.apache.geode.lang.AttachAPINotFoundException;
import org.apache.geode.management.internal.cli.util.HostUtils;
import org.apache.geode.management.internal.cli.util.JsonUtil;

/**
 * The LocatorLauncher class is a launcher for a GemFire Locator.
 *
 * @see org.apache.geode.distributed.AbstractLauncher
 * @see org.apache.geode.distributed.ServerLauncher
 * @since GemFire 7.0
 */
@SuppressWarnings({"unused"})
public class LocatorLauncher extends AbstractLauncher<String> {

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

  @Immutable
  private static final Boolean DEFAULT_LOAD_SHARED_CONFIG_FROM_DIR = Boolean.FALSE;

  @Immutable
  private static final Map<String, String> helpMap;

  static {
    final Map<String, String> help = new HashMap<>();
    help.put("launcher",
        "A GemFire launcher used to start, stop and determine a Locator's status.");
    help.put(Command.START.getName(), String.format(
        "Starts a Locator running in the current working directory listening on the default port (%s) bound to all IP addresses available to the localhost.  The Locator must be given a member name in the GemFire cluster.  The default bind-address and port may be overridden using the corresponding command-line options.",
        String.valueOf(getDefaultLocatorPort())));
    help.put(Command.STATUS.getName(),
        "Displays the status of a Locator given any combination of the bind-address[port], member name/ID, PID, or the directory in which the Locator is running.");
    help.put(Command.STOP.getName(),
        "Stops a running Locator given a member name/ID, PID, or the directory in which the Locator is running.");
    help.put(Command.VERSION.getName(),
        "Displays GemFire product version information.");
    help.put("bind-address",
        "Specifies the IP address on which to bind, or on which the Locator is bound, listening for client requests.  Defaults to all IP addresses available to the localhost.");
    help.put("debug", "Displays verbose information during the invocation of the launcher.");
    help.put("delete-pid-file-on-stop",
        "Specifies that this Locator's PID file should be deleted on stop.  The default is to not delete this Locator's PID file until JVM exit if --delete-pid-file-on-stop is not specified.");
    help.put("dir",
        "Specifies the working directory where the Locator is running.  Defaults to the current working directory.");
    help.put("force",
        "Enables any existing Locator PID file to be overwritten on start.  The default is to throw an error if a PID file already exists and --force is not specified.");
    help.put("help",
        "Causes GemFire to print out information instead of performing the command. This option is supported by all commands.");
    help.put("hostname-for-clients",
        "An option to specify the hostname or IP address to send to clients so they can connect to this Locator. The default is to use the IP address to which the Locator is bound.");
    help.put("member", "Identifies the Locator by member name or ID in the GemFire cluster.");
    help.put("pid", "Indicates the OS process ID of the running Locator.");
    help.put("port", String.format(
        "Specifies the port on which the Locator is listening for client requests. Defaults to %s.",
        String.valueOf(getDefaultLocatorPort())));
    help.put("redirect-output",
        "An option to cause the Locator to redirect standard out and standard error to the GemFire log file.");

    helpMap = Collections.unmodifiableMap(help);
  }

  @Immutable
  private static final Map<Command, String> usageMap;

  static {
    Map<Command, String> usage = new TreeMap<>();
    usage.put(Command.START,
        "start <member-name> [--bind-address=<IP-address>] [--hostname-for-clients=<IP-address>] [--port=<port>] [--dir=<Locator-working-directory>] [--force] [--debug] [--help]");
    usage.put(Command.STATUS,
        "status [--bind-address=<IP-address>] [--port=<port>] [--member=<member-ID/Name>] [--pid=<process-ID>] [--dir=<Locator-working-directory>] [--debug] [--help]");
    usage.put(Command.STOP,
        "stop [--member=<member-ID/Name>] [--pid=<process-ID>] [--dir=<Locator-working-directory>] [--debug] [--help]");
    usage.put(Command.VERSION, "version");
    usageMap = usage;
  }

  private static final String DEFAULT_LOCATOR_LOG_EXT = ".log";
  private static final String DEFAULT_LOCATOR_LOG_NAME = "locator";
  private static final String LOCATOR_SERVICE_NAME = "Locator";

  @MakeNotStatic
  private static final AtomicReference<LocatorLauncher> INSTANCE = new AtomicReference<>();

  // private transient volatile boolean debug;

  private final transient ControlNotificationHandler controlHandler;

  private final AtomicBoolean starting = new AtomicBoolean(false);

  private final boolean deletePidFileOnStop;
  private final boolean force;
  private final boolean help;
  private final boolean redirectOutput;

  private final Command command;

  private final boolean bindAddressSpecified;
  private final boolean portSpecified;
  private final boolean workingDirectorySpecified;

  private final InetAddress bindAddress;

  private final Integer pid;
  private final Integer port;

  private transient volatile InternalLocator locator;

  private final Properties distributedSystemProperties;

  private final String hostnameForClients;
  private final String memberName;
  private final String workingDirectory;

  // NOTE in addition to debug and locator, the other shared, mutable state
  private transient volatile String statusMessage;

  private transient volatile ControllableProcess process;

  private final transient LocatorControllerParameters controllerParameters;

  /**
   * Launches a GemFire Locator from the command-line configured with the given arguments.
   *
   * @param args the command-line arguments used to configure the GemFire Locator at runtime.
   */
  public static void main(final String... args) {
    try {
      new Builder(args).build().run();
    } catch (AttachAPINotFoundException handled) {
      System.err.println(handled.getMessage());
    }
  }

  private static Integer getDefaultLocatorPort() {
    return Integer.getInteger(DistributionLocator.TEST_OVERRIDE_DEFAULT_PORT_PROPERTY,
        DistributionLocator.DEFAULT_LOCATOR_PORT);
  }

  /**
   * Gets the instance of the LocatorLauncher used to launch the GemFire Locator, or null if this VM
   * does not have an instance of LocatorLauncher indicating no GemFire Locator is running.
   *
   * @return the instance of LocatorLauncher used to launcher a GemFire Locator in this VM.
   */
  public static LocatorLauncher getInstance() {
    return INSTANCE.get();
  }

  /**
   * Gets the LocatorState for this process or null if this process was not launched using this VM's
   * LocatorLauncher reference.
   *
   * @return the LocatorState for this process or null.
   */
  public static LocatorState getLocatorState() {
    return (getInstance() != null ? getInstance().status() : null);
  }

  /**
   * Private constructor used to properly construct an immutable instance of the LocatorLauncher
   * using a Builder. The Builder is used to configure a LocatorLauncher instance. The Builder can
   * process user input from the command-line or be used to properly construct an instance of the
   * LocatorLauncher programmatically using the API.
   *
   * @param builder an instance of LocatorLauncher.Builder for configuring and constructing an
   *        instance of the LocatorLauncher.
   * @see org.apache.geode.distributed.LocatorLauncher.Builder
   */
  private LocatorLauncher(final Builder builder) {
    this.command = builder.getCommand();
    this.help = Boolean.TRUE.equals(builder.getHelp());
    this.bindAddressSpecified = builder.isBindAddressSpecified();
    this.bindAddress = builder.getBindAddress();
    setDebug(Boolean.TRUE.equals(builder.getDebug()));
    this.deletePidFileOnStop = Boolean.TRUE.equals(builder.getDeletePidFileOnStop());
    this.distributedSystemProperties = builder.getDistributedSystemProperties();
    this.force = Boolean.TRUE.equals(builder.getForce());
    this.hostnameForClients = builder.getHostnameForClients();
    this.memberName = builder.getMemberName();
    this.pid = builder.getPid();
    this.portSpecified = builder.isPortSpecified();
    this.port = builder.getPort();
    this.redirectOutput = Boolean.TRUE.equals(builder.getRedirectOutput());
    this.workingDirectorySpecified = builder.isWorkingDirectorySpecified();
    this.workingDirectory = builder.getWorkingDirectory();
    this.controllerParameters = new LocatorControllerParameters();
    this.controlHandler = new ControlNotificationHandler() {
      @Override
      public void handleStop() {
        if (isStoppable()) {
          stopInProcess();
        }
      }

      @Override
      public ServiceState<?> handleStatus() {
        return statusInProcess();
      }
    };
  }

  /**
   * Returns the status of the locator on the given host & port
   */
  public static LocatorStatusResponse statusLocator(int port, InetAddress bindAddress)
      throws IOException {
    // final int timeout = (60 * 2 * 1000); // 2 minutes
    final int timeout = Integer.MAX_VALUE; // 2 minutes

    try {
      TcpClient client = new TcpClient(new DistributionConfigImpl(new Properties()));
      return (LocatorStatusResponse) client.requestToServer(bindAddress, port,
          new LocatorStatusRequest(), timeout, true);
    } catch (ClassNotFoundException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Gets a reference to the {@code Cache} that was created by this {@code LocatorLauncher}.
   *
   * @return a reference to the Cache
   * @see Cache
   */
  public Cache getCache() {
    return getInternalLocator().getCache();
  }

  /**
   * Gets a reference to the {@code Locator} that was created by this {@code LocatorLauncher}.
   *
   * @return a reference to the Locator.
   * @see Locator
   */
  public Locator getLocator() {
    return locator;
  }

  /**
   * Gets a reference to the {@code Locator} as an {@code InternalLocator}. For internal use only.
   *
   * @return a reference to the Locator as an InternalLocator.
   */
  InternalLocator getInternalLocator() {
    return locator;
  }

  /**
   * Gets an identifier that uniquely identifies and represents the Locator associated with this
   * launcher.
   *
   * @return a String value identifier to uniquely identify the Locator and it's launcher.
   * @see #getBindAddressAsString()
   * @see #getPortAsString()
   */
  public String getId() {
    return LocatorState.getBindAddressAsString(this).concat("[")
        .concat(LocatorState.getPortAsString(this)).concat("]");
  }

  /**
   * Get the Locator launcher command used to invoke the Locator.
   *
   * @return the Locator launcher command used to invoke the Locator.
   * @see org.apache.geode.distributed.LocatorLauncher.Command
   */
  public Command getCommand() {
    return this.command;
  }

  /**
   * Determines whether the PID file is allowed to be overwritten when the Locator is started and a
   * PID file already exists in the Locator's specified working directory.
   *
   * @return boolean indicating if force has been enabled.
   */
  public boolean isForcing() {
    return this.force;
  }

  /**
   * Determines whether this launcher will be used to display help information. If so, then none of
   * the standard Locator launcher commands will be used to affect the state of the Locator. A
   * launcher is said to be 'helping' if the user entered the "--help" option (switch) on the
   * command-line.
   *
   * @return a boolean value indicating if this launcher is used for displaying help information.
   * @see org.apache.geode.distributed.LocatorLauncher.Command
   */
  public boolean isHelping() {
    return this.help;
  }

  /**
   * Determines whether this launcher will redirect output to system logs when starting a new
   * Locator process.
   *
   * @return a boolean value indicating if this launcher will redirect output to system logs when
   *         starting a new Locator process
   */
  public boolean isRedirectingOutput() {
    return this.redirectOutput;
  }

  /**
   * Gets the IP address of the NIC to which the Locator has bound itself listening for client
   * requests.
   *
   * @return an InetAddress object representing the configured bind address for the Locator.
   * @see java.net.InetAddress
   */
  public InetAddress getBindAddress() {
    return this.bindAddress;
  }

  /**
   * Gets the host, as either hostname or IP address, on which the Locator was bound and running. An
   * attempt is made to get the canonical hostname for IP address to which the Locator was bound for
   * accepting client requests. If the bind address is null or localhost is unknown, then a default
   * String value of "localhost/127.0.0.1" is returned.
   *
   * Note, this information is purely information and should not be used to re-construct state or
   * for other purposes.
   *
   * @return the hostname or IP address of the host running the Locator, based on the bind-address,
   *         or 'localhost/127.0.0.1' if the bind address is null and localhost is unknown.
   * @see java.net.InetAddress
   * @see #getBindAddress()
   */
  protected String getBindAddressAsString() {
    try {
      if (getBindAddress() != null) {
        return getBindAddress().getCanonicalHostName();
      }

      InetAddress localhost = SocketCreator.getLocalHost();

      return localhost.getCanonicalHostName();
    } catch (UnknownHostException handled) {
      // Returning localhost/127.0.0.1 implies the bindAddress was null and no IP address for
      // localhost could be found
      return "localhost/127.0.0.1";
    }
  }

  /**
   * Gets the hostname that clients will use to lookup the running Locator.
   *
   * @return a String indicating the hostname used by clients to lookup the Locator.
   */
  public String getHostnameForClients() {
    return this.hostnameForClients;
  }

  /**
   * Gets the name of the log file used to log information about this Locator.
   *
   * @return a String value indicating the name of this Locator's log file.
   */
  @Override
  public String getLogFileName() {
    return defaultIfBlank(getMemberName(), DEFAULT_LOCATOR_LOG_NAME)
        .concat(DEFAULT_LOCATOR_LOG_EXT);
  }

  /**
   * Gets the name of this member (this Locator) in the GemFire distributed system and determined by
   * the 'name' GemFire property.
   *
   * @return a String indicating the name of the member (this Locator) in the GemFire distributed
   *         system.
   */
  @Override
  public String getMemberName() {
    return defaultIfBlank(this.memberName, super.getMemberName());
  }

  /**
   * Gets the user-specified process ID (PID) of the running Locator that LocatorLauncher uses to
   * issue status and stop commands to the Locator.
   *
   * @return an Integer value indicating the process ID (PID) of the running Locator.
   */
  @Override
  public Integer getPid() {
    return this.pid;
  }

  /**
   * Gets the port number on which the Locator listens for client requests.
   *
   * @return an Integer value indicating the port number on which the Locator is listening for
   *         client requests.
   */
  public Integer getPort() {
    if (locator != null) {
      return locator.getPort();
    }

    return this.port;
  }

  /**
   * Gets the port number represented as a String value. If the port number is null, the the default
   * Locator port (10334) is returned;
   *
   * @return the port number as a String value.
   * @see #getPort()
   */
  public String getPortAsString() {
    Integer port = getPort();
    return (port != null ? port : getDefaultLocatorPort()).toString();
  }

  /**
   * Gets the GemFire Distributed System (cluster) Properties.
   *
   * @return a Properties object containing the configuration settings for the GemFire Distributed
   *         System (cluster).
   * @see java.util.Properties
   */
  public Properties getProperties() {
    return (Properties) this.distributedSystemProperties.clone();
  }

  /**
   * Gets the name for a GemFire Locator.
   *
   * @return a String indicating the name for a GemFire Locator.
   */
  @Override
  public String getServiceName() {
    return LOCATOR_SERVICE_NAME;
  }

  /**
   * Gets the working directory pathname in which the Locator will be run.
   *
   * @return a String value indicating the pathname of the Locator's working directory.
   */
  @Override
  public String getWorkingDirectory() {
    return this.workingDirectory;
  }

  /**
   * Displays help for the specified Locator launcher command to standard err. If the Locator
   * launcher command is unspecified, then usage information is displayed instead.
   *
   * @param command the Locator launcher command in which to display help information.
   * @see #usage()
   */
  public void help(final Command command) {
    if (Command.isUnspecified(command)) {
      usage();
    } else {
      info(wrap(helpMap.get(command.getName()), 80, ""));
      info("\n\nusage: \n\n");
      info(wrap("> java ... " + getClass().getName() + " " + usageMap.get(command), 80, "\t\t"));
      info("\n\noptions: \n\n");

      for (String option : command.getOptions()) {
        info(wrap("--" + option + ": " + helpMap.get(option) + "\n", 80, "\t"));
      }

      info("\n\n");
    }
  }

  /**
   * Displays usage information on the proper invocation of the LocatorLauncher from the
   * command-line to standard err.
   *
   * @see #help(org.apache.geode.distributed.LocatorLauncher.Command)
   */
  public void usage() {
    info(wrap(helpMap.get("launcher"), 80, "\t"));
    info("\n\nSTART\n\n");
    help(Command.START);
    info("STATUS\n\n");
    help(Command.STATUS);
    info("STOP\n\n");
    help(Command.STOP);
  }

  /**
   * The Runnable method used to launch the Locator with the specified command. If 'start' has been
   * issued, then run will block as expected for the Locator to stop. The 'start' command is
   * implemented with a call to start() followed by a call to waitOnLocator().
   *
   * @see java.lang.Runnable
   * @see LocatorLauncher.Command
   * @see LocatorLauncher#start()
   * @see LocatorLauncher#waitOnLocator()
   * @see LocatorLauncher#status()
   * @see LocatorLauncher#stop()
   * @see LocatorLauncher#version()
   * @see LocatorLauncher#help(org.apache.geode.distributed.LocatorLauncher.Command)
   * @see LocatorLauncher#usage()
   */
  @Override
  public void run() {
    if (!isHelping()) {
      switch (getCommand()) {
        case START:
          info(start());
          waitOnLocator();
          break;
        case STATUS:
          info(status());
          break;
        case STOP:
          info(stop());
          break;
        case VERSION:
          info(version());
          break;
        default:
          usage();
      }
    } else {
      help(getCommand());
    }
  }

  /**
   * Gets a File reference with the path to the PID file for the Locator.
   *
   * @return a File reference to the path of the Locator's PID file.
   */
  protected File getLocatorPidFile() {
    return new File(getWorkingDirectory(), ProcessType.LOCATOR.getPidFileName());
  }

  /**
   * Determines whether a GemFire Locator can be started with this instance of LocatorLauncher.
   *
   * @return a boolean indicating whether a GemFire Locator can be started with this instance of
   *         LocatorLauncher, which is true if the LocatorLauncher has not already started a Locator
   *         or a Locator is not already running.
   * @see #start()
   */
  private boolean isStartable() {
    return (!isRunning() && this.starting.compareAndSet(false, true));
  }

  /**
   * Starts a Locator running on the specified port and bind address, as determined by getPort and
   * getBindAddress respectively, defaulting to 10334 and 'localhost' if not specified, with both
   * peer and server location enabled.
   *
   * 'start' is an asynchronous invocation of the Locator. As such, this method makes no guarantees
   * whether the Locator's location services (peer and server) are actually running before it
   * returns. The Locator's location-based services are initiated in separate, daemon Threads and
   * depends on the relative timing and scheduling of those Threads by the JVM. If the application
   * using this API wishes for the Locator to continue running after normal application processing
   * completes, then one must call <code>waitOnLocator</code>.
   *
   * Given the nature of start, the Locator's status will be in either 1 of 2 possible states. If
   * the 'request' to start the Locator proceeds without exception, the status will be 'STARTED'.
   * However, if any exception is encountered during the normal startup sequence, then a
   * RuntimeException is thrown and the status is set to 'STOPPED'.
   *
   * @return a LocatorState to reflect the state of the Locator after start.
   * @throws RuntimeException if the Locator failed to start for any reason.
   * @throws IllegalStateException if the Locator is already running.
   * @see #failOnStart(Throwable)
   * @see #getBindAddress()
   * @see #getDistributedSystemProperties()
   * @see #isForcing()
   * @see #getLogFile()
   * @see #getLocatorPidFile
   * @see #getPort()
   * @see #status()
   * @see #stop()
   * @see #waitOnLocator()
   * @see #waitOnStatusResponse(long, long, java.util.concurrent.TimeUnit)
   * @see org.apache.geode.distributed.LocatorLauncher.LocatorState
   * @see org.apache.geode.distributed.AbstractLauncher.Status#NOT_RESPONDING
   * @see org.apache.geode.distributed.AbstractLauncher.Status#ONLINE
   * @see org.apache.geode.distributed.AbstractLauncher.Status#STARTING
   */
  @SuppressWarnings("deprecation")
  public LocatorState start() {
    if (isStartable()) {
      INSTANCE.compareAndSet(null, this);

      try {
        this.process = new ControllableProcess(this.controlHandler, new File(getWorkingDirectory()),
            ProcessType.LOCATOR, isForcing());

        assertPortAvailable(getBindAddress(), getPort());

        ProcessLauncherContext.set(isRedirectingOutput(), getOverriddenDefaults(),
            statusMessage -> LocatorLauncher.this.statusMessage = statusMessage);

        try {
          this.locator = InternalLocator.startLocator(getPort(), getLogFile(), null, null,
              getBindAddress(), true, getDistributedSystemProperties(), getHostnameForClients(),
              Paths.get(workingDirectory));
        } finally {
          ProcessLauncherContext.remove();
        }

        debug("Running Locator on (%1$s) in (%2$s) as (%3$s)...", getId(), getWorkingDirectory(),
            getMember());
        log.debug("Locator is online");
        running.set(true);

        return new LocatorState(this, Status.ONLINE);
      } catch (IOException e) {
        failOnStart(e);
        throw new RuntimeException(
            String.format("An IO error occurred while starting a %s in %s on %s: %s",
                getServiceName(), getWorkingDirectory(), getId(), e.getMessage()),
            e);
      } catch (FileAlreadyExistsException e) {
        failOnStart(e);
        throw new RuntimeException(
            String.format("A PID file already exists and a %s may be running in %s on %s.",
                getServiceName(), getWorkingDirectory(), getId()),
            e);
      } catch (PidUnavailableException e) {
        failOnStart(e);
        throw new RuntimeException(
            String.format("The process ID could not be determined while starting %s %s in %s: %s",
                getServiceName(), getId(), getWorkingDirectory(), e.getMessage()),
            e);
      } catch (Error | RuntimeException e) {
        failOnStart(e);
        throw e;
      } catch (Exception e) {
        failOnStart(e);
        throw new RuntimeException(e);
      } finally {
        this.starting.set(false);
      }
    } else {
      throw new IllegalStateException(
          String.format("A %s is already running in %s on %s.",
              getServiceName(), getWorkingDirectory(), getId()));
    }
  }

  @Override
  protected Properties getDistributedSystemProperties() {
    return super.getDistributedSystemProperties(getProperties());
  }

  /**
   * A helper method to ensure the same sequence of actions are taken when the Locator fails to
   * start caused by some exception.
   *
   * @param cause the Throwable thrown during the startup or wait operation on the Locator.
   */
  private void failOnStart(final Throwable cause) {
    if (cause != null) {
      log.info("locator is exiting due to an exception", cause);
    } else {
      log.info("locator is exiting normally");
    }

    if (this.locator != null) {
      this.locator.stop();
      this.locator = null;
    }
    if (this.process != null) {
      this.process.stop(this.deletePidFileOnStop);
      this.process = null;
    }

    INSTANCE.compareAndSet(this, null);

    this.running.set(false);
  }

  /**
   * Waits on the Locator to stop causing the calling Thread to join with the Locator's
   * location-based services Thread.
   *
   * @return the Locator's status once it stops.
   * @throws AssertionError if the Locator has not been started and the reference is null
   *         (assertions must be enabled for the error to be thrown).
   * @see #failOnStart(Throwable)
   * @see org.apache.geode.distributed.AbstractLauncher.Status
   * @see org.apache.geode.distributed.LocatorLauncher.LocatorState
   */
  public LocatorState waitOnLocator() {
    Throwable t = null;

    try {
      // make sure the Locator was started and the reference was set
      assert getInternalLocator() != null : "The Locator must first be started with a call to start!";

      debug("Waiting on Locator (%1$s) to stop...", getId());

      // prevent the JVM from exiting by joining the Locator Thread
      getInternalLocator().waitToStop();
    } catch (InterruptedException handled) {
      Thread.currentThread().interrupt();
      t = handled;
      debug(handled);
    } catch (Throwable e) {
      t = e;
      throw e;
    } finally {
      failOnStart(t);
    }

    return new LocatorState(this, Status.STOPPED);
  }

  /**
   * Waits for a Locator status request response to be returned up to the specified timeout in the
   * given unit of time. This call will send status requests at fixed intervals in the given unit of
   * time until the timeout expires. If the request to determine the Locator's status is successful,
   * then the Locator is considered to be 'ONLINE'. Otherwise, the Locator is considered to be
   * unresponsive to the status request.
   *
   * However, this does not necessarily imply the Locator start was unsuccessful, only that a
   * response was not received in the given time period.
   *
   * Note, this method does not block or cause the Locator's location-based services (daemon
   * Threads) to continue running in anyway if the main application Thread terminates when running
   * the Locator in-process. If the caller wishes to start a Locator in an asynchronous manner
   * within the application process, then a call should be made to <code>waitOnLocator</code>.
   *
   * @param timeout a long value in time unit indicating when the period of time should expire in
   *        attempting to determine the Locator's status.
   * @param interval a long value in time unit for how frequent the requests should be sent to the
   *        Locator.
   * @param timeUnit the unit of time in which the timeout and interval are measured.
   * @return the state of the Locator, which will either be 'ONLINE' or "NOT RESPONDING'. If the
   *         status returned is 'NOT RESPONDING', it just means the Locator did not respond to the
   *         status request within the given time period. It should not be taken as the Locator
   *         failed to start.
   * @see #waitOnLocator()
   */
  public LocatorState waitOnStatusResponse(final long timeout, final long interval,
      final TimeUnit timeUnit) {
    final long endTimeInMilliseconds = (System.currentTimeMillis() + timeUnit.toMillis(timeout));

    while (System.currentTimeMillis() < endTimeInMilliseconds) {
      try {
        LocatorStatusResponse response = statusLocator(getPort(), getBindAddress());
        return new LocatorState(this, Status.ONLINE, response);
      } catch (Exception handled) {
        timedWait(interval, timeUnit);
      }
    }

    // NOTE just because we were not able to communicate with the Locator in the given amount of
    // time does not mean
    // the Locator is having problems. The Locator could be slow in starting up and the timeout may
    // not be
    // long enough.
    return new LocatorState(this, Status.NOT_RESPONDING);
  }

  private void timedWait(final long interval, final TimeUnit timeUnit) {
    try {
      synchronized (this) {
        timeUnit.timedWait(this, interval);
      }
    } catch (InterruptedException handled) {
      // NOTE just go and send another status request to the Locator...
    }
  }

  /**
   * Attempts to determine the state of the Locator. The Locator's status will be in only 1 of 2
   * possible states, either ONLINE or OFFLINE. This method behaves differently depending on which
   * parameters were specified when the LocatorLauncher was constructed with an instance of Builder.
   * If either the 'dir' or the 'pid' command-line option were specified, then an attempt is made to
   * determine the Locator's status by using the dir or pid to correctly identify the Locator's
   * MemberMXBean registered in the MBeanServer of the Locator's JVM, and invoking the 'status'
   * operation. The same behavior occurs if the caller specified the Locator's GemFire member name
   * or ID.
   *
   * However, if 'dir' or 'pid' were not specified, then determining the Locator's status defaults
   * to using the configured bind address and port. If the bind address or port was not specified
   * when using the Builder to construct a LocatorLauncher instance, then the defaults for both bind
   * address and port are used. In either case, an actual TCP/IP request is made to the Locator's
   * ServerSocket to ensure it is listening for client requests. This is true even when the
   * LocatorLauncher is used in-process by calling the API.
   *
   * If the conditions above hold, then the Locator is deemed to be 'ONLINE', otherwise, the Locator
   * is considered 'OFFLINE'.
   *
   * @return the Locator's state.
   * @see #start()
   * @see #stop()
   * @see org.apache.geode.distributed.AbstractLauncher.Status
   * @see org.apache.geode.distributed.LocatorLauncher.LocatorState
   */
  public LocatorState status() {
    final LocatorLauncher launcher = getInstance();
    // if this instance is starting then return local status
    if (this.starting.get()) {
      debug(
          "Getting status from the LocatorLauncher instance that actually launched the GemFire Locator.%n");
      return new LocatorState(this, Status.STARTING);
    }
    // if this instance is running then return local status
    else if (isRunning()) {
      debug("Getting Locator status using host (%1$s) and port (%2$s)%n", getBindAddressAsString(),
          getPortAsString());
      return statusWithPort();
    }
    // if in-process do not use ProcessController
    else if (isPidInProcess() && launcher != null) {
      return launcher.statusInProcess();
    }
    // attempt to get status using pid if provided
    else if (getPid() != null) {
      debug("Getting Locator status using process ID (%1$s)%n", getPid());
      return statusWithPid();
    }
    // attempt to get status using workingDirectory unless port was specified
    else if (!(this.bindAddressSpecified || this.portSpecified)) {
      debug("Getting Locator status using working directory (%1$s)%n", getWorkingDirectory());
      return statusWithWorkingDirectory();
    }
    // attempt to get status using host and port (Note, bind address doubles as host when the
    // launcher is used to get the Locator's status).
    else {
      debug("Getting Locator status using host (%1$s) and port (%2$s)%n", getBindAddressAsString(),
          getPortAsString());
      return statusWithPort();
    }
  }

  private LocatorState statusInProcess() {
    if (this.starting.get()) {
      debug(
          "Getting status from the LocatorLauncher instance that actually launched the GemFire Locator.%n");
      return new LocatorState(this, Status.STARTING);
    } else {
      debug("Getting Locator status using host (%1$s) and port (%2$s)%n", getBindAddressAsString(),
          getPortAsString());
      return statusWithPort();
    }

  }

  private LocatorState statusWithPid() {
    try {
      final ProcessController controller = new ProcessControllerFactory()
          .createProcessController(this.controllerParameters, getPid());
      controller.checkPidSupport();
      final String statusJson = controller.status();
      return LocatorState.fromJson(statusJson);
    } catch (ConnectionFailedException handled) {
      // failed to attach to locator JVM
      return createNoResponseState(handled,
          "Failed to connect to locator with process id " + getPid());
    } catch (IOException | MBeanInvocationFailedException | UnableToControlProcessException
        | TimeoutException handled) {
      return createNoResponseState(handled,
          "Failed to communicate with locator with process id " + getPid());
    } catch (InterruptedException handled) {
      Thread.currentThread().interrupt();
      return createNoResponseState(handled,
          "Interrupted while trying to communicate with locator with process id " + getPid());
    }
  }

  private LocatorState statusWithPort() {
    try {
      LocatorStatusResponse response = statusLocator(getPort(), getBindAddress());
      return new LocatorState(this, Status.ONLINE, response);
    } catch (Exception handled) {
      return createNoResponseState(handled,
          "Failed to connect to locator " + getBindAddressAsString() + "[" + getPort() + "]");
    }
  }

  private LocatorState statusWithWorkingDirectory() {
    int parsedPid = 0;
    try {
      final ProcessController controller =
          new ProcessControllerFactory().createProcessController(this.controllerParameters,
              new File(getWorkingDirectory()), ProcessType.LOCATOR.getPidFileName());
      parsedPid = controller.getProcessId();

      // note: in-process request will go infinite loop unless we do the following
      if (parsedPid == ProcessUtils.identifyPid()) {
        LocatorLauncher runningLauncher = getInstance();
        if (runningLauncher != null) {
          return runningLauncher.status();
        }
      }

      final String statusJson = controller.status();
      return LocatorState.fromJson(statusJson);
    } catch (ConnectionFailedException handled) {
      // failed to attach to locator JVM
      return createNoResponseState(handled,
          "Failed to connect to locator with process id " + parsedPid);
    } catch (FileNotFoundException handled) {
      // could not find pid file
      return createNoResponseState(handled, "Failed to find process file "
          + ProcessType.LOCATOR.getPidFileName() + " in " + getWorkingDirectory());
    } catch (IOException | MBeanInvocationFailedException | UnableToControlProcessException
        | TimeoutException handled) {
      return createNoResponseState(handled,
          "Failed to communicate with locator with process id " + parsedPid);
    } catch (PidUnavailableException e) {
      // couldn't determine pid from within locator JVM
      return createNoResponseState(e, "Failed to find usable process id within file "
          + ProcessType.LOCATOR.getPidFileName() + " in " + getWorkingDirectory());
    } catch (InterruptedException handled) {
      Thread.currentThread().interrupt();
      return createNoResponseState(handled,
          "Interrupted while trying to communicate with locator with process id " + parsedPid);
    }
  }

  /**
   * Determines whether the Locator can be stopped in-process, such as when a Locator is embedded in
   * an application and the LocatorLauncher API is being used.
   *
   * @return a boolean indicating whether the Locator can be stopped in-process (the application's
   *         process with an embedded Locator).
   */
  protected boolean isStoppable() {
    return (isRunning() && getInternalLocator() != null);
  }

  /**
   * Stop shuts the running Locator down. Using the API, the Locator is requested to stop by calling
   * the Locator object's 'stop' method. Internally, this method is no different than using the
   * LocatorLauncher class from the command-line or from within GemFire shell (Gfsh). In every
   * single case, stop sends a TCP/IP 'shutdown' request on the configured address/port to which the
   * Locator is bound and listening.
   *
   * If the "shutdown" request is successful, then the Locator will be 'STOPPED'. Otherwise, the
   * Locator is considered 'OFFLINE' since the actual state cannot be fully assessed (as in the
   * application process in which the Locator was hosted may still be running and the Locator object
   * may still exist even though it is no longer responding to location-based requests). The later
   * is particularly important in cases where the system resources (such as Sockets) may not have
   * been cleaned up yet. Therefore, by returning a status of 'OFFLINE', the value is meant to
   * reflect this in-deterministic state.
   *
   * @return a LocatorState indicating the state of the Locator after stop has been requested.
   * @see #start()
   * @see #status()
   * @see org.apache.geode.distributed.LocatorLauncher.LocatorState
   * @see org.apache.geode.distributed.AbstractLauncher.Status#NOT_RESPONDING
   * @see org.apache.geode.distributed.AbstractLauncher.Status#STOPPED
   */
  public LocatorState stop() {
    final LocatorLauncher launcher = getInstance();
    // if this instance is running then stop it
    if (isStoppable()) {
      return stopInProcess();
    }
    // if in-process but difference instance of LocatorLauncher
    else if (isPidInProcess() && launcher != null) {
      return launcher.stopInProcess();
    }
    // attempt to stop Locator using pid...
    else if (getPid() != null) {
      return stopWithPid();
    }
    // attempt to stop Locator using the working directory...
    else if (getWorkingDirectory() != null) {
      return stopWithWorkingDirectory();
    } else {
      return new LocatorState(this, Status.NOT_RESPONDING);
    }
  }

  private LocatorState stopInProcess() {
    if (isStoppable()) {
      this.locator.stop();
      this.locator = null;
      this.process.stop(this.deletePidFileOnStop);
      this.process = null;
      INSTANCE.compareAndSet(this, null); // note: other thread may return Status.NOT_RESPONDING now
      this.running.set(false);
      return new LocatorState(this, Status.STOPPED);
    } else {
      return new LocatorState(this, Status.NOT_RESPONDING);
    }
  }

  private LocatorState stopWithPid() {
    try {
      final ProcessController controller = new ProcessControllerFactory()
          .createProcessController(new LocatorControllerParameters(), getPid());
      controller.checkPidSupport();
      controller.stop();
      return new LocatorState(this, Status.STOPPED);
    } catch (ConnectionFailedException handled) {
      // failed to attach to locator JVM
      return createNoResponseState(handled,
          "Failed to connect to locator with process id " + getPid());
    } catch (IOException | MBeanInvocationFailedException
        | UnableToControlProcessException handled) {
      return createNoResponseState(handled,
          "Failed to communicate with locator with process id " + getPid());
    }
  }

  private LocatorState stopWithWorkingDirectory() {
    int parsedPid = 0;
    try {
      final ProcessController controller =
          new ProcessControllerFactory().createProcessController(this.controllerParameters,
              new File(getWorkingDirectory()), ProcessType.LOCATOR.getPidFileName());
      parsedPid = controller.getProcessId();

      // NOTE in-process request will go infinite loop unless we do the following
      if (parsedPid == ProcessUtils.identifyPid()) {
        final LocatorLauncher runningLauncher = getInstance();
        if (runningLauncher != null) {
          return runningLauncher.stopInProcess();
        }
      }

      controller.stop();
      return new LocatorState(this, Status.STOPPED);
    } catch (ConnectionFailedException handled) {
      // failed to attach to locator JVM
      return createNoResponseState(handled,
          "Failed to connect to locator with process id " + parsedPid);
    } catch (FileNotFoundException handled) {
      // could not find pid file
      return createNoResponseState(handled, "Failed to find process file "
          + ProcessType.LOCATOR.getPidFileName() + " in " + getWorkingDirectory());
    } catch (IOException | MBeanInvocationFailedException
        | UnableToControlProcessException handled) {
      return createNoResponseState(handled,
          "Failed to communicate with locator with process id " + parsedPid);
    } catch (InterruptedException handled) {
      Thread.currentThread().interrupt();
      return createNoResponseState(handled,
          "Interrupted while trying to communicate with locator with process id " + parsedPid);
    } catch (PidUnavailableException handled) {
      // couldn't determine pid from within locator JVM
      return createNoResponseState(handled, "Failed to find usable process id within file "
          + ProcessType.LOCATOR.getPidFileName() + " in " + getWorkingDirectory());
    } catch (TimeoutException handled) {
      return createNoResponseState(handled,
          "Timed out trying to find usable process id within file "
              + ProcessType.LOCATOR.getPidFileName() + " in " + getWorkingDirectory());
    }
  }

  private LocatorState createNoResponseState(final Exception cause, final String errorMessage) {
    debug(ExceptionUtils.getStackTrace(cause) + errorMessage);
    return new LocatorState(this, Status.NOT_RESPONDING, errorMessage);
  }

  private Properties getOverriddenDefaults() throws IOException {
    Properties overriddenDefaults = new Properties();

    overriddenDefaults.put(ProcessLauncherContext.OVERRIDDEN_DEFAULTS_PREFIX.concat(LOG_FILE),
        getLogFile().getCanonicalPath());

    for (String key : System.getProperties().stringPropertyNames()) {
      if (key.startsWith(ProcessLauncherContext.OVERRIDDEN_DEFAULTS_PREFIX)) {
        overriddenDefaults.put(key, System.getProperty(key));
      }
    }

    return overriddenDefaults;
  }

  private class LocatorControllerParameters implements ProcessControllerParameters {
    @Override
    public File getPidFile() {
      return getLocatorPidFile();
    }

    @Override
    public File getDirectory() {
      return new File(LocatorLauncher.this.getWorkingDirectory());
    }

    @Override
    public int getProcessId() {
      return getPid();
    }

    @Override
    public ProcessType getProcessType() {
      return ProcessType.LOCATOR;
    }

    @Override
    public ObjectName getNamePattern() {
      try {
        return ObjectName.getInstance("GemFire:type=Member,*");
      } catch (MalformedObjectNameException | NullPointerException handled) {
        return null;
      }
    }

    @Override
    public String getPidAttribute() {
      return "ProcessId";
    }

    @Override
    public String getStopMethod() {
      return "shutDownMember";
    }

    @Override
    public String getStatusMethod() {
      return "status";
    }

    @Override
    public String[] getAttributes() {
      return new String[] {"Locator", "Server"};
    }

    @Override
    public Object[] getValues() {
      return new Object[] {Boolean.TRUE, Boolean.FALSE};
    }
  }

  /**
   * Following the Builder design pattern, the LocatorLauncher Builder is used to configure and
   * create a properly initialized instance of the LocatorLauncher class for running the Locator and
   * performing other Locator operations.
   */
  public static class Builder {

    @Immutable
    protected static final Command DEFAULT_COMMAND = Command.UNSPECIFIED;

    private Boolean debug;
    private Boolean deletePidFileOnStop;
    private Boolean force;
    private Boolean help;
    private Boolean redirectOutput;
    private Boolean loadSharedConfigFromDir;
    private Command command;

    private InetAddress bindAddress;

    private Integer pid;
    private Integer port;

    private final Properties distributedSystemProperties = new Properties();

    private String hostnameForClients;
    private String memberName;
    private String workingDirectory;

    /**
     * Default constructor used to create an instance of the Builder class for programmatical
     * access.
     */
    public Builder() {}

    /**
     * Constructor used to create and configure an instance of the Builder class with the specified
     * arguments, often passed from the command-line when launching an instance of this class from
     * the command-line using the Java launcher.
     *
     * @param args the array of arguments used to configure the Builder.
     */
    public Builder(final String... args) {
      parseArguments(args != null ? args : new String[0]);
    }

    /**
     * Gets an instance of the JOpt Simple OptionParser to parse the command-line arguments.
     *
     * @return an instance of the JOpt Simple OptionParser configured with the command-line options
     *         used by the Locator.
     */
    private OptionParser getParser() {
      final OptionParser parser = new OptionParser(true);

      parser.accepts("bind-address").withRequiredArg().ofType(String.class);
      parser.accepts("debug");
      parser.accepts("delete-pid-file-on-stop");
      parser.accepts("dir").withRequiredArg().ofType(String.class);
      parser.accepts("force");
      parser.accepts("help");
      parser.accepts("hostname-for-clients").withRequiredArg().ofType(String.class);
      parser.accepts("pid").withRequiredArg().ofType(Integer.class);
      parser.accepts("port").withRequiredArg().ofType(Integer.class);
      parser.accepts("redirect-output");
      parser.accepts("version");

      return parser;
    }

    /**
     * Parses an array of arguments to configure this Builder with the intent of constructing a
     * Locator launcher to invoke a Locator. This method is called to parse the arguments specified
     * by the user on the command-line.
     *
     * @param args the array of arguments used to configure this Builder and create an instance of
     *        LocatorLauncher.
     */
    protected void parseArguments(final String... args) {
      try {
        parseCommand(args);
        parseMemberName(args);

        final OptionSet options = getParser().parse(args);

        setDebug(options.has("debug"));
        setDeletePidFileOnStop(options.has("delete-pid-file-on-stop"));
        setForce(options.has("force"));
        setHelp(options.has("help"));
        setRedirectOutput(options.has("redirect-output"));

        if (!isHelping()) {
          if (options.has("bind-address")) {
            setBindAddress(ObjectUtils.toString(options.valueOf("bind-address")));
          }

          if (options.has("dir")) {
            setWorkingDirectory(ObjectUtils.toString(options.valueOf("dir")));
          }

          if (options.has("hostname-for-clients")) {
            setHostnameForClients(ObjectUtils.toString(options.valueOf("hostname-for-clients")));
          }

          if (options.has("pid")) {
            setPid((Integer) options.valueOf("pid"));
          }

          if (options.has("port")) {
            setPort((Integer) options.valueOf("port"));
          }

          if (options.has("version")) {
            setCommand(Command.VERSION);
          }
        }
      } catch (OptionException e) {
        throw new IllegalArgumentException(
            String.format("An error occurred while parsing command-line arguments for the %s: %s",
                "Locator", e.getMessage()),
            e);
      } catch (Exception e) {
        throw new RuntimeException(e.getMessage(), e);
      }
    }

    /**
     * Iterates the list of arguments in search of the target Locator launcher command.
     *
     * @param args an array of arguments from which to search for the Locator launcher command.
     * @see org.apache.geode.distributed.LocatorLauncher.Command#valueOfName(String)
     * @see #parseArguments(String...)
     */
    protected void parseCommand(final String... args) {
      // search the list of arguments for the command; technically, the command should be the first
      // argument in the
      // list, but does it really matter? stop after we find one valid command.
      if (args != null) {
        for (String arg : args) {
          final Command command = Command.valueOfName(arg);
          if (command != null) {
            setCommand(command);
            break;
          }
        }
      }
    }

    /**
     * Iterates the list of arguments in search of the Locator's GemFire member name. If the
     * argument does not start with '-' or is not the name of a Locator launcher command, then the
     * value is presumed to be the member name for the Locator in GemFire.
     *
     * @param args the array of arguments from which to search for the Locator's member name in
     *        GemFire.
     * @see org.apache.geode.distributed.LocatorLauncher.Command#isCommand(String)
     * @see #parseArguments(String...)
     */
    protected void parseMemberName(final String... args) {
      if (args != null) {
        for (String arg : args) {
          if (!(arg.startsWith(OPTION_PREFIX) || Command.isCommand(arg))) {
            setMemberName(arg);
            break;
          }
        }
      }
    }

    /**
     * Gets the Locator launcher command used during the invocation of the LocatorLauncher.
     *
     * @return the Locator launcher command used to invoke (run) the LocatorLauncher class.
     * @see #setCommand(org.apache.geode.distributed.LocatorLauncher.Command)
     * @see LocatorLauncher.Command
     */
    public Command getCommand() {
      return this.command != null ? this.command : DEFAULT_COMMAND;
    }

    /**
     * Sets the Locator launcher command used during the invocation of the LocatorLauncher
     *
     * @param command the targeted Locator launcher command used during the invocation (run) of
     *        LocatorLauncher.
     * @return this Builder instance.
     * @see #getCommand()
     * @see LocatorLauncher.Command
     */
    public Builder setCommand(final Command command) {
      this.command = command;
      return this;
    }

    /**
     * Determines whether the new instance of the LocatorLauncher will be set to debug mode.
     *
     * @return a boolean value indicating whether debug mode is enabled or disabled.
     * @see #setDebug(Boolean)
     */
    public Boolean getDebug() {
      return this.debug;
    }

    /**
     * Sets whether the new instance of the LocatorLauncher will be set to debug mode.
     *
     * @param debug a boolean value indicating whether debug mode is to be enabled or disabled.
     * @return this Builder instance.
     * @see #getDebug()
     */
    public Builder setDebug(final Boolean debug) {
      this.debug = debug;
      return this;
    }

    /**
     * Determines whether the Geode Locator should delete the pid file when its service stops or
     * when the JVM exits.
     *
     * @return a boolean value indicating if the pid file should be deleted when this service stops
     *         or when the JVM exits.
     * @see #setDeletePidFileOnStop(Boolean)
     */
    public Boolean getDeletePidFileOnStop() {
      return this.deletePidFileOnStop;
    }

    /**
     * Sets whether the Geode Locator should delete the pid file when its service stops or when the
     * JVM exits.
     *
     * @param deletePidFileOnStop a boolean value indicating if the pid file should be deleted when
     *        this service stops or when the JVM exits.
     * @return this Builder instance.
     * @see #getDeletePidFileOnStop()
     */
    public Builder setDeletePidFileOnStop(final Boolean deletePidFileOnStop) {
      this.deletePidFileOnStop = deletePidFileOnStop;
      return this;
    }

    /**
     * Gets the GemFire Distributed System (cluster) Properties configuration.
     *
     * @return a Properties object containing configuration settings for the GemFire Distributed
     *         System (cluster).
     * @see java.util.Properties
     */
    public Properties getDistributedSystemProperties() {
      return this.distributedSystemProperties;
    }

    /**
     * Gets the boolean value used by the Locator to determine if it should overwrite the PID file
     * if it already exists.
     *
     * @return the boolean value specifying whether or not to overwrite the PID file if it already
     *         exists.
     * @see #setForce(Boolean)
     */
    public Boolean getForce() {
      return this.force != null ? this.force : DEFAULT_FORCE;
    }

    /**
     * Sets the boolean value used by the Locator to determine if it should overwrite the PID file
     * if it already exists.
     *
     * @param force a boolean value indicating whether to overwrite the PID file when it already
     *        exists.
     * @return this Builder instance.
     * @see #getForce()
     */
    public Builder setForce(final Boolean force) {
      this.force = force;
      return this;
    }


    /**
     * Determines whether the new instance of LocatorLauncher will be used to output help
     * information for either a specific command, or for using LocatorLauncher in general.
     *
     * @return a boolean value indicating whether help will be output during the invocation of
     *         LocatorLauncher.
     * @see #setHelp(Boolean)
     */
    public Boolean getHelp() {
      return this.help;
    }

    /**
     * Determines whether help has been enabled.
     *
     * @return a boolean indicating if help was enabled.
     */
    private boolean isHelping() {
      return Boolean.TRUE.equals(getHelp());
    }

    /**
     * Sets whether the new instance of LocatorLauncher will be used to output help information for
     * either a specific command, or for using LocatorLauncher in general.
     *
     * @param help a boolean indicating whether help information is to be displayed during
     *        invocation of LocatorLauncher.
     * @return this Builder instance.
     * @see #getHelp()
     */
    public Builder setHelp(final Boolean help) {
      this.help = help;
      return this;
    }

    boolean isBindAddressSpecified() {
      return (getBindAddress() != null);

    }

    /**
     * Gets the IP address to which the Locator has bound itself listening for client requests.
     *
     * @return an InetAddress with the IP address or hostname on which the Locator is bound and
     *         listening.
     * @see #setBindAddress(String)
     * @see java.net.InetAddress
     */
    public InetAddress getBindAddress() {
      return this.bindAddress;
    }

    /**
     * Sets the IP address as an java.net.InetAddress to which the Locator has bound itself
     * listening for client requests.
     *
     * @param bindAddress the InetAddress with the IP address or hostname on which the Locator is
     *        bound and listening.
     * @return this Builder instance.
     * @throws IllegalArgumentException wrapping the UnknownHostException if the IP address or
     *         hostname for the bind address is unknown.
     * @see #getBindAddress()
     * @see java.net.InetAddress
     */
    public Builder setBindAddress(final String bindAddress) {
      if (isBlank(bindAddress)) {
        this.bindAddress = null;
        return this;
      } else {
        try {
          InetAddress address = InetAddress.getByName(bindAddress);
          if (SocketCreator.isLocalHost(address)) {
            this.bindAddress = address;
            return this;
          } else {
            throw new IllegalArgumentException(
                bindAddress + " is not an address for this machine.");
          }
        } catch (UnknownHostException e) {
          throw new IllegalArgumentException(
              String.format("The hostname/IP address to which the %s will be bound is unknown.",
                  "Locator"),
              e);
        }
      }
    }

    /**
     * Gets the hostname used by clients to lookup the Locator.
     *
     * @return a String indicating the hostname Locator binding used in client lookups.
     * @see #setHostnameForClients(String)
     */
    public String getHostnameForClients() {
      return this.hostnameForClients;
    }

    /**
     * Sets the hostname used by clients to lookup the Locator.
     *
     * @param hostnameForClients a String indicating the hostname Locator binding used in client
     *        lookups.
     * @return this Builder instance.
     * @throws IllegalArgumentException if the hostname was not specified (is blank or empty), such
     *         as when the --hostname-for-clients command-line option may have been specified
     *         without any argument.
     * @see #getHostnameForClients()
     */
    public Builder setHostnameForClients(final String hostnameForClients) {
      if (isBlank(hostnameForClients)) {
        throw new IllegalArgumentException(
            "The hostname used by clients to connect to the Locator must have an argument if the --hostname-for-clients command-line option is specified!");
      }
      this.hostnameForClients = hostnameForClients;
      return this;
    }

    /**
     * Gets the member name of this Locator in GemFire.
     *
     * @return a String indicating the member name of this Locator in GemFire.
     * @see #setMemberName(String)
     */
    public String getMemberName() {
      return this.memberName;
    }

    /**
     * Sets the member name of the Locator in GemFire.
     *
     * @param memberName a String indicating the member name of this Locator in GemFire.
     * @return this Builder instance.
     * @throws IllegalArgumentException if the member name is invalid.
     * @see #getMemberName()
     */
    public Builder setMemberName(final String memberName) {
      if (isBlank(memberName)) {
        throw new IllegalArgumentException(
            String.format("The %s member name must be specified.",
                "Locator"));
      }
      this.memberName = memberName;
      return this;
    }

    /**
     * Gets the process ID (PID) of the running Locator indicated by the user as an argument to the
     * LocatorLauncher. This PID is used by the Locator launcher to determine the Locator's status,
     * or invoke shutdown on the Locator.
     *
     * @return a user specified Integer value indicating the process ID of the running Locator.
     * @see #setPid(Integer)
     */
    public Integer getPid() {
      return this.pid;
    }

    /**
     * Sets the process ID (PID) of the running Locator indicated by the user as an argument to the
     * LocatorLauncher. This PID will be used by the Locator launcher to determine the Locator's
     * status, or invoke shutdown on the Locator.
     *
     * @param pid a user specified Integer value indicating the process ID of the running Locator.
     * @return this Builder instance.
     * @throws IllegalArgumentException if the process ID (PID) is not valid (greater than zero if
     *         not null).
     * @see #getPid()
     */
    public Builder setPid(final Integer pid) {
      if (pid != null && pid < 0) {
        throw new IllegalArgumentException(
            "A process ID (PID) must be a non-negative integer value.");
      }
      this.pid = pid;
      return this;
    }

    boolean isPortSpecified() {
      return (this.port != null);
    }

    /**
     * Gets the port number used by the Locator to listen for client requests. If the port was not
     * specified, then the default Locator port (10334) is returned.
     *
     * @return the specified Locator port or the default port if unspecified.
     * @see #setPort(Integer)
     */
    public Integer getPort() {
      return port != null ? port : getDefaultLocatorPort();
    }

    /**
     * Sets the port number used by the Locator to listen for client requests. The port number must
     * be between 1 and 65535 inclusive.
     *
     * @param port an Integer value indicating the port used by the Locator to listen for client
     *        requests.
     * @return this Builder instance.
     * @throws IllegalArgumentException if the port number is not valid.
     * @see #getPort()
     */
    public Builder setPort(final Integer port) {
      // NOTE if the user were to specify a port number of 0, then java.net.ServerSocket will pick
      // an ephemeral port
      // to bind the socket, which we do not want.
      if (port != null && (port < 0 || port > 65535)) {
        throw new IllegalArgumentException(
            String.format(
                "The port on which the %s will listen must be between 1 and 65535 inclusive.",
                "Locator"));
      }
      this.port = port;
      return this;
    }

    /**
     * Determines whether the new instance of LocatorLauncher will redirect output to system logs
     * when starting a Locator.
     *
     * @return a boolean value indicating if output will be redirected to system logs when starting
     *         a Locator
     * @see #setRedirectOutput(Boolean)
     */
    public Boolean getRedirectOutput() {
      return this.redirectOutput;
    }

    /**
     * Determines whether redirecting of output has been enabled.
     *
     * @return a boolean indicating if redirecting of output was enabled.
     */
    private boolean isRedirectingOutput() {
      return Boolean.TRUE.equals(getRedirectOutput());
    }

    /**
     * Sets whether the new instance of LocatorLauncher will redirect output to system logs when
     * starting a Locator.
     *
     * @param redirectOutput a boolean value indicating if output will be redirected to system logs
     *        when starting a Locator.
     * @return this Builder instance.
     * @see #getRedirectOutput()
     */
    public Builder setRedirectOutput(final Boolean redirectOutput) {
      this.redirectOutput = redirectOutput;
      return this;
    }

    boolean isWorkingDirectorySpecified() {
      return isNotBlank(this.workingDirectory);
    }

    /**
     * Gets the working directory pathname in which the Locator will be ran. If the directory is
     * unspecified, then working directory defaults to the current directory.
     *
     * @return a String indicating the working directory pathname.
     * @see #setWorkingDirectory(String)
     */
    public String getWorkingDirectory() {
      return tryGetCanonicalPathElseGetAbsolutePath(
          new File(defaultIfBlank(this.workingDirectory, DEFAULT_WORKING_DIRECTORY)));
    }

    /**
     * Sets the working directory in which the Locator will be ran. This also the directory in which
     * all Locator files (such as log and license files) will be written. If the directory is
     * unspecified, then the working directory defaults to the current directory.
     *
     * @param workingDirectory a String indicating the pathname of the directory in which the
     *        Locator will be ran.
     * @return this Builder instance.
     * @throws IllegalArgumentException wrapping a FileNotFoundException if the working directory
     *         pathname cannot be found.
     * @see #getWorkingDirectory()
     * @see java.io.FileNotFoundException
     */
    public Builder setWorkingDirectory(final String workingDirectory) {
      if (!new File(defaultIfBlank(workingDirectory, DEFAULT_WORKING_DIRECTORY)).isDirectory()) {
        throw new IllegalArgumentException(
            String.format(AbstractLauncher.WORKING_DIRECTORY_NOT_FOUND_ERROR_MESSAGE,
                "Locator"),
            new FileNotFoundException(workingDirectory));
      }
      this.workingDirectory = workingDirectory;
      return this;
    }

    /**
     * Sets a GemFire Distributed System Property.
     *
     * @param propertyName a String indicating the name of the GemFire Distributed System property
     *        as described in {@link ConfigurationProperties}
     * @param propertyValue a String value for the GemFire Distributed System property.
     * @return this Builder instance.
     */
    public Builder set(final String propertyName, final String propertyValue) {
      this.distributedSystemProperties.setProperty(propertyName, propertyValue);
      return this;
    }

    /**
     * Validates the configuration settings and properties of this Builder, ensuring that all
     * invariants have been met. Currently, the only invariant constraining the Builder is that the
     * user must specify the member name for the Locator in the GemFire distributed system as a
     * command-line argument, or by setting the memberName property programmatically using the
     * corresponding setter method. If the member name is not given, then the user must have
     * specified the pathname to the gemfire.properties file before validate is called. It is then
     * assumed, but not further validated, that the user has specified the Locator's member name in
     * the properties file.
     *
     * @throws IllegalStateException if the Builder is not properly configured.
     */
    protected void validate() {
      if (!isHelping()) {
        validateOnStart();
        validateOnStatus();
        validateOnStop();
        // no validation for 'version' required
      }
    }

    /**
     * Validates the arguments passed to the Builder when the 'start' command has been issued.
     *
     * @see org.apache.geode.distributed.LocatorLauncher.Command#START
     */
    protected void validateOnStart() {
      if (Command.START == getCommand()) {
        if (isBlank(getMemberName())
            && !isSet(System.getProperties(), DistributionConfig.GEMFIRE_PREFIX + NAME)
            && !isSet(getDistributedSystemProperties(), NAME)
            && !isSet(loadGemFireProperties(DistributedSystem.getPropertyFileURL()), NAME)) {
          throw new IllegalStateException(
              String.format(
                  AbstractLauncher.MEMBER_NAME_ERROR_MESSAGE,
                  "Locator", "Locator"));
        }

        if (!CURRENT_DIRECTORY.equalsIgnoreCase(getWorkingDirectory())) {
          throw new IllegalStateException(
              String.format(
                  AbstractLauncher.WORKING_DIRECTORY_OPTION_NOT_VALID_ERROR_MESSAGE,
                  "Locator", "Locator"));
        }
      }
    }

    /**
     * Validates the arguments passed to the Builder when the 'status' command has been issued.
     *
     * @see org.apache.geode.distributed.LocatorLauncher.Command#STATUS
     */
    protected void validateOnStatus() {
      if (Command.STATUS == getCommand()) {
      }
    }

    /**
     * Validates the arguments passed to the Builder when the 'stop' command has been issued.
     *
     * @see org.apache.geode.distributed.LocatorLauncher.Command#STOP
     */
    protected void validateOnStop() {
      if (Command.STOP == getCommand()) {
      }
    }

    /**
     * Validates the Builder configuration settings and then constructs an instance of the
     * LocatorLauncher class to invoke operations on a GemFire Locator.
     *
     * @return a newly constructed instance of LocatorLauncher configured with this Builder.
     * @see #validate()
     * @see org.apache.geode.distributed.LocatorLauncher
     */
    public LocatorLauncher build() {
      validate();
      return new LocatorLauncher(this);
    }
  }

  /**
   * An enumerated type representing valid commands to the Locator launcher.
   */
  public enum Command {
    START("start", "bind-address", "hostname-for-clients", "port", "force", "debug", "help"),
    STATUS("status", "bind-address", "port", "member", "pid", "dir", "debug", "help"),
    STOP("stop", "member", "pid", "dir", "debug", "help"),
    VERSION("version"),
    UNSPECIFIED("unspecified");

    private final List<String> options;

    private final String name;

    Command(final String name, final String... options) {
      assert isNotBlank(name) : "The name of the locator launcher command must be specified!";
      this.name = name;
      this.options = (options != null ? Collections.unmodifiableList(Arrays.asList(options))
          : Collections.emptyList());
    }

    /**
     * Determines whether the specified name refers to a valid Locator launcher command, as defined
     * by this enumerated type.
     *
     * @param name a String value indicating the potential name of a Locator launcher command.
     * @return a boolean indicating whether the specified name for a Locator launcher command is
     *         valid.
     */
    public static boolean isCommand(final String name) {
      return (valueOfName(name) != null);
    }

    /**
     * Determines whether the given Locator launcher command has been properly specified. The
     * command is deemed unspecified if the reference is null or the Command is UNSPECIFIED.
     *
     * @param command the Locator launcher command.
     * @return a boolean value indicating whether the Locator launcher command is unspecified.
     * @see Command#UNSPECIFIED
     */
    public static boolean isUnspecified(final Command command) {
      return (command == null || command.isUnspecified());
    }

    /**
     * Looks up a Locator launcher command by name. The equality comparison on name is
     * case-insensitive.
     *
     * @param name a String value indicating the name of the Locator launcher command.
     * @return an enumerated type representing the command name or null if the no such command with
     *         the specified name exists.
     */
    public static Command valueOfName(final String name) {
      for (Command command : values()) {
        if (command.getName().equalsIgnoreCase(name)) {
          return command;
        }
      }

      return null;
    }

    /**
     * Gets the name of the Locator launcher command.
     *
     * @return a String value indicating the name of the Locator launcher command.
     */
    public String getName() {
      return this.name;
    }

    /**
     * Gets a set of valid options that can be used with the Locator launcher command when used from
     * the command-line.
     *
     * @return a Set of Strings indicating the names of the options available to the Locator
     *         launcher command.
     */
    public List<String> getOptions() {
      return this.options;
    }

    /**
     * Determines whether this Locator launcher command has the specified command-line option.
     *
     * @param option a String indicating the name of the command-line option to this command.
     * @return a boolean value indicating whether this command has the specified named command-line
     *         option.
     */
    public boolean hasOption(final String option) {
      return getOptions().contains(lowerCase(option));
    }

    /**
     * Convenience method for determining whether this is the UNSPECIFIED Locator launcher command.
     *
     * @return a boolean indicating if this command is UNSPECIFIED.
     * @see #UNSPECIFIED
     */
    public boolean isUnspecified() {
      return UNSPECIFIED == this;
    }

    /**
     * Gets the String representation of this Locator launcher command.
     *
     * @return a String value representing this Locator launcher command.
     */
    @Override
    public String toString() {
      return getName();
    }
  }

  /**
   * The LocatorState is an immutable type representing the state of the specified Locator at any
   * given moment in time. The state of the Locator is assessed at the exact moment an instance of
   * this class is constructed.
   *
   * @see org.apache.geode.distributed.AbstractLauncher.ServiceState
   */
  public static class LocatorState extends ServiceState<String> {

    /**
     * Unmarshals a LocatorState instance from the JSON String.
     *
     * @return a LocatorState value unmarshalled from the JSON String.
     */
    public static LocatorState fromJson(final String json) {
      try {
        final JsonNode jsonObject = new ObjectMapper().readTree(json);

        final Status status = Status.valueOfDescription(jsonObject.get(JSON_STATUS).asText());

        final List<String> jvmArguments = JsonUtil.toStringList(jsonObject.get(JSON_JVMARGUMENTS));

        return new LocatorState(status, jsonObject.get(JSON_STATUSMESSAGE).asText(),
            jsonObject.get(JSON_TIMESTAMP).asLong(), jsonObject.get(JSON_LOCATION).asText(),
            jsonObject.get(JSON_PID).asInt(), jsonObject.get(JSON_UPTIME).asLong(),
            jsonObject.get(JSON_WORKINGDIRECTORY).asText(), jvmArguments,
            jsonObject.get(JSON_CLASSPATH).asText(), jsonObject.get(JSON_GEMFIREVERSION).asText(),
            jsonObject.get(JSON_JAVAVERSION).asText(), jsonObject.get(JSON_LOGFILE).asText(),
            jsonObject.get(JSON_HOST).asText(), jsonObject.get(JSON_PORT).asText(),
            jsonObject.get(JSON_MEMBERNAME).asText());
      } catch (Exception e) {
        throw new IllegalArgumentException(
            "Unable to create LocatorStatus from JSON: ".concat(json), e);
      }
    }

    public static LocatorState fromDirectory(final String workingDirectory,
        final String memberName) {
      LocatorState locatorState =
          new LocatorLauncher.Builder().setWorkingDirectory(workingDirectory).build().status();

      if (ObjectUtils.equals(locatorState.getMemberName(), memberName)) {
        return locatorState;
      }

      return new LocatorState(new LocatorLauncher.Builder().build(), Status.NOT_RESPONDING);
    }

    public LocatorState(final LocatorLauncher launcher, final Status status) {
      // if status is NOT_RESPONDING then this is executing inside the JVM asking for the status;
      // pid etc will be set according to the caller's JVM instead
      this(status, launcher.statusMessage, System.currentTimeMillis(), launcher.getId(),
          identifyPid(), ManagementFactory.getRuntimeMXBean().getUptime(),
          launcher.getWorkingDirectory(), ManagementFactory.getRuntimeMXBean().getInputArguments(),
          System.getProperty("java.class.path"), GemFireVersion.getGemFireVersion(),
          System.getProperty("java.version"), getLogFileCanonicalPath(launcher),
          launcher.getBindAddressAsString(), launcher.getPortAsString(), launcher.getMemberName());
    }

    public LocatorState(final LocatorLauncher launcher, final Status status,
        final String errorMessage) {
      this(status, // status
          errorMessage, // statusMessage
          System.currentTimeMillis(), // timestamp
          getLocatorLocation(launcher), // locatorLocation
          null, // pid
          0L, // uptime
          launcher.getWorkingDirectory(), // workingDirectory
          ManagementFactory.getRuntimeMXBean().getInputArguments(), // jvmArguments
          null, // classpath
          GemFireVersion.getGemFireVersion(), // gemfireVersion
          System.getProperty("java.version"), // javaVersion
          null, // logFile
          launcher.getBindAddressAsString(), // host
          launcher.getPortAsString(), // port
          null);// memberName
    }

    /*
     * Guards against throwing NPEs due to incorrect or missing host information while constructing
     * error states
     */
    private static String getLocatorLocation(LocatorLauncher launcher) {
      if (launcher.getPort() == null) {
        return launcher.getId();
      }
      if (launcher.getBindAddress() == null) {
        return HostUtils.getLocatorId(HostUtils.getLocalHost(), launcher.getPort());
      }
      return HostUtils.getLocatorId(launcher.getBindAddressAsString(), launcher.getPort());
    }

    private static String getBindAddressAsString(LocatorLauncher launcher) {
      if (InternalLocator.hasLocator()) {
        final InternalLocator locator = InternalLocator.getLocator();
        final InetAddress bindAddress = locator.getBindAddress();
        if (bindAddress != null) {
          if (isNotBlank(bindAddress.getHostAddress())) {
            return bindAddress.getHostAddress();
          }
        }
      }
      return launcher.getBindAddressAsString();
    }

    private static String getLogFileCanonicalPath(LocatorLauncher launcher) {
      if (InternalLocator.hasLocator()) {
        final InternalLocator locator = InternalLocator.getLocator();
        final File logFile = locator.getLogFile();

        if (logFile != null && logFile.isFile()) {
          final String logFileCanonicalPath = tryGetCanonicalPathElseGetAbsolutePath(logFile);
          if (isNotBlank(logFileCanonicalPath)) { // this is probably not need but a
            // safe check none-the-less.
            return logFileCanonicalPath;
          }
        }
      }
      return launcher.getLogFileCanonicalPath();
    }

    private static String getPortAsString(LocatorLauncher launcher) {
      if (InternalLocator.hasLocator()) {
        final InternalLocator locator = InternalLocator.getLocator();
        final String portAsString = String.valueOf(locator.getPort());
        if (isNotBlank(portAsString)) {
          return portAsString;
        }
      }
      return launcher.getPortAsString();
    }

    protected LocatorState(final Status status, final String statusMessage, final long timestamp,
        final String locatorLocation, final Integer pid, final Long uptime,
        final String workingDirectory, final List<String> jvmArguments, final String classpath,
        final String gemfireVersion, final String javaVersion, final String logFile,
        final String host, final String port, final String memberName) {
      super(status, statusMessage, timestamp, locatorLocation, pid, uptime, workingDirectory,
          jvmArguments, classpath, gemfireVersion, javaVersion, logFile, host, port, memberName);
    }

    private LocatorState(final LocatorLauncher launcher, final Status status,
        final LocatorStatusResponse response) {
      this(status, launcher.statusMessage, System.currentTimeMillis(), launcher.getId(),
          response.getPid(), response.getUptime(), response.getWorkingDirectory(),
          response.getJvmArgs(), response.getClasspath(), response.getGemFireVersion(),
          response.getJavaVersion(), response.getLogFile(), response.getHost(),
          String.valueOf(response.getPort()), response.getName());
    }

    @Override
    protected String getServiceName() {
      return LOCATOR_SERVICE_NAME;
    }
  }

}
