You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by je...@apache.org on 2016/02/25 21:27:24 UTC

[36/50] [abbrv] incubator-geode git commit: Merge branch 'develop' into feature/GEODE-17

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5c01d5f4/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/LauncherLifecycleCommands.java
----------------------------------------------------------------------
diff --cc geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/LauncherLifecycleCommands.java
index 0000000,8eae00b..3ec52e3
mode 000000,100755..100755
--- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/LauncherLifecycleCommands.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/LauncherLifecycleCommands.java
@@@ -1,0 -1,2803 +1,2816 @@@
+ /*
+  * 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 com.gemstone.gemfire.management.internal.cli.commands;
+ 
+ import java.awt.Desktop;
+ import java.io.BufferedReader;
+ import java.io.BufferedWriter;
+ import java.io.File;
+ import java.io.FileFilter;
+ import java.io.FileNotFoundException;
+ import java.io.FileReader;
+ import java.io.FileWriter;
+ import java.io.IOException;
+ import java.io.InputStream;
+ import java.io.InputStreamReader;
+ import java.net.InetAddress;
+ import java.net.MalformedURLException;
+ import java.net.URI;
+ import java.net.UnknownHostException;
+ import java.util.ArrayList;
+ import java.util.Arrays;
+ import java.util.Collections;
+ import java.util.EmptyStackException;
+ import java.util.HashMap;
+ import java.util.HashSet;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Properties;
+ import java.util.Set;
+ import java.util.Stack;
+ import java.util.TreeSet;
+ import java.util.concurrent.TimeUnit;
+ import java.util.concurrent.atomic.AtomicReference;
+ 
+ import javax.management.MalformedObjectNameException;
+ import javax.management.ObjectName;
+ import javax.management.Query;
+ import javax.management.QueryExp;
+ import javax.net.ssl.SSLException;
+ import javax.net.ssl.SSLHandshakeException;
+ 
+ import com.gemstone.gemfire.GemFireException;
+ import com.gemstone.gemfire.SystemFailure;
+ import com.gemstone.gemfire.cache.server.CacheServer;
+ import com.gemstone.gemfire.distributed.AbstractLauncher;
+ import com.gemstone.gemfire.distributed.AbstractLauncher.ServiceState;
+ import com.gemstone.gemfire.distributed.AbstractLauncher.Status;
+ import com.gemstone.gemfire.distributed.LocatorLauncher;
+ import com.gemstone.gemfire.distributed.LocatorLauncher.LocatorState;
+ import com.gemstone.gemfire.distributed.ServerLauncher;
+ import com.gemstone.gemfire.distributed.ServerLauncher.ServerState;
+ import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+ import com.gemstone.gemfire.distributed.internal.tcpserver.TcpClient;
+ import com.gemstone.gemfire.internal.DistributionLocator;
+ import com.gemstone.gemfire.internal.GemFireVersion;
+ import com.gemstone.gemfire.internal.OSProcess;
+ import com.gemstone.gemfire.internal.SocketCreator;
+ import com.gemstone.gemfire.internal.cache.persistence.PersistentMemberPattern;
+ import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+ import com.gemstone.gemfire.internal.lang.ClassUtils;
+ import com.gemstone.gemfire.internal.lang.ObjectUtils;
+ import com.gemstone.gemfire.internal.lang.StringUtils;
+ import com.gemstone.gemfire.internal.lang.SystemUtils;
+ import com.gemstone.gemfire.internal.process.ClusterConfigurationNotAvailableException;
+ import com.gemstone.gemfire.internal.process.NonBlockingProcessStreamReader;
+ import com.gemstone.gemfire.internal.process.ProcessLauncherContext;
+ import com.gemstone.gemfire.internal.process.ProcessStreamReader;
+ import com.gemstone.gemfire.internal.process.ProcessStreamReader.InputListener;
+ import com.gemstone.gemfire.internal.process.ProcessStreamReader.ReadingMode;
+ import com.gemstone.gemfire.internal.process.ProcessType;
+ import com.gemstone.gemfire.internal.process.ProcessUtils;
+ import com.gemstone.gemfire.internal.process.signal.SignalEvent;
+ import com.gemstone.gemfire.internal.process.signal.SignalListener;
+ import com.gemstone.gemfire.internal.util.IOUtils;
+ import com.gemstone.gemfire.internal.util.StopWatch;
+ import com.gemstone.gemfire.lang.AttachAPINotFoundException;
+ import com.gemstone.gemfire.management.DistributedSystemMXBean;
+ import com.gemstone.gemfire.management.MemberMXBean;
+ import com.gemstone.gemfire.management.cli.CliMetaData;
+ import com.gemstone.gemfire.management.cli.ConverterHint;
+ import com.gemstone.gemfire.management.cli.Result;
+ import com.gemstone.gemfire.management.internal.ManagementConstants;
+ import com.gemstone.gemfire.management.internal.cli.CliUtil;
+ import com.gemstone.gemfire.management.internal.cli.LogWrapper;
+ import com.gemstone.gemfire.management.internal.cli.converters.ConnectionEndpointConverter;
+ import com.gemstone.gemfire.management.internal.cli.domain.ConnectToLocatorResult;
+ import com.gemstone.gemfire.management.internal.cli.i18n.CliStrings;
+ import com.gemstone.gemfire.management.internal.cli.result.InfoResultData;
+ import com.gemstone.gemfire.management.internal.cli.result.ResultBuilder;
+ import com.gemstone.gemfire.management.internal.cli.shell.Gfsh;
+ import com.gemstone.gemfire.management.internal.cli.shell.JmxOperationInvoker;
+ import com.gemstone.gemfire.management.internal.cli.shell.OperationInvoker;
+ import com.gemstone.gemfire.management.internal.cli.util.CauseFinder;
+ import com.gemstone.gemfire.management.internal.cli.util.CommandStringBuilder;
+ import com.gemstone.gemfire.management.internal.cli.util.ConnectionEndpoint;
+ import com.gemstone.gemfire.management.internal.cli.util.JConsoleNotFoundException;
+ import com.gemstone.gemfire.management.internal.cli.util.VisualVmNotFoundException;
+ import com.gemstone.gemfire.management.internal.configuration.domain.SharedConfigurationStatus;
+ import com.gemstone.gemfire.management.internal.configuration.messages.SharedConfigurationStatusRequest;
+ import com.gemstone.gemfire.management.internal.configuration.messages.SharedConfigurationStatusResponse;
 -
++import com.gemstone.gemfire.management.internal.security.Resource;
++import com.gemstone.gemfire.management.internal.security.ResourceConstants;
++import com.gemstone.gemfire.management.internal.security.ResourceOperation;
+ import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
+ import org.springframework.shell.core.annotation.CliCommand;
+ import org.springframework.shell.core.annotation.CliOption;
+ 
+ /**
+  * The LauncherLifecycleCommands class encapsulates all GemFire launcher commands for GemFire tools (like starting
+  * GemFire Monitor (GFMon) and Visual Statistics Display (VSD)) as well external tools (like jconsole).
+  * <p>
+  * @author John Blum
+  * @see com.gemstone.gemfire.distributed.LocatorLauncher
+  * @see com.gemstone.gemfire.distributed.ServerLauncher
+  * @see com.gemstone.gemfire.management.internal.cli.commands.AbstractCommandsSupport
+  * @see com.gemstone.gemfire.management.internal.cli.shell.Gfsh
+  * @since 7.0
+  */
+ @SuppressWarnings("unused")
+ public class LauncherLifecycleCommands extends AbstractCommandsSupport {
+ 
+   private static final String LOCATOR_TERM_NAME = "Locator";
+   private static final String SERVER_TERM_NAME  = "Server";
+   
+   private static final long PROCESS_STREAM_READER_JOIN_TIMEOUT_MILLIS = 30*1000;
+   private static final long PROCESS_STREAM_READER_ASYNC_STOP_TIMEOUT_MILLIS = 5*1000;
+   private static final long WAITING_FOR_STOP_TO_MAKE_PID_GO_AWAY_TIMEOUT_MILLIS = 30*1000;
+   private static final long WAITING_FOR_PID_FILE_TO_CONTAIN_PID_TIMEOUT_MILLIS = 2*1000;
+   
+   protected static final int CMS_INITIAL_OCCUPANCY_FRACTION = 60;
+   protected static final int DEFAULT_PROCESS_OUTPUT_WAIT_TIME_MILLISECONDS = 5000;
+   protected static final int INVALID_PID = -1;
+   protected static final int MINIMUM_HEAP_FREE_RATIO = 10;
+   protected static final int NUM_ATTEMPTS_FOR_SHARED_CONFIGURATION_STATUS = 3;
+ 
+   protected static final AtomicReference<Boolean> ATTACH_API_AVAILABLE = new AtomicReference<>(null);
+ 
+   protected static final String ATTACH_API_CLASS_NAME = "com.sun.tools.attach.AttachNotSupportedException";
+   protected static final String GEMFIRE_HOME = System.getenv("GEMFIRE");
+   protected static final String JAVA_HOME = System.getProperty("java.home");
+   protected static final String LOCALHOST = "localhost";
+ 
+   // MUST CHANGE THIS TO REGEX SINCE VERSION CHANGES IN JAR NAME
+   protected static final String GEMFIRE_JAR_PATHNAME = IOUtils.appendToPath(GEMFIRE_HOME, "lib", GemFireVersion.getGemFireJarFileName());
+ 
+   protected static final String CORE_DEPENDENCIES_JAR_PATHNAME =
+     IOUtils.appendToPath(GEMFIRE_HOME, "lib", "geode-dependencies.jar");
+ 
+   protected static final String SPRING_AOP_JAR_NAME_PREFIX = "spring-aop";
+   protected static final String SPRING_BEANS_JAR_NAME_PREFIX = "spring-beans";
+   protected static final String SPRING_CONTEXT_JAR_NAME_PREFIX = "spring-context";
+   protected static final String SPRING_CONTEXT_SUPPORT_JAR_NAME_PREFIX = "spring-context-support";
+   protected static final String SPRING_DATA_COMMONS_JAR_NAME_PREFIX = "spring-data-commons";
+   protected static final String SPRING_DATA_GEMFIRE_JAR_NAME_PREFIX = "spring-data-gemfire";
+   protected static final String SPRING_EXPRESSION_JAR_NAME_PREFIX = "spring-expression";
+   protected static final String SPRING_TX_JAR_NAME_PREFIX = "spring-tx";
+ 
+   protected static final Set<String> SPRING_JAR_NAME_PREFIXES;
+ 
+   static {
+     Set<String> springJarNamePrefixes = new HashSet<>(8);
+ 
+     springJarNamePrefixes.add(SPRING_AOP_JAR_NAME_PREFIX);
+     springJarNamePrefixes.add(SPRING_BEANS_JAR_NAME_PREFIX);
+     springJarNamePrefixes.add(SPRING_CONTEXT_JAR_NAME_PREFIX);
+     springJarNamePrefixes.add(SPRING_CONTEXT_SUPPORT_JAR_NAME_PREFIX);
+     springJarNamePrefixes.add(SPRING_DATA_COMMONS_JAR_NAME_PREFIX);
+     springJarNamePrefixes.add(SPRING_DATA_GEMFIRE_JAR_NAME_PREFIX);
+     springJarNamePrefixes.add(SPRING_EXPRESSION_JAR_NAME_PREFIX);
+     springJarNamePrefixes.add(SPRING_TX_JAR_NAME_PREFIX);
+ 
+     SPRING_JAR_NAME_PREFIXES = Collections.unmodifiableSet(springJarNamePrefixes);
+   }
+ 
+   protected static boolean isAttachApiAvailable() {
+     if (ATTACH_API_AVAILABLE.get() == null) {
+       try {
+         ClassUtils.forName(ATTACH_API_CLASS_NAME, new AttachAPINotFoundException());
+         ATTACH_API_AVAILABLE.set(Boolean.TRUE);
+       }
+       catch (AttachAPINotFoundException ignore) {
+         ATTACH_API_AVAILABLE.set(Boolean.FALSE);
+       }
+     }
+ 
+     return ATTACH_API_AVAILABLE.get();
+   }
+ 
+   @CliCommand(value = CliStrings.START_LOCATOR, help = CliStrings.START_LOCATOR__HELP)
+   @CliMetaData(shellOnly = true, relatedTopic = { CliStrings.TOPIC_GEMFIRE_LOCATOR, CliStrings.TOPIC_GEMFIRE_LIFECYCLE })
++  @ResourceOperation(resource = Resource.DISTRIBUTED_SYSTEM, operation= ResourceConstants.LIST_DS)
+   public Result startLocator(@CliOption(key = CliStrings.START_LOCATOR__MEMBER_NAME,
+                                         mandatory = true,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__MEMBER_NAME__HELP)
+                              final String memberName,
+                              @CliOption(key = CliStrings.START_LOCATOR__BIND_ADDRESS,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__BIND_ADDRESS__HELP)
+                              final String bindAddress,
+                              @CliOption(key = CliStrings.START_LOCATOR__CLASSPATH,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__CLASSPATH__HELP)
+                              final String classpath,
+                              @CliOption(key = CliStrings.START_LOCATOR__FORCE,
+                                         unspecifiedDefaultValue = "false",
+                                         specifiedDefaultValue = "true",
+                                         help = CliStrings.START_LOCATOR__FORCE__HELP)
+                              final Boolean force,
+                              @CliOption(key = CliStrings.START_LOCATOR__GROUP,
+                                         optionContext = ConverterHint.MEMBERGROUP,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__GROUP__HELP)
+                              final String group,
+                              @CliOption(key = CliStrings.START_LOCATOR__HOSTNAME_FOR_CLIENTS,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__HOSTNAME_FOR_CLIENTS__HELP)
+                              final String hostnameForClients,
+                              @CliOption(key = CliStrings.START_LOCATOR__INCLUDE_SYSTEM_CLASSPATH,
+                                         specifiedDefaultValue = "true",
+                                         unspecifiedDefaultValue = "false",
+                                         help = CliStrings.START_LOCATOR__INCLUDE_SYSTEM_CLASSPATH__HELP)
+                              final Boolean includeSystemClasspath,
+                              @CliOption(key = CliStrings.START_LOCATOR__LOCATORS,
+                                         optionContext = ConverterHint.LOCATOR_DISCOVERY_CONFIG,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__LOCATORS__HELP)
+                              final String locators,
+                              @CliOption(key = CliStrings.START_LOCATOR__LOG_LEVEL,
+                                         optionContext = ConverterHint.LOG_LEVEL,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__LOG_LEVEL__HELP)
+                              final String logLevel,
+                              @CliOption(key = CliStrings.START_LOCATOR__MCAST_ADDRESS,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__MCAST_ADDRESS__HELP)
+                              final String mcastBindAddress,
+                              @CliOption(key = CliStrings.START_LOCATOR__MCAST_PORT,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__MCAST_PORT__HELP)
+                              final Integer mcastPort,
+                              @CliOption(key = CliStrings.START_LOCATOR__PORT,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__PORT__HELP)
+                              final Integer port,
+                              @CliOption(key = CliStrings.START_LOCATOR__DIR,
+                                         optionContext = ConverterHint.DIR_PATHSTRING,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__DIR__HELP)
+                              String workingDirectory,
+                              @CliOption(key = CliStrings.START_LOCATOR__PROPERTIES,
+                                         optionContext = ConverterHint.FILE_PATHSTRING,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__PROPERTIES__HELP)
+                              String gemfirePropertiesPathname,
+                              @CliOption(key = CliStrings.START_LOCATOR__SECURITY_PROPERTIES,
+                                         optionContext = ConverterHint.FILE_PATHSTRING,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__SECURITY_PROPERTIES__HELP)
+                              String gemfireSecurityPropertiesPathname,
+                              @CliOption(key = CliStrings.START_LOCATOR__INITIALHEAP,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__INITIALHEAP__HELP)
+                              final String initialHeap,
+                              @CliOption(key = CliStrings.START_LOCATOR__MAXHEAP,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__MAXHEAP__HELP)
+                              final String maxHeap,
+                              @CliOption(key = CliStrings.START_LOCATOR__J,
+                                         optionContext = ConverterHint.STRING_LIST,
+                                         unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                         help = CliStrings.START_LOCATOR__J__HELP)
+                              @CliMetaData(valueSeparator = ",")
+                              final String[] jvmArgsOpts,
+                              @CliOption (key = CliStrings.START_LOCATOR__CONNECT,
+                                         unspecifiedDefaultValue = "true",
+                                         specifiedDefaultValue = "true",
+                                         help = CliStrings.START_LOCATOR__CONNECT__HELP)
+                              final boolean connect,
+                              @CliOption(key = CliStrings.START_LOCATOR__ENABLE__SHARED__CONFIGURATION,
+                                         unspecifiedDefaultValue = "true",
+                                         specifiedDefaultValue = "true",
+                                         help = CliStrings.START_LOCATOR__ENABLE__SHARED__CONFIGURATION__HELP)
+                              final boolean enableSharedConfiguration,
+                              @CliOption(key = CliStrings.START_LOCATOR__LOAD__SHARED_CONFIGURATION__FROM__FILESYSTEM,
+                                         unspecifiedDefaultValue = "false",
+                                         help = CliStrings.START_LOCATOR__LOAD__SHARED_CONFIGURATION__FROM__FILESYSTEM__HELP)
+                              final boolean loadSharedConfigurationFromDirectory,
+                              @CliOption(key = CliStrings.START_LOCATOR__CLUSTER__CONFIG__DIR,
+                                         unspecifiedDefaultValue = "",
+                                         help = CliStrings.START_LOCATOR__CLUSTER__CONFIG__DIR__HELP)
+                              final String clusterConfigDir
+   ) {
+     try {
+       if (workingDirectory == null) {
+         // attempt to use or make sub-directory using memberName...
+         File locatorWorkingDirectory = new File(memberName);
+ 
+         if (!(locatorWorkingDirectory.exists() || locatorWorkingDirectory.mkdir())) {
+           throw new IllegalStateException(CliStrings.format(CliStrings.START_LOCATOR__MSG__COULD_NOT_CREATE_DIRECTORY_0_VERIFY_PERMISSIONS,
+             locatorWorkingDirectory.getAbsolutePath()));
+         }
+ 
+         workingDirectory = IOUtils.tryGetCanonicalPathElseGetAbsolutePath(locatorWorkingDirectory);
+       }
+ 
+       gemfirePropertiesPathname = CliUtil.resolvePathname(gemfirePropertiesPathname);
+ 
+       if (!StringUtils.isBlank(gemfirePropertiesPathname) && !IOUtils.isExistingPathname(gemfirePropertiesPathname)) {
+         return ResultBuilder.createUserErrorResult(CliStrings.format(CliStrings.GEMFIRE_0_PROPERTIES_1_NOT_FOUND_MESSAGE,
+           StringUtils.EMPTY_STRING, gemfirePropertiesPathname));
+       }
+ 
+       gemfireSecurityPropertiesPathname = CliUtil.resolvePathname(gemfireSecurityPropertiesPathname);
+ 
+       if (!StringUtils.isBlank(gemfireSecurityPropertiesPathname) && !IOUtils.isExistingPathname(gemfireSecurityPropertiesPathname)) {
+         return ResultBuilder.createUserErrorResult(CliStrings.format(CliStrings.GEMFIRE_0_PROPERTIES_1_NOT_FOUND_MESSAGE,
+           "Security ", gemfireSecurityPropertiesPathname));
+       }
+ 
+       File locatorPidFile = new File(workingDirectory, ProcessType.LOCATOR.getPidFileName());
+ 
+       final int oldPid = readPid(locatorPidFile);
+ 
+       Properties gemfireProperties = new Properties();
+ 
+       gemfireProperties.setProperty(DistributionConfig.GROUPS_NAME, StringUtils.valueOf(group, StringUtils.EMPTY_STRING));
+       gemfireProperties.setProperty(DistributionConfig.LOCATORS_NAME, StringUtils.valueOf(locators, StringUtils.EMPTY_STRING));
+       gemfireProperties.setProperty(DistributionConfig.LOG_LEVEL_NAME, StringUtils.valueOf(logLevel, StringUtils.EMPTY_STRING));
+       gemfireProperties.setProperty(DistributionConfig.MCAST_ADDRESS_NAME, StringUtils.valueOf(mcastBindAddress, StringUtils.EMPTY_STRING));
+       gemfireProperties.setProperty(DistributionConfig.MCAST_PORT_NAME, StringUtils.valueOf(mcastPort, StringUtils.EMPTY_STRING));
+       gemfireProperties.setProperty(DistributionConfig.ENABLE_CLUSTER_CONFIGURATION_NAME, StringUtils.valueOf(enableSharedConfiguration, StringUtils.EMPTY_STRING));
+       gemfireProperties.setProperty(DistributionConfig.LOAD_CLUSTER_CONFIG_FROM_DIR_NAME, StringUtils.valueOf(loadSharedConfigurationFromDirectory, StringUtils.EMPTY_STRING));
+       gemfireProperties.setProperty(DistributionConfig.CLUSTER_CONFIGURATION_DIR, StringUtils.valueOf(clusterConfigDir, StringUtils.EMPTY_STRING));
+       
+       // read the OSProcess enable redirect system property here -- TODO: replace with new GFSH argument
+       final boolean redirectOutput = Boolean.getBoolean(OSProcess.ENABLE_OUTPUT_REDIRECTION_PROPERTY);
+       LocatorLauncher locatorLauncher = new LocatorLauncher.Builder()
+         .setBindAddress(bindAddress)
+         .setForce(force)
+         .setHostnameForClients(hostnameForClients)
+         .setMemberName(memberName)
+         .setPort(port)
+         .setRedirectOutput(redirectOutput)
+         .setWorkingDirectory(workingDirectory)
+         .build();
+ 
+       String[] locatorCommandLine = createStartLocatorCommandLine(locatorLauncher, gemfirePropertiesPathname,
+           gemfireSecurityPropertiesPathname, gemfireProperties, classpath, includeSystemClasspath, jvmArgsOpts, initialHeap, maxHeap);
+ 
+       //getGfsh().logInfo(StringUtils.concat(locatorCommandLine, " "), null);
+ 
+       final Process locatorProcess = new ProcessBuilder(locatorCommandLine)
+         .directory(new File(locatorLauncher.getWorkingDirectory()))
+         .start();
+ 
+       locatorProcess.getInputStream().close();
+       locatorProcess.getOutputStream().close();
+ 
+       // fix TRAC bug #51967 by using NON_BLOCKING on Windows
+       final ReadingMode readingMode = SystemUtils.isWindows() ? ReadingMode.NON_BLOCKING : ReadingMode.BLOCKING;
+ 
+       final StringBuffer message = new StringBuffer(); // need thread-safe StringBuffer
+       InputListener inputListener = new InputListener() {
+         @Override
+         public void notifyInputLine(String line) {
+           message.append(line);
+           if (readingMode == ReadingMode.BLOCKING) {
+             message.append(StringUtils.LINE_SEPARATOR);
+           }
+         }
+       };
+ 
+       ProcessStreamReader stderrReader = new ProcessStreamReader.Builder(locatorProcess)
+           .inputStream(locatorProcess.getErrorStream())
+           .inputListener(inputListener)
+           .readingMode(readingMode)
+           .continueReadingMillis(2*1000)
+           .build()
+           .start();
+ 
+       LocatorState locatorState;
+ 
+       String previousLocatorStatusMessage = null;
+ 
+       LauncherSignalListener locatorSignalListener = new LauncherSignalListener();
+ 
+       final boolean registeredLocatorSignalListener = getGfsh().getSignalHandler().registerListener(locatorSignalListener);
+ 
+       try {
+         getGfsh().logInfo(String.format(CliStrings.START_LOCATOR__RUN_MESSAGE,
+           IOUtils.tryGetCanonicalPathElseGetAbsolutePath(new File(locatorLauncher.getWorkingDirectory()))), null);
+ 
+         do {
+           try {
+             final int exitValue = locatorProcess.exitValue();
+ 
+             stderrReader.join(PROCESS_STREAM_READER_JOIN_TIMEOUT_MILLIS); // was Long.MAX_VALUE
+ 
+             //Gfsh.println(message);
+ 
+             return ResultBuilder.createShellClientErrorResult(String.format(
+               CliStrings.START_LOCATOR__PROCESS_TERMINATED_ABNORMALLY_ERROR_MESSAGE,
+                 exitValue, locatorLauncher.getWorkingDirectory(), message.toString()));
+           }
+           catch (IllegalThreadStateException ignore) {
+             // the IllegalThreadStateException is expected; it means the Locator's process has not terminated,
+             // and basically should not
+             Gfsh.print(".");
+ 
+             synchronized (this) {
+               TimeUnit.MILLISECONDS.timedWait(this, 500);
+             }
+ 
+             locatorState = (ProcessUtils.isAttachApiAvailable() ? locatorStatus(locatorPidFile, oldPid, memberName)
+                 : locatorStatus(workingDirectory, memberName));
+ 
+             String currentLocatorStatusMessage = locatorState.getStatusMessage();
+ 
+             if (isStartingOrNotResponding(locatorState.getStatus())
+               && !(StringUtils.isBlank(currentLocatorStatusMessage)
+                 || currentLocatorStatusMessage.equalsIgnoreCase(previousLocatorStatusMessage)))
+             {
+               Gfsh.println();
+               Gfsh.println(currentLocatorStatusMessage);
+               previousLocatorStatusMessage = currentLocatorStatusMessage;
+             }
+           }
+         }
+         while (!(registeredLocatorSignalListener && locatorSignalListener.isSignaled())
+           && isStartingOrNotResponding(locatorState.getStatus()));
+       }
+       finally {
+         stderrReader.stopAsync(PROCESS_STREAM_READER_ASYNC_STOP_TIMEOUT_MILLIS); // stop will close ErrorStream
+         getGfsh().getSignalHandler().unregisterListener(locatorSignalListener);
+       }
+ 
+       Gfsh.println();
+ 
+       final boolean asyncStart = (registeredLocatorSignalListener && locatorSignalListener.isSignaled()
+         && isStartingNotRespondingOrNull(locatorState));
+ 
+       InfoResultData infoResultData = ResultBuilder.createInfoResultData();
+ 
+       if (asyncStart) {
+         infoResultData.addLine(String.format(CliStrings.ASYNC_PROCESS_LAUNCH_MESSAGE, LOCATOR_TERM_NAME));
+       }
+       else {
+         infoResultData.addLine(locatorState.toString());
+ 
+         String locatorHostName = StringUtils.defaultIfBlank(locatorLauncher.getHostnameForClients(), getLocalHost());
+         int locatorPort = locatorLauncher.getPort();
+ 
+         // AUTO-CONNECT
+         // If the connect succeeds add the connected message to the result,
+         // Else, ask the user to use the "connect" command to connect to the Locator.
+         if (shouldAutoConnect(connect)) {
+           doAutoConnect(locatorHostName, locatorPort, gemfirePropertiesPathname, gemfireSecurityPropertiesPathname,
+             infoResultData);
+         }
+ 
+         // Report on the state of the Shared Configuration service if enabled...
+         if (enableSharedConfiguration) {
+           infoResultData.addLine(getSharedConfigurationStatusFromLocator(locatorHostName, locatorPort));
+         }
+       }
+ 
+       return ResultBuilder.buildResult(infoResultData);
+     }
+     catch (IllegalArgumentException e) {
+       String message = e.getMessage();
+       if (message != null && message.matches(LocalizedStrings.Launcher_Builder_UNKNOWN_HOST_ERROR_MESSAGE.toLocalizedString(".+"))) {
+         message = CliStrings.format(CliStrings.LAUNCHERLIFECYCLECOMMANDS__MSG__FAILED_TO_START_0_REASON_1, LOCATOR_TERM_NAME, message);
+       }
+       return ResultBuilder.createUserErrorResult(message);
+     }
+     catch (IllegalStateException e) {
+       return ResultBuilder.createUserErrorResult(e.getMessage());
+     }
+     catch (VirtualMachineError e) {
+       SystemFailure.initiateFailure(e);
+       throw e;
+     }
+     catch (Throwable t) {
+       SystemFailure.checkFailure();
+       String errorMessage = String.format(CliStrings.START_LOCATOR__GENERAL_ERROR_MESSAGE,
+         StringUtils.defaultIfBlank(workingDirectory, memberName), getLocatorId(bindAddress, port),
+         toString(t, getGfsh().getDebug()));
+       getGfsh().logToFile(errorMessage, t);
+       return ResultBuilder.createShellClientErrorResult(errorMessage);
+     }
+     finally {
+       Gfsh.redirectInternalJavaLoggers();
+     }
+   }
+ 
+   protected String[] createStartLocatorCommandLine(final LocatorLauncher launcher,
+                                                    final String gemfirePropertiesPathname,
+                                                    final String gemfireSecurityPropertiesPathname,
+                                                    final Properties gemfireProperties,
+                                                    final String userClasspath,
+                                                    final Boolean includeSystemClasspath,
+                                                    final String[] jvmArgsOpts,
+                                                    final String initialHeap,
+                                                    final String maxHeap)
+     throws MalformedObjectNameException
+   {
+     List<String> commandLine = new ArrayList<>();
+ 
+     commandLine.add(getJavaPath());
+     commandLine.add("-server");
+     commandLine.add("-classpath");
+     commandLine.add(getLocatorClasspath(Boolean.TRUE.equals(includeSystemClasspath), userClasspath));
+ 
+     addCurrentLocators(commandLine, gemfireProperties);
+     addGemFirePropertyFile(commandLine, gemfirePropertiesPathname);
+     addGemFireSecurityPropertyFile(commandLine, gemfireSecurityPropertiesPathname);
+     addGemFireSystemProperties(commandLine, gemfireProperties);
+     addJvmArgumentsAndOptions(commandLine, jvmArgsOpts);
+     addInitialHeap(commandLine, initialHeap);
+     addMaxHeap(commandLine, maxHeap);
+ 
+     commandLine.add("-D".concat(AbstractLauncher.SIGNAL_HANDLER_REGISTRATION_SYSTEM_PROPERTY.concat("=true")));
+     commandLine.add("-Djava.awt.headless=true");
+     commandLine.add("-Dsun.rmi.dgc.server.gcInterval".concat("=").concat(Long.toString(Long.MAX_VALUE-1)));
+     commandLine.add(LocatorLauncher.class.getName());
+     commandLine.add(LocatorLauncher.Command.START.getName());
+ 
+     if (!StringUtils.isBlank(launcher.getMemberName())) {
+       commandLine.add(launcher.getMemberName());
+     }
+ 
+     if (launcher.getBindAddress() != null) {
+       commandLine.add("--bind-address=" + launcher.getBindAddress().getCanonicalHostName());
+     }
+ 
+     if (launcher.isDebugging() || isDebugging()) {
+       commandLine.add("--debug");
+     }
+ 
+     if (launcher.isForcing()) {
+       commandLine.add("--force");
+     }
+ 
+     if (!StringUtils.isBlank(launcher.getHostnameForClients())) {
+       commandLine.add("--hostname-for-clients=" + launcher.getHostnameForClients());
+     }
+ 
+     if (launcher.getPort() != null) {
+       commandLine.add("--port=" + launcher.getPort());
+     }
+ 
+     if (launcher.isRedirectingOutput()) {
+       commandLine.add("--redirect-output");
+     }
+ 
+     return commandLine.toArray(new String[commandLine.size()]);
+   }
+ 
+   // TODO should we connect implicitly when in non-interactive, headless mode (e.g. gfsh -e "start locator ...")?
+   // With execute option (-e), there could be multiple commands which might presume that a prior "start locator"
+   // has formed the connection.
+   private boolean shouldAutoConnect(final boolean connect) {
+     return (connect && !(getGfsh() == null || isConnectedAndReady()));
+   }
+ 
+   private boolean doAutoConnect(final String locatorHostname,
+                                 final int locatorPort,
+                                 final String gemfirePropertiesPathname,
+                                 final String gemfireSecurityPropertiesPathname,
+                                 final InfoResultData infoResultData)
+   {
+     boolean connectSuccess = false;
+     boolean jmxManagerAuthEnabled = false;
+     boolean jmxManagerSslEnabled = false;
+ 
+     Map<String, String> configurationProperties = loadConfigurationProperties(gemfireSecurityPropertiesPathname,
+       loadConfigurationProperties(gemfirePropertiesPathname));
+     Map<String, String> locatorConfigurationProperties = new HashMap<>(configurationProperties);
+ 
+     String responseFailureMessage = null;
+ 
+     for (int attempts = 0; (attempts < 10 && !connectSuccess); attempts++) {
+       try {
+         ConnectToLocatorResult connectToLocatorResult = ShellCommands.connectToLocator(locatorHostname, locatorPort,
+           ShellCommands.getConnectLocatorTimeoutInMS() / 4, locatorConfigurationProperties);
+ 
+         ConnectionEndpoint memberEndpoint = connectToLocatorResult.getMemberEndpoint();
+ 
+         jmxManagerSslEnabled = connectToLocatorResult.isJmxManagerSslEnabled();
+ 
+         if (!jmxManagerSslEnabled) {
+           configurationProperties.clear();
+         }
+ 
+         getGfsh().setOperationInvoker(new JmxOperationInvoker(memberEndpoint.getHost(), memberEndpoint.getPort(),
 -          null, null, configurationProperties));
++          null, null, configurationProperties, null));
+ 
+         String shellAndLogMessage = CliStrings.format(CliStrings.CONNECT__MSG__SUCCESS, memberEndpoint.toString(false));
+ 
+         infoResultData.addLine("\n");
+         infoResultData.addLine(shellAndLogMessage);
+         getGfsh().logToFile(shellAndLogMessage, null);
+ 
+         connectSuccess = true;
+         responseFailureMessage = null;
+       }
+       catch (IllegalStateException unexpected) {
+         if (CauseFinder.indexOfCause(unexpected, ClassCastException.class, false) != -1) {
+           responseFailureMessage = "The Locator might require SSL Configuration.";
+         }
+       }
+       catch (SecurityException ignore) {
+         getGfsh().logToFile(ignore.getMessage(), ignore);
+         jmxManagerAuthEnabled = true;
+         break; // no need to continue after SecurityException
+       }
+       catch (SSLException ignore) {
+         if (ignore instanceof SSLHandshakeException) {
+           // try to connect again without SSL since the SSL handshake failed implying a plain text connection...
+           locatorConfigurationProperties.clear();
+         }
+         else {
+           // another type of SSL error occurred (possibly a configuration issue); pass the buck...
+           getGfsh().logToFile(ignore.getMessage(), ignore);
+           responseFailureMessage = "Check your SSL configuration and try again.";
+           break;
+         }
+       }
+       catch (Exception ignore) {
+         getGfsh().logToFile(ignore.getMessage(), ignore);
+         responseFailureMessage = "Failed to connect; unknown cause: " + ignore.getMessage();
+       }
+     }
+ 
+     if (!connectSuccess) {
+       doOnConnectionFailure(locatorHostname, locatorPort, jmxManagerAuthEnabled, jmxManagerSslEnabled, infoResultData);
+     }
+ 
+     if (!StringUtils.isBlank(responseFailureMessage)) {
+       infoResultData.addLine("\n");
+       infoResultData.addLine(responseFailureMessage);
+     }
+ 
+     return connectSuccess;
+   }
+ 
+   private void doOnConnectionFailure(final String locatorHostName,
+                                      final int locatorPort,
+                                      final boolean jmxManagerAuthEnabled,
+                                      final boolean jmxManagerSslEnabled,
+                                      final InfoResultData infoResultData)
+   {
+     infoResultData.addLine("\n");
+     infoResultData.addLine(CliStrings.format(CliStrings.START_LOCATOR__USE__0__TO__CONNECT,
+       new CommandStringBuilder(CliStrings.CONNECT).addOption(CliStrings.CONNECT__LOCATOR,
+         locatorHostName + "[" + locatorPort + "]").toString()));
+ 
+     StringBuilder message = new StringBuilder();
+ 
+     if (jmxManagerAuthEnabled) {
+       message.append("Authentication");
+     }
+     if (jmxManagerSslEnabled) {
+       message.append(jmxManagerAuthEnabled ? " and " : StringUtils.EMPTY_STRING).append("SSL configuration");
+     }
+     if (jmxManagerAuthEnabled || jmxManagerSslEnabled) {
+       message.append(" required to connect to the Manager.");
+       infoResultData.addLine("\n");
+       infoResultData.addLine(message.toString());
+     }
+   }
+ 
+   private Map<String, String> loadConfigurationProperties(final String configurationPropertiesPathname) {
+     return loadConfigurationProperties(configurationPropertiesPathname, null);
+   }
+ 
+   private Map<String, String> loadConfigurationProperties(final String configurationPropertiesPathname,
+                                                           Map<String, String> configurationProperties)
+   {
+     configurationProperties = (configurationProperties != null ? configurationProperties
+       : new HashMap<String, String>());
+ 
+     if (IOUtils.isExistingPathname(configurationPropertiesPathname)) {
+       try {
+         configurationProperties.putAll(ShellCommands.loadPropertiesFromURL(
+           new File(configurationPropertiesPathname).toURI().toURL()));
+       }
+       catch (MalformedURLException ignore) {
+         LogWrapper.getInstance().warning(String.format(
+           "Failed to load GemFire configuration properties from pathname (%1$s)!",
+             configurationPropertiesPathname), ignore);
+       }
+     }
+ 
+     return configurationProperties;
+   }
+ 
+   private String getSharedConfigurationStatusFromLocatorState(LocatorState locatorState) throws ClassNotFoundException, IOException {
+     return getSharedConfigurationStatusFromLocator(locatorState.getHost(), Integer.parseInt(locatorState.getPort()));
+   }
+ 
+   private String getSharedConfigurationStatusFromLocator(String locatorHostName, int locatorPort) throws ClassNotFoundException, IOException  {
+     final StringBuilder buffer = new StringBuilder();
+     
+     try {
+       final InetAddress networkAddress = InetAddress.getByName(locatorHostName);
+ 
+       SharedConfigurationStatusResponse statusResponse = (SharedConfigurationStatusResponse)
+         TcpClient.requestToServer(networkAddress, locatorPort, new SharedConfigurationStatusRequest(), 10000, true);
+       
+       for (int i=0; i<NUM_ATTEMPTS_FOR_SHARED_CONFIGURATION_STATUS; i++) {
+         if (statusResponse.getStatus().equals(SharedConfigurationStatus.STARTED) || statusResponse.getStatus().equals(SharedConfigurationStatus.NOT_STARTED)) {
+           statusResponse = (SharedConfigurationStatusResponse) TcpClient.requestToServer(networkAddress, locatorPort, new SharedConfigurationStatusRequest(), 10000, true);
+           try {
+             Thread.sleep(5000);
+           } catch (InterruptedException e) {
+             //Swallow the exception
+           }
+         } else {
+           break;
+         }
+       }
+       
+       switch (statusResponse.getStatus()) {
+         case RUNNING:
+           buffer.append("\nCluster configuration service is up and running.");
+           break;
+         case STOPPED:
+           buffer.append("\nCluster configuration service failed to start , please check the log file for errors.");
+           break;
+         case WAITING:
+           buffer.append("\nCluster configuration service is waiting for other locators with newer shared configuration data.");
+           Set<PersistentMemberPattern> pmpSet = statusResponse.getOtherLocatorInformation();
+           if (!pmpSet.isEmpty()) {
+             buffer.append("\nThis locator might have stale cluster configuration data.");
+             buffer.append("\nFollowing locators contain potentially newer cluster configuration data");
+ 
+             for (PersistentMemberPattern pmp : pmpSet) {
+               buffer.append("\nHost : ").append(pmp.getHost());
+               buffer.append("\nDirectory : ").append(pmp.getDirectory());
+             }
+           }
+           else {
+             buffer.append("\nPlease check the log file for errors");
+           }
+           break;
+         case UNDETERMINED:
+           buffer.append("\nUnable to determine the status of shared configuration service, please check the log file");
+           break;
+         case NOT_STARTED:
+           buffer.append("\nCluster configuration service has not been started yet");
+           break;
+         case STARTED:
+           buffer.append("\nCluster configuration service has been started, but its not running yet");
+           break;
+       }
+     }
+     catch (Exception e) {
+       // TODO fix this once Trac Bug #50513 gets fixed
+       // NOTE this ClassCastException occurs if the a plain text TCP/IP connection is used to connect to a Locator
+       // configured with SSL.
+       getGfsh().logToFile(String.format("Failed to get the status of the Shared Configuration Service running on Locator (%1$s[%2$d])!",
+         locatorHostName, locatorPort), e);
+     }
+ 
+     return buffer.toString();
+   }
+ 
+   @CliCommand(value = CliStrings.STATUS_LOCATOR, help = CliStrings.STATUS_LOCATOR__HELP)
+   @CliMetaData(shellOnly = true, relatedTopic = { CliStrings.TOPIC_GEMFIRE_LOCATOR, CliStrings.TOPIC_GEMFIRE_LIFECYCLE })
++  @ResourceOperation(resource = Resource.DISTRIBUTED_SYSTEM, operation= ResourceConstants.LIST_DS)
+   public Result statusLocator(@CliOption(key = CliStrings.STATUS_LOCATOR__MEMBER,
+                                          optionContext = ConverterHint.LOCATOR_MEMBER_IDNAME,
+                                          unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                          help = CliStrings.STATUS_LOCATOR__MEMBER__HELP)
+                               final String member,
+                               @CliOption(key = CliStrings.STATUS_LOCATOR__HOST,
+                                          unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                          help = CliStrings.STATUS_LOCATOR__HOST__HELP)
+                               final String locatorHost,
+                               @CliOption(key = CliStrings.STATUS_LOCATOR__PORT,
+                                          unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                          help = CliStrings.STATUS_LOCATOR__PORT__HELP)
+                               final Integer locatorPort,
+                               @CliOption(key = CliStrings.STATUS_LOCATOR__PID,
+                                          unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                          help = CliStrings.STATUS_LOCATOR__PID__HELP)
+                               final Integer pid,
+                               @CliOption(key = CliStrings.STATUS_LOCATOR__DIR,
+                                          optionContext = ConverterHint.DIR_PATHSTRING,
+                                          unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                          help = CliStrings.STATUS_LOCATOR__DIR__HELP)
+                               final String workingDirectory)
+   {
+     try {
+       if (!StringUtils.isBlank(member)) {
+         if (isConnectedAndReady()) {
+           final MemberMXBean locatorProxy = getMemberMXBean(member);
+ 
+           if (locatorProxy != null) {
+             LocatorState state = LocatorState.fromJson(locatorProxy.status());
+             return createStatusLocatorResult(state);
+           }
+           else {
+             return ResultBuilder.createUserErrorResult(CliStrings.format(
+               CliStrings.STATUS_LOCATOR__NO_LOCATOR_FOUND_FOR_MEMBER_ERROR_MESSAGE, member));
+           }
+         }
+         else {
+           return ResultBuilder.createUserErrorResult(CliStrings.format(
+             CliStrings.STATUS_SERVICE__GFSH_NOT_CONNECTED_ERROR_MESSAGE, LOCATOR_TERM_NAME));
+         }
+       }
+       else {
+         final LocatorLauncher locatorLauncher = new LocatorLauncher.Builder()
+           .setCommand(LocatorLauncher.Command.STATUS)
+           .setBindAddress(locatorHost)
+           .setDebug(isDebugging())
+           .setPid(pid)
+           .setPort(locatorPort)
+           .setWorkingDirectory(workingDirectory)
+           .build();
+ 
+         final LocatorState state = locatorLauncher.status();
+         return createStatusLocatorResult(state);
+       }
+     }
+     catch (IllegalArgumentException e) {
+       return ResultBuilder.createUserErrorResult(e.getMessage());
+     }
+     catch (IllegalStateException e) {
+       return ResultBuilder.createUserErrorResult(e.getMessage());
+     }
+     catch (VirtualMachineError e) {
+       SystemFailure.initiateFailure(e);
+       throw e;
+     }
+     catch (Throwable t) {
+       SystemFailure.checkFailure();
+       return ResultBuilder.createShellClientErrorResult(String.format(CliStrings.STATUS_LOCATOR__GENERAL_ERROR_MESSAGE,
+         getLocatorId(locatorHost, locatorPort), StringUtils.defaultIfBlank(workingDirectory, SystemUtils.CURRENT_DIRECTORY),
+           toString(t, getGfsh().getDebug())));
+     }
+   }
+ 
+   @CliCommand(value=CliStrings.STOP_LOCATOR, help=CliStrings.STOP_LOCATOR__HELP)
+   @CliMetaData(shellOnly=true, relatedTopic = {CliStrings.TOPIC_GEMFIRE_LOCATOR, CliStrings.TOPIC_GEMFIRE_LIFECYCLE})
++  @ResourceOperation(resource = Resource.DISTRIBUTED_SYSTEM, operation= ResourceConstants.LIST_DS)
+   public Result stopLocator(@CliOption(key = CliStrings.STOP_LOCATOR__MEMBER,
+                                        optionContext = ConverterHint.LOCATOR_MEMBER_IDNAME,
+                                        unspecifiedDefaultValue=CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help=CliStrings.STOP_LOCATOR__MEMBER__HELP)
+                             final String member,
+                             @CliOption(key=CliStrings.STOP_LOCATOR__PID,
+                                        unspecifiedDefaultValue=CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help=CliStrings.STOP_LOCATOR__PID__HELP)
+                             final Integer pid,
+                             @CliOption(key=CliStrings.STOP_LOCATOR__DIR,
+                                        optionContext = ConverterHint.DIR_PATHSTRING,
+                                        unspecifiedDefaultValue=CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help=CliStrings.STOP_LOCATOR__DIR__HELP)
+                             final String workingDirectory)
+   {
+     LocatorState locatorState;
+ 
+     try {
+       if (!StringUtils.isBlank(member)) {
+         if (isConnectedAndReady()) {
+           final MemberMXBean locatorProxy = getMemberMXBean(member);
+ 
+           if (locatorProxy != null) {
+             if (!locatorProxy.isLocator()) {
+               throw new IllegalStateException(CliStrings.format(CliStrings.STOP_LOCATOR__NOT_LOCATOR_ERROR_MESSAGE, member));
+             }
+ 
+             if (locatorProxy.isServer()) {
+               throw new IllegalStateException(CliStrings.format(CliStrings.STOP_LOCATOR__LOCATOR_IS_CACHE_SERVER_ERROR_MESSAGE, member));
+             }
+ 
+             locatorState = LocatorState.fromJson(locatorProxy.status());
+             locatorProxy.shutDownMember();
+           }
+           else {
+             return ResultBuilder.createUserErrorResult(CliStrings.format(
+               CliStrings.STOP_LOCATOR__NO_LOCATOR_FOUND_FOR_MEMBER_ERROR_MESSAGE, member));
+           }
+         }
+         else {
+           return ResultBuilder.createUserErrorResult(CliStrings.format(
+             CliStrings.STOP_SERVICE__GFSH_NOT_CONNECTED_ERROR_MESSAGE, LOCATOR_TERM_NAME));
+         }
+       }
+       else {
+         final LocatorLauncher locatorLauncher = new LocatorLauncher.Builder()
+           .setCommand(LocatorLauncher.Command.STOP)
+           .setDebug(isDebugging())
+           .setPid(pid)
+           .setWorkingDirectory(workingDirectory)
+           .build();
+ 
+         locatorState = locatorLauncher.status();
+         locatorLauncher.stop();
+       }
+ 
+       if (Status.ONLINE.equals(locatorState.getStatus())) {
+         getGfsh().logInfo(String.format(CliStrings.STOP_LOCATOR__STOPPING_LOCATOR_MESSAGE,
+           locatorState.getWorkingDirectory(), locatorState.getServiceLocation(), locatorState.getMemberName(),
+             locatorState.getPid(), locatorState.getLogFile()), null);
+ 
+         StopWatch stopWatch = new StopWatch(true);
+         while (isVmWithProcessIdRunning(locatorState.getPid())) {
+           Gfsh.print(".");
+           if (stopWatch.elapsedTimeMillis() > WAITING_FOR_STOP_TO_MAKE_PID_GO_AWAY_TIMEOUT_MILLIS) {
+             break;
+           }
+           synchronized (this) {
+             TimeUnit.MILLISECONDS.timedWait(this, 500);
+           }
+         }
+ 
+         return ResultBuilder.createInfoResult(StringUtils.EMPTY_STRING);
+       }
+       else {
+         return ResultBuilder.createUserErrorResult(locatorState.toString());
+       }
+     }
+     catch (IllegalArgumentException e) {
+       return ResultBuilder.createUserErrorResult(e.getMessage());
+     }
+     catch (IllegalStateException e) {
+       return ResultBuilder.createUserErrorResult(e.getMessage());
+     }
+     catch (VirtualMachineError e) {
+       SystemFailure.initiateFailure(e);
+       throw e;
+     }
+     catch (Throwable t) {
+       SystemFailure.checkFailure();
+       return ResultBuilder.createShellClientErrorResult(String.format(CliStrings.STOP_LOCATOR__GENERAL_ERROR_MESSAGE,
+         toString(t, getGfsh().getDebug())));
+     } finally {
+       Gfsh.redirectInternalJavaLoggers();
+     }
+   }
+ 
+   // TODO re-evaluate whether a MalformedObjectNameException should be thrown here; just because we were not able to find
+   // the "current" Locators in order to conveniently add the new member to the GemFire cluster does not mean we should
+   // throw an Exception!
+   protected void addCurrentLocators(final List<String> commandLine, final Properties gemfireProperties) throws MalformedObjectNameException {
+     if (StringUtils.isBlank(gemfireProperties.getProperty(DistributionConfig.LOCATORS_NAME))) {
+       String currentLocators = getCurrentLocators();
+ 
+       if (!StringUtils.isBlank(currentLocators)) {
+         commandLine.add("-D".concat(ProcessLauncherContext.OVERRIDDEN_DEFAULTS_PREFIX)
+           .concat(DistributionConfig.LOCATORS_NAME).concat("=").concat(currentLocators));
+       }
+     }
+   }
+   
+   protected Result createStatusLocatorResult(final LocatorState state) throws NumberFormatException, IOException, ClassNotFoundException {
+     InfoResultData infoResultData = ResultBuilder.createInfoResultData();
+     infoResultData.addLine(state.toString());
+     infoResultData.addLine(getSharedConfigurationStatusFromLocatorState(state));
+     return ResultBuilder.buildResult(infoResultData);
+   }
+ 
+   protected void addGemFirePropertyFile(final List<String> commandLine, final String gemfirePropertiesPathname) {
+     if (!StringUtils.isBlank(gemfirePropertiesPathname)) {
+       commandLine.add("-DgemfirePropertyFile=" + gemfirePropertiesPathname);
+     }
+   }
+ 
+   protected void addGemFireSecurityPropertyFile(final List<String> commandLine, final String gemfireSecurityPropertiesPathname) {
+     if (!StringUtils.isBlank(gemfireSecurityPropertiesPathname)) {
+       commandLine.add("-DgemfireSecurityPropertyFile=" + gemfireSecurityPropertiesPathname);
+     }
+   }
+ 
+   protected void addGemFireSystemProperties(final List<String> commandLine, final Properties gemfireProperties) {
+     for (final Object property : gemfireProperties.keySet()) {
+       final String propertyName = property.toString();
+       final String propertyValue = gemfireProperties.getProperty(propertyName);
+       if (!StringUtils.isBlank(propertyValue)) {
+         commandLine.add("-Dgemfire." + propertyName + "=" + propertyValue);
+       }
+     }
+   }
+ 
+   protected void addInitialHeap(final List<String> commandLine, final String initialHeap) {
+     if (!StringUtils.isBlank(initialHeap)) {
+       commandLine.add("-Xms" + initialHeap);
+     }
+   }
+ 
+   protected void addJvmArgumentsAndOptions(final List<String> commandLine, final String[] jvmArgsOpts) {
+     if (jvmArgsOpts != null) {
+       commandLine.addAll(Arrays.asList(jvmArgsOpts));
+     }
+   }
+ 
+   // Fix for Bug #47192 - "Causing the GemFire member (JVM process) to exit on OutOfMemoryErrors"
+   protected void addJvmOptionsForOutOfMemoryErrors(final List<String> commandLine) {
+     if (SystemUtils.isHotSpotVM()) {
+       if (SystemUtils.isWindows()) {
+         // ProcessBuilder "on Windows" needs every word (space separated) to be
+         // a different element in the array/list. See #47312. Need to study why!
+         commandLine.add("-XX:OnOutOfMemoryError=taskkill /F /PID %p");
+       }
+       else { // All other platforms (Linux, Mac OS X, UNIX, etc)
+         commandLine.add("-XX:OnOutOfMemoryError=kill -KILL %p");
+       }
+     }
+     else if (SystemUtils.isJ9VM()) {
+       // NOTE IBM states the following IBM J9 JVM command-line option/switch has side-effects on "performance",
+       // as noted in the reference documentation...
+       // http://publib.boulder.ibm.com/infocenter/javasdk/v6r0/index.jsp?topic=/com.ibm.java.doc.diagnostics.60/diag/appendixes/cmdline/commands_jvm.html
+       commandLine.add("-Xcheck:memory");
+     }
+     else if (SystemUtils.isJRockitVM()) {
+       // NOTE the following Oracle JRockit JVM documentation was referenced to identify the appropriate JVM option to
+       // set when handling OutOfMemoryErrors.
+       // http://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/optionXX.html
+       commandLine.add("-XXexitOnOutOfMemory");
+     }
+   }
+ 
+   protected void addMaxHeap(final List<String> commandLine, final String maxHeap) {
+     if (!StringUtils.isBlank(maxHeap)) {
+       commandLine.add("-Xmx" + maxHeap);
+       commandLine.add("-XX:+UseConcMarkSweepGC");
+       commandLine.add("-XX:CMSInitiatingOccupancyFraction=" + CMS_INITIAL_OCCUPANCY_FRACTION);
+       //commandLine.add("-XX:MinHeapFreeRatio=" + MINIMUM_HEAP_FREE_RATIO);
+     }
+   }
+ 
+   protected LocatorState locatorStatus(final File locatorPidFile, final int oldPid, final String memberName) {
+     final int newPid = readPid(locatorPidFile);
+ 
+     if (newPid != INVALID_PID && newPid != oldPid) {
+       LocatorState locatorState = new LocatorLauncher.Builder().setPid(newPid).build().status();
+ 
+       if (ObjectUtils.equals(locatorState.getMemberName(), memberName)) {
+         return locatorState;
+       }
+     }
+ 
+     return new LocatorState(new LocatorLauncher.Builder().build(), Status.NOT_RESPONDING);
+   }
+ 
+   protected LocatorState locatorStatus(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);
+   }
+ 
+   protected String readErrorStream(final Process process) throws IOException {
+     BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
+     StringBuilder message = new StringBuilder();
+ 
+     for (String line = reader.readLine(); line != null; line = reader.readLine()) {
+       message.append(line);
+       message.append(StringUtils.LINE_SEPARATOR);
+     }
+ 
+     IOUtils.close(reader);
+ 
+     return message.toString();
+   }
+ 
+   protected int readPid(final File pidFile) {
+     assert pidFile != null : "The file from which to read the process ID (pid) cannot be null!";
+ 
+     if (pidFile.isFile()) {
+       BufferedReader fileReader = null;
+       try {
+         fileReader = new BufferedReader(new FileReader(pidFile));
+         return Integer.parseInt(fileReader.readLine());
+       }
+       catch (IOException ignore) {
+       }
+       catch (NumberFormatException  ignore) {
+       }
+       finally {
+         IOUtils.close(fileReader);
+       }
+     }
+ 
+     return INVALID_PID;
+   }
+ 
+   protected ServerState serverStatus(final File serverPidFile, final int oldPid, final String memberName) {
+     final int newPid = readPid(serverPidFile);
+ 
+     if (newPid != INVALID_PID && newPid != oldPid) {
+       ServerState serverState = new ServerLauncher.Builder().setPid(newPid).setDisableDefaultServer(true)
+         .build().status();
+ 
+       if (ObjectUtils.equals(serverState.getMemberName(), memberName)) {
+         return serverState;
+       }
+     }
+ 
+     return new ServerState(new ServerLauncher.Builder().build(), Status.NOT_RESPONDING);
+   }
+ 
+   protected ServerState serverStatus(final String workingDirectory, final String memberName) {
+     ServerState serverState = new ServerLauncher.Builder().setWorkingDirectory(workingDirectory)
+       .setDisableDefaultServer(true).build().status();
+ 
+     if (ObjectUtils.equals(serverState.getMemberName(), memberName)) {
+       return serverState;
+     }
+ 
+     return new ServerState(new ServerLauncher.Builder().build(), Status.NOT_RESPONDING);
+   }
+ 
+   @Deprecated
+   protected String getClasspath(final String userClasspath) {
+     String classpath = getSystemClasspath();
+ 
+     if (!StringUtils.isBlank(userClasspath)) {
+       classpath += (File.pathSeparator + userClasspath);
+     }
+ 
+     return classpath;
+   }
+ 
+   protected String getLocatorClasspath(final boolean includeSystemClasspath, final String userClasspath) {
+     return toClasspath(includeSystemClasspath, new String[] { CORE_DEPENDENCIES_JAR_PATHNAME }, userClasspath);
+   }
+ 
+   protected String getServerClasspath(final boolean includeSystemClasspath,
+                                       final boolean includeSpringDependencies,
+                                       final String userClasspath)
+   {
+     List<String> jarFilePathnames = new ArrayList<>();
+ 
+     jarFilePathnames.add(CORE_DEPENDENCIES_JAR_PATHNAME);
+ 
+     if (includeSpringDependencies) {
+       jarFilePathnames.addAll(getSpringJars());
+     }
+ 
+     return toClasspath(includeSystemClasspath, jarFilePathnames.toArray(new String[jarFilePathnames.size()]),
+       userClasspath);
+   }
+ 
+   protected List<String> getSpringJars() {
+     File gemfireHomeDirectory= new File(GEMFIRE_HOME);
+ 
+     assertArgument(gemfireHomeDirectory.isDirectory(),
+       "Please set the GEMFIRE environment variable to the product installation directory.");
+ 
+     List<String> springJarFilePathnames = new ArrayList<>(SPRING_JAR_NAME_PREFIXES.size());
+ 
+     for (File jarFile : new File(gemfireHomeDirectory, "lib").listFiles(new FileFilter() {
+       @Override public boolean accept(final File pathname) {
+         return (pathname.getName().startsWith("spring-") && pathname.getAbsolutePath().endsWith(".jar"));
+       }
+     })) {
+       String jarFileName = jarFile.getName();
+       String jarFileNamePrefix = jarFileName.substring(0, jarFileName.lastIndexOf("-"));
+ 
+       if (SPRING_JAR_NAME_PREFIXES.contains(jarFileNamePrefix.toLowerCase().trim())) {
+         springJarFilePathnames.add(jarFile.getAbsolutePath());
+       }
+     }
+ 
+     assertState(springJarFilePathnames.size() == SPRING_JAR_NAME_PREFIXES.size(),
+       "Unable to find all the necessary Spring JAR files in $GEMFIRE/lib (%1$s): expected (%2$s); but was (%3$s)",
+         gemfireHomeDirectory, SPRING_JAR_NAME_PREFIXES, springJarFilePathnames);
+ 
+     return springJarFilePathnames;
+   }
+ 
+   protected String getSystemClasspath() {
+     return System.getProperty("java.class.path");
+   }
+ 
+   String toClasspath(final boolean includeSystemClasspath, String[] jarFilePathnames, String... userClasspaths) {
+     // gemfire jar must absolutely be the first JAR file on the CLASSPATH!!!
+     String classpath = getGemFireJarPath();
+ 
+     userClasspaths = (userClasspaths != null ? userClasspaths : StringUtils.EMPTY_STRING_ARRAY);
+ 
+     // Then, include user-specified classes on CLASSPATH to enable the user to override GemFire JAR dependencies
+     // with application-specific versions; this logic/block corresponds to classes/jar-files specified with the
+     // --classpath option to the 'start locator' and 'start server commands'; also this will override any
+     // System CLASSPATH environment variable setting, which is consistent with the Java platform behavior...
+     for (String userClasspath : userClasspaths) {
+       if (!StringUtils.isBlank(userClasspath)) {
+         classpath += (classpath.isEmpty() ? StringUtils.EMPTY_STRING : File.pathSeparator);
+         classpath += userClasspath;
+       }
+     }
+ 
+     // Now, include any System-specified CLASSPATH environment variable setting...
+     if (includeSystemClasspath) {
+       classpath += File.pathSeparator;
+       classpath += getSystemClasspath();
+     }
+ 
+     jarFilePathnames = (jarFilePathnames != null ? jarFilePathnames : StringUtils.EMPTY_STRING_ARRAY);
+ 
+     // And finally, include all GemFire dependencies on the CLASSPATH...
+     for (String jarFilePathname : jarFilePathnames) {
+       if (!StringUtils.isBlank(jarFilePathname)) {
+         classpath += (classpath.isEmpty() ? StringUtils.EMPTY_STRING : File.pathSeparator);
+         classpath += jarFilePathname;
+       }
+     }
+ 
+     return classpath;
+   }
+ 
+   protected String getGemFireJarPath() {
+     String classpath = getSystemClasspath();
+     String gemfireJarPath = GEMFIRE_JAR_PATHNAME;
+ 
+     for (String classpathElement : classpath.split(File.pathSeparator)) {
+       // MUST CHANGE THIS TO REGEX SINCE VERSION CHANGES IN JAR NAME
+       if (classpathElement.endsWith("gemfire-core-8.2.0.0-SNAPSHOT.jar")) {
+         gemfireJarPath = classpathElement;
+         break;
+       }
+     }
+ 
+     return gemfireJarPath;
+   }
+ 
+   protected String getJavaPath() {
+     return new File(new File(JAVA_HOME, "bin"), "java").getPath();
+   }
+ 
+   @Deprecated
+   protected String getToolsJarPath() throws AttachAPINotFoundException {
+     String toolsJarPathname = null;
+ 
+     if (!SystemUtils.isMacOSX()) {
+       toolsJarPathname = IOUtils.appendToPath(JAVA_HOME, "lib", "tools.jar");
+ 
+       if (!IOUtils.isExistingPathname(toolsJarPathname)) {
+         // perhaps the java.home System property refers to the JRE ($JAVA_HOME/jre)...
+         String JDK_HOME = new File(JAVA_HOME).getParentFile().getPath();
+         toolsJarPathname = IOUtils.appendToPath(JDK_HOME, "lib", "tools.jar");
+       }
+ 
+       try {
+         IOUtils.verifyPathnameExists(toolsJarPathname);
+       }
+       catch (IOException e) {
+         throw new AttachAPINotFoundException(getAttachAPINotFoundMessage());
+       }
+     }
+ 
+     return toolsJarPathname;
+   }
+ 
+   // TODO refactor the following method into a common base class or utility class
+   protected String getLocalHost() {
+     try {
+       return SocketCreator.getLocalHost().getCanonicalHostName();
+     }
+     catch (UnknownHostException ignore) {
+       return LOCALHOST;
+     }
+   }
+ 
+   protected String getAttachAPINotFoundMessage() {
+     return CliStrings.format(CliStrings.ATTACH_API_IN_0_NOT_FOUND_ERROR_MESSAGE,
+       ((SystemUtils.isMacOSX() && SystemUtils.isAppleJVM()) ? "classes.jar" : "tools.jar"));
+   }
+ 
+   protected String getLocatorId(final String host, final Integer port) {
+     final String locatorHost = (host != null ? host : getLocalHost());
+     final String locatorPort = StringUtils.valueOf(port, String.valueOf(DistributionLocator.DEFAULT_LOCATOR_PORT));
+     return locatorHost.concat("[").concat(locatorPort).concat("]");
+   }
+ 
+   /**
+    * Gets a proxy to the DistributedSystemMXBean from the GemFire Manager's MBeanServer, or null if unable to find
+    * the DistributedSystemMXBean.
+    * </p>
+    * @return a proxy to the DistributedSystemMXBean from the GemFire Manager's MBeanServer, or null if unable to find
+    * the DistributedSystemMXBean.
+    */
+   protected DistributedSystemMXBean getDistributedSystemMXBean() throws IOException, MalformedObjectNameException {
+     assertState(isConnectedAndReady(), "Gfsh must be connected in order to get proxy to a GemFire DistributedSystemMXBean.");
+     return getGfsh().getOperationInvoker().getDistributedSystemMXBean();
+   }
+ 
+   /**
+    * Gets a proxy to the MemberMXBean for the GemFire member specified by member name or ID from the GemFire Manager's
+    * MBeanServer.
+    * </p>
+    * @param member a String indicating the GemFire member's name or ID.
+    * @return a proxy to the MemberMXBean having the specified GemFire member's name or ID from the GemFire Manager's
+    * MBeanServer, or null if no GemFire member could be found with the specified member name or ID.
+    * @see #getMemberMXBean(String, String)
+    */
+   protected MemberMXBean getMemberMXBean(final String member) throws IOException {
+     return getMemberMXBean(null, member);
+   }
+ 
+   protected MemberMXBean getMemberMXBean(final String serviceName, final String member) throws IOException {
+     assertState(isConnectedAndReady(), "Gfsh must be connected in order to get proxy to a GemFire Member MBean.");
+ 
+     MemberMXBean memberBean = null;
+ 
+     try {
+       String objectNamePattern = ManagementConstants.OBJECTNAME__PREFIX;
+ 
+       objectNamePattern += (StringUtils.isBlank(serviceName) ? StringUtils.EMPTY_STRING
+         : "service=" + serviceName + StringUtils.COMMA_DELIMITER);
+       objectNamePattern += "type=Member,*";
+ 
+       // NOTE throws a MalformedObjectNameException, however, this should not happen since the ObjectName is constructed
+       // here in a conforming pattern
+       final ObjectName objectName = ObjectName.getInstance(objectNamePattern);
+ 
+       final QueryExp query = Query.or(
+         Query.eq(Query.attr("Name"), Query.value(member)),
+         Query.eq(Query.attr("Id"), Query.value(member))
+       );
+ 
+       final Set<ObjectName> memberObjectNames = getGfsh().getOperationInvoker().queryNames(objectName, query);
+ 
+       if (!memberObjectNames.isEmpty()) {
+         memberBean = getGfsh().getOperationInvoker().getMBeanProxy(memberObjectNames.iterator().next(), MemberMXBean.class);
+       }
+     }
+     catch (MalformedObjectNameException e) {
+       getGfsh().logSevere(e.getMessage(), e);
+     }
+ 
+     return memberBean;
+   }
+ 
+   protected String getServerId(final String host, final Integer port) {
+     String serverHost = (host != null ? host : getLocalHost());
+     String serverPort = StringUtils.valueOf(port, String.valueOf(CacheServer.DEFAULT_PORT));
+     return serverHost.concat("[").concat(serverPort).concat("]");
+   }
+ 
+   protected boolean isStartingNotRespondingOrNull(final ServiceState serviceState) {
+     return (serviceState == null || isStartingOrNotResponding(serviceState.getStatus()));
+   }
+ 
+   protected boolean isStartingOrNotResponding(final Status processStatus) {
+     return (Status.NOT_RESPONDING.equals(processStatus) || Status.STARTING.equals(processStatus));
+   }
+ 
+   protected boolean isVmWithProcessIdRunning(final Integer pid) {
+     // note: this will use JNA if available or Attach if available or return false if neither is available
+     return ProcessUtils.isProcessAlive(pid);
+   }
+ 
+   @CliCommand(value = CliStrings.START_SERVER, help = CliStrings.START_SERVER__HELP)
+   @CliMetaData(shellOnly = true, relatedTopic = { CliStrings.TOPIC_GEMFIRE_SERVER, CliStrings.TOPIC_GEMFIRE_LIFECYCLE })
++  @ResourceOperation(resource = Resource.DISTRIBUTED_SYSTEM, operation= ResourceConstants.LIST_DS)
+   public Result startServer(@CliOption(key = CliStrings.START_SERVER__ASSIGN_BUCKETS,
+                                       unspecifiedDefaultValue = "false",
+                                       specifiedDefaultValue = "true",
+                                       help = CliStrings.START_SERVER__ASSIGN_BUCKETS__HELP)
+                             final Boolean assignBuckets,
+                             @CliOption(key = CliStrings.START_SERVER__BIND_ADDRESS,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__BIND_ADDRESS__HELP)
+                             final String bindAddress,
+                             @CliOption(key = CliStrings.START_SERVER__CACHE_XML_FILE,
+                                       optionContext = ConverterHint.FILE_PATHSTRING,
+                                       unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                       help = CliStrings.START_SERVER__CACHE_XML_FILE__HELP)
+                             String cacheXmlPathname,
+                             @CliOption(key = CliStrings.START_SERVER__CLASSPATH,
+                                       /*optionContext = ConverterHint.FILE_PATHSTRING, // there's an issue with TAB here*/
+                                       unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                       help = CliStrings.START_SERVER__CLASSPATH__HELP)
+                             final String classpath,
+                             @CliOption(key = CliStrings.START_SERVER__CRITICAL__HEAP__PERCENTAGE,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__CRITICAL__HEAP__HELP)
+                             final Float criticalHeapPercentage,
+                             @CliOption(key = CliStrings.START_SERVER__CRITICAL_OFF_HEAP_PERCENTAGE,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__CRITICAL_OFF_HEAP__HELP)
+                             final Float criticalOffHeapPercentage,
+                             @CliOption(key = CliStrings.START_SERVER__DIR,
+                                        optionContext = ConverterHint.DIR_PATHSTRING,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__DIR__HELP)
+                             String workingDirectory,
+                             @CliOption(key = CliStrings.START_SERVER__DISABLE_DEFAULT_SERVER,
+                                       unspecifiedDefaultValue = "false",
+                                       specifiedDefaultValue = "true",
+                                       help = CliStrings.START_SERVER__DISABLE_DEFAULT_SERVER__HELP)
+                             final Boolean disableDefaultServer,
+                             @CliOption(key = CliStrings.START_SERVER__DISABLE_EXIT_WHEN_OUT_OF_MEMORY,
+                                       unspecifiedDefaultValue = "false",
+                                       specifiedDefaultValue = "true",
+                                       help = CliStrings.START_SERVER__DISABLE_EXIT_WHEN_OUT_OF_MEMORY_HELP)
+                             final Boolean disableExitWhenOutOfMemory,
+                             @CliOption(key = CliStrings.START_SERVER__ENABLE_TIME_STATISTICS,
+                                       unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                       specifiedDefaultValue = "true",
+                                       help = CliStrings.START_SERVER__ENABLE_TIME_STATISTICS__HELP)
+                             final Boolean enableTimeStatistics,
+                             @CliOption(key = CliStrings.START_SERVER__EVICTION__HEAP__PERCENTAGE,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__EVICTION__HEAP__PERCENTAGE__HELP)
+                             final Float evictionHeapPercentage,
+                             @CliOption(key = CliStrings.START_SERVER__EVICTION_OFF_HEAP_PERCENTAGE,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__EVICTION_OFF_HEAP_PERCENTAGE__HELP)
+                             final Float evictionOffHeapPercentage,
+                             @CliOption(key = CliStrings.START_SERVER__FORCE,
+                                       unspecifiedDefaultValue = "false",
+                                       specifiedDefaultValue = "true",
+                                       help = CliStrings.START_SERVER__FORCE__HELP)
+                             final Boolean force,
+                             @CliOption(key = CliStrings.START_SERVER__GROUP,
+                                        optionContext = ConverterHint.MEMBERGROUP,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__GROUP__HELP)
+                             final String group,
+                             @CliOption(key = CliStrings.START_SERVER__HOSTNAME__FOR__CLIENTS,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__HOSTNAME__FOR__CLIENTS__HELP)
+                             final String hostNameForClients,
+                             @CliOption(key = CliStrings.START_SERVER__INCLUDE_SYSTEM_CLASSPATH,
+                                       specifiedDefaultValue = "true",
+                                       unspecifiedDefaultValue = "false",
+                                       help = CliStrings.START_SERVER__INCLUDE_SYSTEM_CLASSPATH__HELP)
+                             final Boolean includeSystemClasspath,
+                             @CliOption(key = CliStrings.START_SERVER__INITIAL_HEAP,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__INITIAL_HEAP__HELP)
+                             final String initialHeap,
+                             @CliOption(key = CliStrings.START_SERVER__J,
+                                        optionContext = ConverterHint.STRING_LIST,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__J__HELP)
+                             @CliMetaData(valueSeparator = ",")
+                             final String[] jvmArgsOpts, 
+                             @CliOption(key = CliStrings.START_SERVER__LOCATORS,
+                                       optionContext = ConverterHint.LOCATOR_DISCOVERY_CONFIG,
+                                       unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                       help = CliStrings.START_SERVER__LOCATORS__HELP)
+                             final String locators,
+                             @CliOption(key = CliStrings.START_SERVER__LOCATOR_WAIT_TIME,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__LOCATOR_WAIT_TIME_HELP)
+                             final Integer locatorWaitTime,
+                             @CliOption(key = CliStrings.START_SERVER__LOCK_MEMORY,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        specifiedDefaultValue = "true",
+                                        help = CliStrings.START_SERVER__LOCK_MEMORY__HELP)
+                             final Boolean lockMemory,
+                             @CliOption(key = CliStrings.START_SERVER__LOG_LEVEL,
+                                       optionContext = ConverterHint.LOG_LEVEL,
+                                       unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                       help = CliStrings.START_SERVER__LOG_LEVEL__HELP)
+                             final String logLevel,
+                             @CliOption(key = CliStrings.START_SERVER__MAX__CONNECTIONS,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__MAX__CONNECTIONS__HELP)
+                             final Integer maxConnections,
+                             @CliOption(key = CliStrings.START_SERVER__MAXHEAP,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__MAXHEAP__HELP)
+                             final String maxHeap,
+                             @CliOption(key = CliStrings.START_SERVER__MAX__MESSAGE__COUNT,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__MAX__MESSAGE__COUNT__HELP)
+                             final Integer maxMessageCount,
+                             @CliOption(key = CliStrings.START_SERVER__MAX__THREADS,
+                                       unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                       help = CliStrings.START_SERVER__MAX__THREADS__HELP)
+                             final Integer maxThreads,
+                             @CliOption(key = CliStrings.START_SERVER__MCAST_ADDRESS,
+                                       unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                       help = CliStrings.START_SERVER__MCAST_ADDRESS__HELP)
+                             final String mcastBindAddress,
+                             @CliOption(key = CliStrings.START_SERVER__MCAST_PORT,
+                                       unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                       help = CliStrings.START_SERVER__MCAST_PORT__HELP)
+                             final Integer mcastPort,
+                             @CliOption(key = CliStrings.START_SERVER__MEMCACHED_PORT,
+                                       unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                       help = CliStrings.START_SERVER__MEMCACHED_PORT__HELP)
+                             final Integer memcachedPort,
+                             @CliOption(key = CliStrings.START_SERVER__MEMCACHED_PROTOCOL,
+                                       unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                       help = CliStrings.START_SERVER__MEMCACHED_PROTOCOL__HELP)
+                             final String memcachedProtocol,
+                             @CliOption(key = CliStrings.START_SERVER__MEMCACHED_BIND_ADDRESS,
+                                       unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                       help = CliStrings.START_SERVER__MEMCACHED_BIND_ADDRESS__HELP)
+                             final String memcachedBindAddress,
+                             @CliOption(key = CliStrings.START_SERVER__REDIS_PORT,
+                                       unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                       help = CliStrings.START_SERVER__REDIS_PORT__HELP)
+                             final Integer redisPort,
+                             @CliOption(key = CliStrings.START_SERVER__REDIS_BIND_ADDRESS,
+                                       unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                       help = CliStrings.START_SERVER__REDIS_BIND_ADDRESS__HELP)
+                             final String redisBindAddress,
+                             @CliOption(key = CliStrings.START_SERVER__REDIS_PASSWORD,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__REDIS_PASSWORD__HELP)
+                             final String redisPassword,
+                             @CliOption(key = CliStrings.START_SERVER__MESSAGE__TIME__TO__LIVE,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__MESSAGE__TIME__TO__LIVE__HELP)
+                             final Integer messageTimeToLive,
+                             @CliOption(key = CliStrings.START_SERVER__NAME,
+                                        mandatory = true,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__NAME__HELP)
+                             final String memberName,
+                             @CliOption(key = CliStrings.START_SERVER__OFF_HEAP_MEMORY_SIZE,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__OFF_HEAP_MEMORY_SIZE__HELP)
+                             final String offHeapMemorySize,
+                             @CliOption(key = CliStrings.START_SERVER__PROPERTIES,
+                                        optionContext = ConverterHint.FILE_PATHSTRING,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__PROPERTIES__HELP)
+                             String gemfirePropertiesPathname,
+                             @CliOption(key = CliStrings.START_SERVER__REBALANCE,
+                                       unspecifiedDefaultValue = "false",
+                                       specifiedDefaultValue = "true",
+                                       help = CliStrings.START_SERVER__REBALANCE__HELP)
+                             final Boolean rebalance,
+                             @CliOption(key = CliStrings.START_SERVER__SECURITY_PROPERTIES,
+                                        optionContext = ConverterHint.FILE_PATHSTRING,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__SECURITY_PROPERTIES__HELP)
+                             String gemfireSecurityPropertiesPathname,
+                             @CliOption(key = CliStrings.START_SERVER__SERVER_BIND_ADDRESS,
+                                       unspecifiedDefaultValue = CacheServer.DEFAULT_BIND_ADDRESS,
+                                       help = CliStrings.START_SERVER__SERVER_BIND_ADDRESS__HELP)
+                             final String serverBindAddress,
+                             @CliOption(key = CliStrings.START_SERVER__SERVER_PORT,
+                                       unspecifiedDefaultValue = ("" + CacheServer.DEFAULT_PORT),
+                                       help = CliStrings.START_SERVER__SERVER_PORT__HELP)
+                             final Integer serverPort,
+                             @CliOption(key = CliStrings.START_SERVER__SOCKET__BUFFER__SIZE,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__SOCKET__BUFFER__SIZE__HELP)
+                             final Integer socketBufferSize,
+                             @CliOption(key = CliStrings.START_SERVER__SPRING_XML_LOCATION,
+                                        unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                        help = CliStrings.START_SERVER__SPRING_XML_LOCATION_HELP)
+                             final String springXmlLocation,
+                             @CliOption(key = CliStrings.START_SERVER__STATISTIC_ARCHIVE_FILE,
+                                       unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+                                       help = CliStrings.START_SERVER__STATISTIC_ARCHIVE_FILE__HELP)
+                             final String statisticsArchivePathname,
+                             @CliOption(key = CliStrings.START_SERVER__USE_CLUSTER_CONFIGURATION,
+                                       unspecifiedDefaultValue = "true",
+                                       specifiedDefaultValue = "true",
+                                       help = CliStrings.START_SERVER__USE_CLUSTER_CONFIGURATION__HELP)
+                             final Boolean requestSharedConfiguration)
+                             // NOTICE: keep the parameters in alphabetical order based on their CliStrings.START_SERVER_* text
+   {
+ 
+     try {
+       if (workingDirectory == null) {
+         // attempt to use or make sub-directory using memberName...
+         File serverWorkingDirectory = new File(memberName);
+ 
+         if (!(serverWorkingDirectory.exists() || serverWorkingDirectory.mkdir())) {
+           throw new IllegalStateException(CliStrings.format(CliStrings.START_SERVER__MSG__COULD_NOT_CREATE_DIRECTORY_0_VERIFY_PERMISSIONS,
+             serverWorkingDirectory.getAbsolutePath()));
+         }
+ 
+         workingDirectory = IOUtils.tryGetCanonicalPathElseGetAbsolutePath(serverWorkingDirectory);
+       }
+ 
+       cacheXmlPathname = CliUtil.resolvePathname(cacheXmlPathname);
+ 
+       if (!StringUtils.isBlank(cacheXmlPathname) && !IOUtils.isExistingPathname(cacheXmlPathname)) {
+         return ResultBuilder.createUserErrorResult(CliStrings.format(CliStrings.CACHE_XML_NOT_FOUND_MESSAGE, cacheXmlPathname));
+       }
+ 
+       gemfirePropertiesPathname = CliUtil.resolvePathname(gemfirePropertiesPathname);
+ 
+       if (!StringUtils.isBlank(gemfirePropertiesPathname) && !IOUtils.isExistingPathname(gemfirePropertiesPathname)) {
+         return ResultBuilder.createUserErrorResult(CliStrings.format(CliStrings.GEMFIRE_0_PROPERTIES_1_NOT_FOUND_MESSAGE,
+           StringUtils.EMPTY_STRING, gemfirePropertiesPathname));
+       }
+ 
+       gemfireSecurityPropertiesPathname = CliUtil.resolvePathname(gemfireSecurityPropertiesPathname);
+ 
+       if (!StringUtils.isBlank(gemfireSecurityPropertiesPathname) && !IOUtils.isExistingPathname(gemfireSecurityPropertiesPathname)) {
+         return ResultBuilder.createUserErrorResult(CliStrings.format(CliStrings.GEMFIRE_0_PROPERTIES_1_NOT_FOUND_MESSAGE,
+           "Security ", gemfireSecurityPropertiesPathname));
+       }
+ 
+       File serverPidFile = new File(workingDirectory, ProcessType.SERVER.getPidFileName());
+ 
+     

<TRUNCATED>