/*
 * 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.hadoop.service.launcher;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.service.Service;
import org.apache.hadoop.util.ExitCodeProvider;
import org.apache.hadoop.util.ExitUtil;
import org.apache.hadoop.util.GenericOptionsParser;
import org.apache.hadoop.util.StringUtils;

/**
 * A class to launch any YARN service by name.
 *
 * It's designed to be subclassed for custom entry points.
 *
 * Workflow:
 * <ol>
 *   <li>An instance of the class is created. It must be of the type
 *   {@link Service}</li>
 *   <li>If it implements
 *   {@link LaunchableService#bindArgs(Configuration, List)},
 *    it is given the binding args off the CLI after all general configuration
 *    arguments have been stripped.</li>
 *   <li>Its {@link Service#init(Configuration)} and {@link Service#start()}
 *   methods are called.</li>
 *   <li>If it implements it, {@link LaunchableService#execute()}
 *   is called and its return code used as the exit code.</li>
 *   <li>Otherwise: it waits for the service to stop, assuming that the
 *   {@link Service#start()} method spawns one or more thread
 *   to perform work</li>
 *   <li>If any exception is raised and provides an exit code,
 *   that is, it implements {@link ExitCodeProvider},
 *   the return value of {@link ExitCodeProvider#getExitCode()},
 *   becomes the exit code of the command.</li>
 * </ol>
 * Error and warning messages are logged to {@code stderr}.
 * 
 * @param <S> service class to cast the generated service to.
 */
