/*
 * 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.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.FileControllableProcess;
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.logging.internal.log4j.api.LogService;
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 FileControllableProcess(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;
    }

    /**
     * add the properties in the Gemfire Distributed System Property
     *
     * @param properties a property object that holds one or more Gemfire Distributed System
     *        properties as described in {@link ConfigurationProperties}
     * @return this Builder instance
     * @since Geode 1.12
     */
    public Builder set(Properties properties) {
      this.distributedSystemProperties.putAll(properties);
      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;
    }
  }

}