@SuppressWarnings("UseOfSystemOutOrSystemErr")
public class ServiceLauncher<S extends Service>
    implements LauncherExitCodes, LauncherArguments,
    Thread.UncaughtExceptionHandler {

  /**
   * Logger.
   */
  private static final Logger LOG =
      LoggerFactory.getLogger(ServiceLauncher.class);

  /**
   * Priority for the shutdown hook: {@value}.
   */
  protected static final int SHUTDOWN_PRIORITY = 30;

  /**
   * The name of this class.
   */
  public static final String NAME = "ServiceLauncher";

  protected static final String USAGE_NAME = "Usage: " + NAME;
  protected static final String USAGE_SERVICE_ARGUMENTS =
      "service-classname <service arguments>";

  /**
   * Usage message.
   *
   * Text: {@value}
   */
  public static final String USAGE_MESSAGE =
      USAGE_NAME
          + " [" + ARG_CONF_PREFIXED + " <conf file>]"
          + " [" + ARG_CONFCLASS_PREFIXED + " <configuration classname>]"
          + " "  + USAGE_SERVICE_ARGUMENTS;

  /**
   * The shutdown time on an interrupt: {@value}.
   */
  private static final int SHUTDOWN_TIME_ON_INTERRUPT = 30 * 1000;

  /**
   * The launched service.
   *
   * Invalid until the service has been created. 
   */
  private volatile S service;
  
  /**
   * Exit code of the service.
   *
   * Invalid until a service has
   * executed or stopped, depending on the service type.
   */
  private int serviceExitCode;
  
  /**
   * Any exception raised during execution.
   */
  private ExitUtil.ExitException serviceException;

  /**
   * The interrupt escalator for the service.
   */
  private InterruptEscalator interruptEscalator;

  /**
   * Configuration used for the service.
   */
  private Configuration configuration;

  /**
   * Text description of service for messages.
   */
  private String serviceName;

  /**
   * Classname for the service to create.; empty string otherwise.
   */
  private String serviceClassName = "";

  /**
   * List of the standard configurations to create (and so load in properties).
   * The values are Hadoop, HDFS and YARN configurations.
   */
  protected static final String[] DEFAULT_CONFIGS = {
      "org.apache.hadoop.conf.Configuration",
      "org.apache.hadoop.hdfs.HdfsConfiguration",
      "org.apache.hadoop.yarn.conf.YarnConfiguration"
  };

  /**
   * List of classnames to load to configuration before creating a
   * {@link Configuration} instance.
   */
  private List<String> confClassnames = new ArrayList<>(DEFAULT_CONFIGS.length);

  /**
   * URLs of configurations to load into the configuration instance created.
   */
  private List<URL> confResourceUrls = new ArrayList<>(1);

  /** Command options. Preserved for usage statements. */
  private Options commandOptions;

  /**
   * Create an instance of the launcher.
   * @param serviceClassName classname of the service
   */
  public ServiceLauncher(String serviceClassName) {
    this(serviceClassName, serviceClassName);
  }

  /**
   * Create an instance of the launcher.
   * @param serviceName name of service for text messages
   * @param serviceClassName classname of the service
   */
  public ServiceLauncher(String serviceName, String serviceClassName) {
    this.serviceClassName = serviceClassName;
    this.serviceName = serviceName;
    // set up initial list of configurations
    confClassnames.addAll(Arrays.asList(DEFAULT_CONFIGS));
  }

  /**
   * Get the service.
   *
   * Null until
   * {@link #coreServiceLaunch(Configuration, List, boolean, boolean)}
   * has completed.
   * @return the service
   */
  public final S getService() {
    return service;
  }

  /**
   * Setter is to give subclasses the ability to manipulate the service.
   * @param s the new service
   */
  protected void setService(S s) {
    this.service = s;
  }

  /**
   * Get the configuration constructed from the command line arguments.
   * @return the configuration used to create the service
   */
  public final Configuration getConfiguration() {
    return configuration;
  }

  /**
   * The exit code from a successful service execution.
   * @return the exit code. 
   */
  public final int getServiceExitCode() {
    return serviceExitCode;
  }

  /**
   * Get the exit exception used to end this service.
   * @return an exception, which will be null until the service
   * has exited (and {@code System.exit} has not been called)
   */
  public final ExitUtil.ExitException getServiceException() {
    return serviceException;
  }

  /**
   * Probe for service classname being defined.
   * @return true if the classname is set
   */
  private boolean isClassnameDefined() {
    return serviceClassName != null && !serviceClassName.isEmpty();
  }

  @Override
  public String toString() {
    final StringBuilder sb = new StringBuilder("\"ServiceLauncher for \"");
    sb.append(serviceName);
    if (isClassnameDefined()) {
      sb.append(", serviceClassName='").append(serviceClassName).append('\'');
    }
    if (service != null) {
      sb.append(", service=").append(service);
    }
    return sb.toString();
  }

  /**
   * Launch the service and exit.
   *
   * <ol>
   * <li>Parse the command line.</li> 
   * <li>Build the service configuration from it.</li>
   * <li>Start the service.</li>.
   * <li>If it is a {@link LaunchableService}: execute it</li>
   * <li>Otherwise: wait for it to finish.</li>
   * <li>Exit passing the status code to the {@link #exit(int, String)}
   * method.</li>
   * </ol>
   * @param args arguments to the service. {@code arg[0]} is 
   * assumed to be the service classname.
   */
  public void launchServiceAndExit(List<String> args) {
    StringBuilder builder = new StringBuilder();
    for (String arg : args) {
      builder.append('"').append(arg).append("\" ");
    }
    String argumentString = builder.toString();
    if (LOG.isDebugEnabled()) {
      LOG.debug(startupShutdownMessage(serviceName, args));
      LOG.debug(argumentString);
    }
    registerFailureHandling();
    // set up the configs, using reflection to push in the -site.xml files
    loadConfigurationClasses();
    Configuration conf = createConfiguration();
    for (URL resourceUrl : confResourceUrls) {
      conf.addResource(resourceUrl);
    }
    bindCommandOptions();
    ExitUtil.ExitException exitException;
    try {
      List<String> processedArgs = extractCommandOptions(conf, args);
      exitException = launchService(conf, processedArgs, true, true);
    } catch (ExitUtil.ExitException e) {
      exitException = e;
      noteException(exitException);
    }
    if (exitException.getExitCode() != 0) {
      // something went wrong. Print the usage and commands
      System.err.println(getUsageMessage());
      System.err.println("Command: " + argumentString);
    }
    System.out.flush();
    System.err.flush();
    exit(exitException);
  }

  /**
   * Set the {@link #commandOptions} field to the result of
   * {@link #createOptions()}; protected for subclasses and test access.
   */
  protected void bindCommandOptions() {
    commandOptions = createOptions();
  }

  /**
   * Record that an Exit Exception has been raised.
   * Save it to {@link #serviceException}, with its exit code in
   * {@link #serviceExitCode}
   * @param exitException exception
   */
  void noteException(ExitUtil.ExitException exitException) {
    LOG.debug("Exception raised", exitException);
    serviceExitCode = exitException.getExitCode();
    serviceException = exitException;
  }

  /**
   * Get the usage message, ideally dynamically.
   * @return the usage message
   */
  protected String getUsageMessage() {
    String message =   USAGE_MESSAGE;
    if (commandOptions != null) {
      message = USAGE_NAME
          + " " + commandOptions.toString()
          + " " + USAGE_SERVICE_ARGUMENTS;
    }
    return message;
  }

  /**
   * Override point: create an options instance to combine with the 
   * standard options set.
   * <i>Important. Synchronize uses of {@link OptionBuilder}</i>
   * with {@code OptionBuilder.class}
   * @return the new options
   */
  @SuppressWarnings("static-access")
  protected Options createOptions() {
    synchronized (OptionBuilder.class) {
      Options options = new Options();
      Option oconf = OptionBuilder.withArgName("configuration file")
          .hasArg()
          .withDescription("specify an application configuration file")
          .withLongOpt(ARG_CONF)
          .create(ARG_CONF_SHORT);
      Option confclass = OptionBuilder.withArgName("configuration classname")
          .hasArg()
          .withDescription(
              "Classname of a Hadoop Configuration subclass to load")
          .withLongOpt(ARG_CONFCLASS)
          .create(ARG_CONFCLASS_SHORT);
      Option property = OptionBuilder.withArgName("property=value")
          .hasArg()
          .withDescription("use value for given property")
          .create('D');
      options.addOption(oconf);
      options.addOption(property);
      options.addOption(confclass);
      return options;
    }
  }

  /**
   * Override point: create the base configuration for the service.
   *
   * Subclasses can override to create HDFS/YARN configurations etc.
   * @return the configuration to use as the service initializer.
   */
  protected Configuration createConfiguration() {
    return new Configuration();
  }

  /**
   * Override point: Get a list of configuration classes to create.
   * @return the array of configs to attempt to create. If any are off the
   * classpath, that is logged
   */
  @SuppressWarnings("ReturnOfCollectionOrArrayField")
  protected List<String> getConfigurationsToCreate() {
    return confClassnames;
  }

  /**
   * This creates all the configurations defined by
   * {@link #getConfigurationsToCreate()} , ensuring that
   * the resources have been pushed in.
   * If one cannot be loaded it is logged and the operation continues
   * except in the case that the class does load but it isn't actually
   * a subclass of {@link Configuration}.
   * @throws ExitUtil.ExitException if a loaded class is of the wrong type
   */
  @VisibleForTesting
  public int loadConfigurationClasses() {
    List<String> toCreate = getConfigurationsToCreate();
    int loaded = 0;
    for (String classname : toCreate) {
      try {
        Class<?> loadClass = getClassLoader().loadClass(classname);
        Object instance = loadClass.getConstructor().newInstance();
        if (!(instance instanceof Configuration)) {
          throw new ExitUtil.ExitException(EXIT_SERVICE_CREATION_FAILURE,
              "Could not create " + classname
              + " because it is not a Configuration class/subclass");
        }
        loaded++;
      } catch (ClassNotFoundException e) {
        // class could not be found -implies it is not on the current classpath
        LOG.debug("Failed to load {} because it is not on the classpath",
            classname);
      } catch (ExitUtil.ExitException e) {
        // rethrow
        throw e;
      } catch (Exception e) {
        // any other exception
        LOG.info("Failed to create {}", classname, e);
      }
    }
    return loaded;
  }

  /**
   * Launch a service catching all exceptions and downgrading them to exit codes
   * after logging.
   *
   * Sets {@link #serviceException} to this value.
   * @param conf configuration to use
   * @param processedArgs command line after the launcher-specific arguments
   * have been stripped out.
   * @param addShutdownHook should a shutdown hook be added to terminate
   * this service on shutdown. Tests should set this to false.
   * @param execute execute/wait for the service to stop.
   * @return an exit exception, which will have a status code of 0 if it worked
   */
  @VisibleForTesting
  public ExitUtil.ExitException launchService(Configuration conf,
      List<String> processedArgs,
      boolean addShutdownHook,
      boolean execute) {
    
    ExitUtil.ExitException exitException;
    
    try {
      int exitCode = coreServiceLaunch(conf, processedArgs, addShutdownHook,
          execute);
      if (service != null) {
        // check to see if the service failed
        Throwable failure = service.getFailureCause();
        if (failure != null) {
          // the service exited with a failure.
          // check what state it is in
          Service.STATE failureState = service.getFailureState();
          if (failureState == Service.STATE.STOPPED) {
            // the failure occurred during shutdown, not important enough
            // to bother the user as it may just scare them
            LOG.debug("Failure during shutdown: {} ", failure, failure);
          } else {
            //throw it for the catch handlers to deal with
            throw failure;
          }
        }
      }
      String name = getServiceName();

      if (exitCode == 0) {
        exitException = new ServiceLaunchException(exitCode,
            "%s succeeded",
            name);
      } else {
        exitException = new ServiceLaunchException(exitCode,
            "%s failed ", name);
      }
      // either the service succeeded, or an error raised during shutdown, 
      // which we don't worry that much about
    } catch (ExitUtil.ExitException ee) {
      // exit exceptions are passed through unchanged
      exitException = ee;
    } catch (Throwable thrown) {
      exitException = convertToExitException(thrown);
    }
    noteException(exitException);
    return exitException;
  }

  /**
   * Launch the service.
   *
   * All exceptions that occur are propagated upwards.
   *
   * If the method returns a status code, it means that it got as far starting
   * the service, and if it implements {@link LaunchableService}, that the 
   * method {@link LaunchableService#execute()} has completed. 
   *
   * After this method returns, the service can be retrieved returned by
   * {@link #getService()}.
   *
   * @param conf configuration
   * @param processedArgs arguments after the configuration parameters
   * have been stripped out.
   * @param addShutdownHook should a shutdown hook be added to terminate
   * this service on shutdown. Tests should set this to false.
   * @param execute execute/wait for the service to stop
   * @throws ClassNotFoundException classname not on the classpath
   * @throws IllegalAccessException not allowed at the class
   * @throws InstantiationException not allowed to instantiate it
   * @throws InterruptedException thread interrupted
   * @throws ExitUtil.ExitException any exception defining the status code.
   * @throws Exception any other failure -if it implements
   * {@link ExitCodeProvider} then it defines the exit code for any
   * containing exception
   */

  protected int coreServiceLaunch(Configuration conf,
      List<String> processedArgs,
      boolean addShutdownHook,
      boolean execute) throws Exception {

    // create the service instance
    instantiateService(conf);
    ServiceShutdownHook shutdownHook = null;

    // and the shutdown hook if requested
    if (addShutdownHook) {
      shutdownHook = new ServiceShutdownHook(service);
      shutdownHook.register(SHUTDOWN_PRIORITY);
    }
    String name = getServiceName();
    LOG.debug("Launched service {}", name);
    LaunchableService launchableService = null;

    if (service instanceof LaunchableService) {
      // it's a LaunchableService, pass in the conf and arguments before init)
      LOG.debug("Service {} implements LaunchableService", name);
      launchableService = (LaunchableService) service;
      if (launchableService.isInState(Service.STATE.INITED)) {
        LOG.warn("LaunchableService {}" 
            + " initialized in constructor before CLI arguments passed in",
            name);
      }
      Configuration newconf = launchableService.bindArgs(configuration,
          processedArgs);
      if (newconf != null) {
        configuration = newconf;
      }
    }

    //some class constructors init; here this is picked up on.
    if (!service.isInState(Service.STATE.INITED)) {
      service.init(configuration);
    }
    int exitCode;

    try {
      // start the service
      service.start();
      exitCode = EXIT_SUCCESS;
      if (execute && service.isInState(Service.STATE.STARTED)) {
        if (launchableService != null) {
          // assume that runnable services are meant to run from here
          try {
            exitCode = launchableService.execute();
            LOG.debug("Service {} execution returned exit code {}",
                name, exitCode);
          } finally {
            // then stop the service
            service.stop();
          }
        } else {
          //run the service until it stops or an interrupt happens
          // on a different thread.
          LOG.debug("waiting for service threads to terminate");
          service.waitForServiceToStop(0);
        }
      }
    } finally {
      if (shutdownHook != null) {
        shutdownHook.unregister();
      }
    }
    return exitCode;
  }

  /**
   * Instantiate the service defined in {@code serviceClassName}.
   *
   * Sets the {@code configuration} field
   * to the the value of {@code conf},
   * and the {@code service} field to the service created.
   *
   * @param conf configuration to use
   */
  @SuppressWarnings("unchecked")
  public Service instantiateService(Configuration conf) {
    Preconditions.checkArgument(conf != null, "null conf");
    Preconditions.checkArgument(serviceClassName != null,
        "null service classname");
    Preconditions.checkArgument(!serviceClassName.isEmpty(),
        "undefined service classname");
    configuration = conf;

    // Instantiate the class. this requires the service to have a public
    // zero-argument or string-argument constructor
    Object instance;
    try {
      Class<?> serviceClass = getClassLoader().loadClass(serviceClassName);
      try {
        instance = serviceClass.getConstructor().newInstance();
      } catch (NoSuchMethodException noEmptyConstructor) {
        // no simple constructor, fall back to a string
        LOG.debug("No empty constructor {}", noEmptyConstructor,
            noEmptyConstructor);
        instance = serviceClass.getConstructor(String.class)
                               .newInstance(serviceClassName);
      }
    } catch (Exception e) {
      throw serviceCreationFailure(e);
    }
    if (!(instance instanceof Service)) {
      //not a service
      throw new ServiceLaunchException(
          LauncherExitCodes.EXIT_SERVICE_CREATION_FAILURE,
          "Not a service class: \"%s\"", serviceClassName);
    }

    // cast to the specific instance type of this ServiceLauncher
    service = (S) instance;
    return service;
  }

  /**
   * Convert an exception to an {@code ExitException}.
   *
   * This process may just be a simple pass through, otherwise a new
   * exception is created with an exit code, the text of the supplied
   * exception, and the supplied exception as an inner cause.
   * 
   * <ol>
   *   <li>If is already the right type, pass it through.</li>
   *   <li>If it implements {@link ExitCodeProvider#getExitCode()},
   *   the exit code is extracted and used in the new exception.</li>
   *   <li>Otherwise, the exit code
   *   {@link LauncherExitCodes#EXIT_EXCEPTION_THROWN} is used.</li>
   * </ol>
   *  
   * @param thrown the exception thrown
   * @return an {@code ExitException} with a status code
   */
  protected static ExitUtil.ExitException convertToExitException(
      Throwable thrown) {
    ExitUtil.ExitException exitException;
    // get the exception message
    String message = thrown.toString();
    int exitCode;
    if (thrown instanceof ExitCodeProvider) {
      // the exception provides a status code -extract it
      exitCode = ((ExitCodeProvider) thrown).getExitCode();
      message = thrown.getMessage();
      if (message == null) {
        // some exceptions do not have a message; fall back
        // to the string value.
        message = thrown.toString();
      }
    } else {
      // no exception code: use the default
      exitCode = EXIT_EXCEPTION_THROWN;
    }
    // construct the new exception with the original message and
    // an exit code
    exitException = new ServiceLaunchException(exitCode, message);
    exitException.initCause(thrown);
    return exitException;
  }

  /**
   * Generate an exception announcing a failure to create the service.
   * @param exception inner exception.
   * @return a new exception, with the exit code
   * {@link LauncherExitCodes#EXIT_SERVICE_CREATION_FAILURE}
   */
  protected ServiceLaunchException serviceCreationFailure(Exception exception) {
    return new ServiceLaunchException(EXIT_SERVICE_CREATION_FAILURE, exception);
  }
  
  /**
   * Override point: register this class as the handler for the control-C
   * and SIGINT interrupts.
   *
   * Subclasses can extend this with extra operations, such as
   * an exception handler:
   * <pre>
   *  Thread.setDefaultUncaughtExceptionHandler(
   *     new YarnUncaughtExceptionHandler());
   * </pre>
   */
  protected void registerFailureHandling() {
    try {
      interruptEscalator = new InterruptEscalator(this,
          SHUTDOWN_TIME_ON_INTERRUPT);
      interruptEscalator.register(IrqHandler.CONTROL_C);
      interruptEscalator.register(IrqHandler.SIGTERM);
    } catch (IllegalArgumentException e) {
      // downgrade interrupt registration to warnings
      LOG.warn("{}", e, e);
    }
    Thread.setDefaultUncaughtExceptionHandler(
        new HadoopUncaughtExceptionHandler(this));
  }

  /**
   * Handler for uncaught exceptions: terminate the service.
   * @param thread thread
   * @param exception exception
   */
  @Override
  public void uncaughtException(Thread thread, Throwable exception) {
    LOG.error("Uncaught exception in thread {} -exiting", thread, exception);
    exit(convertToExitException(exception));
  }

  /**
   * Get the service name via {@link Service#getName()}.
   *
   * If the service is not instantiated, the classname is returned instead.
   * @return the service name
   */
  public String getServiceName() {
    Service s = service;
    String name = null;
    if (s != null) {
      try {
        name = s.getName();
      } catch (Exception ignored) {
        // ignored
      }
    }
    if (name != null) {
      return "service " + name;
    } else {
      return "service " + serviceName;
    }
  }
  
  /**
   * Print a warning message.
   * <p>
   * This tries to log to the log's warn() operation.
   * If the log at that level is disabled it logs to system error
   * @param text warning text
   */
  protected void warn(String text) {
    if (LOG.isWarnEnabled()) {
      LOG.warn(text);
    } else {
      System.err.println(text);
    }
  }

  /**
   * Report an error. 
   * <p>
   * This tries to log to {@code LOG.error()}.
   * <p>
   * If that log level is disabled disabled the message
   * is logged to system error along with {@code thrown.toString()}
   * @param message message for the user
   * @param thrown the exception thrown
   */
  protected void error(String message, Throwable thrown) {
    String text = "Exception: " + message;
    if (LOG.isErrorEnabled()) {
      LOG.error(text, thrown);
    } else {
      System.err.println(text);
      if (thrown != null) {
        System.err.println(thrown.toString());
      }
    }
  }
  
  /**
   * Exit the JVM.
   *
   * This is method can be overridden for testing, throwing an 
   * exception instead. Any subclassed method MUST raise an 
   * {@code ExitException} instance/subclass.
   * The service launcher code assumes that after this method is invoked,
   * no other code in the same method is called.
   * @param exitCode code to exit
   */
  protected void exit(int exitCode, String message) {
    ExitUtil.terminate(exitCode, message);
  }

  /**
   * Exit the JVM using an exception for the exit code and message,
   * invoking {@link ExitUtil#terminate(ExitUtil.ExitException)}.
   *
   * This is the standard way a launched service exits.
   * An error code of 0 means success -nothing is printed.
   *
   * If {@link ExitUtil#disableSystemExit()} has been called, this
   * method will throw the exception.
   *
   * The method <i>may</i> be subclassed for testing
   * @param ee exit exception
   * @throws ExitUtil.ExitException if ExitUtil exceptions are disabled
   */
  protected void exit(ExitUtil.ExitException ee) {
    ExitUtil.terminate(ee);
  }

  /**
   * Override point: get the classloader to use.
   * @return the classloader for loading a service class.
   */
  protected ClassLoader getClassLoader() {
    return this.getClass().getClassLoader();
  }

  /**
   * Extract the command options and apply them to the configuration,
   * building an array of processed arguments to hand down to the service.
   *
   * @param conf configuration to update.
   * @param args main arguments. {@code args[0]}is assumed to be
   * the service classname and is skipped.
   * @return the remaining arguments
   * @throws ExitUtil.ExitException if JVM exiting is disabled.
   */
  public List<String> extractCommandOptions(Configuration conf,
      List<String> args) {
    int size = args.size();
    if (size <= 1) {
      return new ArrayList<>(0);
    }
    List<String> coreArgs = args.subList(1, size);

    return parseCommandArgs(conf, coreArgs);
  }

  /**
   * Parse the command arguments, extracting the service class as the last
   * element of the list (after extracting all the rest).
   *
   * The field {@link #commandOptions} field must already have been set.
   * @param conf configuration to use
   * @param args command line argument list
   * @return the remaining arguments
   * @throws ServiceLaunchException if processing of arguments failed
   */
  protected List<String> parseCommandArgs(Configuration conf,
      List<String> args) {
    Preconditions.checkNotNull(commandOptions,
        "Command options have not been created");
    StringBuilder argString = new StringBuilder(args.size() * 32);
    for (String arg : args) {
      argString.append("\"").append(arg).append("\" ");
    }
    LOG.debug("Command line: {}", argString);
    try {
      String[] argArray = args.toArray(new String[args.size()]);
      // parse this the standard way. This will
      // update the configuration in the parser, and potentially
      // patch the user credentials
      GenericOptionsParser parser = createGenericOptionsParser(conf, argArray);
      if (!parser.isParseSuccessful()) {
        throw new ServiceLaunchException(EXIT_COMMAND_ARGUMENT_ERROR,
            E_PARSE_FAILED + " %s", argString);
      }
      CommandLine line = parser.getCommandLine();
      List<String> remainingArgs = Arrays.asList(parser.getRemainingArgs());
      LOG.debug("Remaining arguments {}", remainingArgs);

      // Scan the list of configuration files
      // and bail out if they don't exist
      if (line.hasOption(ARG_CONF)) {
        String[] filenames = line.getOptionValues(ARG_CONF);
        verifyConfigurationFilesExist(filenames);
        // Add URLs of files as list of URLs to load
        for (String filename : filenames) {
          File file = new File(filename);
          LOG.debug("Configuration files {}", file);
          confResourceUrls.add(file.toURI().toURL());
        }
      }
      if (line.hasOption(ARG_CONFCLASS)) {
        // new resources to instantiate as configurations
        List<String> classnameList = Arrays.asList(
            line.getOptionValues(ARG_CONFCLASS));
        LOG.debug("Configuration classes {}", classnameList);
        confClassnames.addAll(classnameList);
      }
      // return the remainder
      return remainingArgs;
    } catch (IOException e) {
      // parsing problem: convert to a command argument error with
      // the original text
      throw new ServiceLaunchException(EXIT_COMMAND_ARGUMENT_ERROR, e);
    } catch (RuntimeException e) {
      // lower level issue such as XML parse failure
      throw new ServiceLaunchException(EXIT_COMMAND_ARGUMENT_ERROR,
          E_PARSE_FAILED + " %s : %s", argString, e);
    }
  }

  /**
   * Override point: create a generic options parser or subclass thereof.
   * @param conf Hadoop configuration
   * @param argArray array of arguments
   * @return a generic options parser to parse the arguments
   * @throws IOException on any failure
   */
  protected GenericOptionsParser createGenericOptionsParser(Configuration conf,
      String[] argArray) throws IOException {
    return new MinimalGenericOptionsParser(conf, commandOptions, argArray);
  }

  /**
   * Verify that all the specified filenames exist.
   * @param filenames a list of files
   * @throws ServiceLaunchException if a file is not found
   */
  protected void verifyConfigurationFilesExist(String[] filenames) {
    if (filenames == null) {
      return;
    }
    for (String filename : filenames) {
      File file = new File(filename);
      LOG.debug("Conf file {}", file.getAbsolutePath());
      if (!file.exists()) {
        // no configuration file
        throw new ServiceLaunchException(EXIT_NOT_FOUND,
            ARG_CONF_PREFIXED + ": configuration file not found: %s",
            file.getAbsolutePath());
      }
    }
  }

  /**
   * Build a log message for starting up and shutting down. 
   * @param classname the class of the server
   * @param args arguments
   */
  protected static String startupShutdownMessage(String classname,
      List<String> args) {
    final String hostname = NetUtils.getHostname();

    return StringUtils.createStartupShutdownMessage(classname, hostname,
        args.toArray(new String[args.size()]));
  }

  /**
   * Exit with a printed message. 
   * @param status status code
   * @param message message message to print before exiting
   * @throws ExitUtil.ExitException if exceptions are disabled
   */
  protected static void exitWithMessage(int status, String message) {
    ExitUtil.terminate(new ServiceLaunchException(status, message));
  }

  /**
   * Exit with the usage exit code {@link #EXIT_USAGE}
   * and message {@link #USAGE_MESSAGE}.
   * @throws ExitUtil.ExitException if exceptions are disabled
   */
  protected static void exitWithUsageMessage() {
    exitWithMessage(EXIT_USAGE, USAGE_MESSAGE);
  }

  /**
   * This is the JVM entry point for the service launcher.
   *
   * Converts the arguments to a list, then invokes {@link #serviceMain(List)}
   * @param args command line arguments.
   */
  public static void main(String[] args) {
    serviceMain(Arrays.asList(args));
  }

  /**
   * Varargs version of the entry point for testing and other in-JVM use.
   * Hands off to {@link #serviceMain(List)}
   * @param args command line arguments.
   */
  public static void serviceMain(String... args) {
    serviceMain(Arrays.asList(args));
  }

  /* ====================================================================== */
  /**
   * The real main function, which takes the arguments as a list.
   * Argument 0 MUST be the service classname
   * @param argsList the list of arguments
   */
  /* ====================================================================== */

  public static void serviceMain(List<String> argsList) {
    if (argsList.isEmpty()) {
      // no arguments: usage message
      exitWithUsageMessage();
    } else {
      ServiceLauncher<Service> serviceLauncher =
          new ServiceLauncher<>(argsList.get(0));
      serviceLauncher.launchServiceAndExit(argsList);
    }
  }

  /**
   * A generic options parser which does not parse any of the traditional
   * Hadoop options.
   */
  protected static class MinimalGenericOptionsParser
      extends GenericOptionsParser {
    public MinimalGenericOptionsParser(Configuration conf,
        Options options, String[] args) throws IOException {
      super(conf, options, args);
    }

    @Override
    protected Options buildGeneralOptions(Options opts) {
      return opts;
    }
  }
}
