You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2017/08/11 17:12:10 UTC

[12/14] geode git commit: GEODE-3413: overhaul launcher and process classes and tests

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/main/java/org/apache/geode/internal/process/FileProcessController.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/process/FileProcessController.java b/geode-core/src/main/java/org/apache/geode/internal/process/FileProcessController.java
index c8ec49d..062cfb6 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/process/FileProcessController.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/process/FileProcessController.java
@@ -14,13 +14,10 @@
  */
 package org.apache.geode.internal.process;
 
-import org.apache.commons.lang.StringUtils;
-import org.apache.geode.distributed.internal.DistributionConfig;
-import org.apache.geode.internal.i18n.LocalizedStrings;
-import org.apache.geode.internal.logging.LogService;
-import org.apache.geode.internal.process.ControlFileWatchdog.ControlRequestHandler;
-import org.apache.geode.lang.AttachAPINotFoundException;
-import org.apache.logging.log4j.Logger;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.apache.commons.lang.StringUtils.isBlank;
+import static org.apache.commons.lang.Validate.isTrue;
+import static org.apache.commons.lang.Validate.notNull;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -30,70 +27,72 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicReference;
 
+import org.apache.geode.internal.i18n.LocalizedStrings;
+import org.apache.geode.internal.process.ControlFileWatchdog.ControlRequestHandler;
+import org.apache.geode.lang.AttachAPINotFoundException;
+
 /**
  * Controls a {@link ControllableProcess} using files to communicate between processes.
  * 
  * @since GemFire 8.0
  */
-public class FileProcessController implements ProcessController {
-  private static final Logger logger = LogService.getLogger();
+class FileProcessController implements ProcessController {
 
-  public static final String STATUS_TIMEOUT_PROPERTY =
-      DistributionConfig.GEMFIRE_PREFIX + "FileProcessController.STATUS_TIMEOUT";
+  static final long DEFAULT_STATUS_TIMEOUT_MILLIS = 60 * 1000;
 
   private final long statusTimeoutMillis;
-  private final FileControllerParameters arguments;
+  private final FileControllerParameters parameters;
   private final int pid;
 
   /**
    * Constructs an instance for controlling a local process.
    * 
-   * @param arguments details about the controllable process
+   * @param parameters details about the controllable process
    * @param pid process id identifying the process to control
    * 
    * @throws IllegalArgumentException if pid is not a positive integer
    */
-  public FileProcessController(final FileControllerParameters arguments, final int pid) {
-    this(arguments, pid, Long.getLong(STATUS_TIMEOUT_PROPERTY, 60 * 1000), TimeUnit.MILLISECONDS);
+  FileProcessController(final FileControllerParameters parameters, final int pid) {
+    this(parameters, pid, DEFAULT_STATUS_TIMEOUT_MILLIS, MILLISECONDS);
   }
 
   /**
    * Constructs an instance for controlling a local process.
    * 
-   * @param arguments details about the controllable process
+   * @param parameters details about the controllable process
    * @param pid process id identifying the process to control
    * @param timeout the timeout that operations must complete within
    * @param units the units of the timeout
    * 
    * @throws IllegalArgumentException if pid is not a positive integer
    */
-  public FileProcessController(final FileControllerParameters arguments, final int pid,
+  FileProcessController(final FileControllerParameters parameters, final int pid,
       final long timeout, final TimeUnit units) {
-    if (pid < 1) {
-      throw new IllegalArgumentException("Invalid pid '" + pid + "' specified");
-    }
+    notNull(parameters, "Invalid parameters '" + parameters + "' specified");
+    isTrue(pid > 0, "Invalid pid '" + pid + "' specified");
+    isTrue(timeout >= 0, "Invalid timeout '" + timeout + "' specified");
+    notNull(units, "Invalid units '" + units + "' specified");
+
     this.pid = pid;
-    this.arguments = arguments;
+    this.parameters = parameters;
     this.statusTimeoutMillis = units.toMillis(timeout);
   }
 
   @Override
   public int getProcessId() {
-    return this.pid;
+    return pid;
   }
 
   @Override
   public String status()
       throws UnableToControlProcessException, IOException, InterruptedException, TimeoutException {
-    return status(this.arguments.getWorkingDirectory(),
-        this.arguments.getProcessType().getStatusRequestFileName(),
-        this.arguments.getProcessType().getStatusFileName());
+    return status(parameters.getDirectory(), parameters.getProcessType().getStatusRequestFileName(),
+        parameters.getProcessType().getStatusFileName());
   }
 
   @Override
   public void stop() throws UnableToControlProcessException, IOException {
-    stop(this.arguments.getWorkingDirectory(),
-        this.arguments.getProcessType().getStopRequestFileName());
+    stop(parameters.getDirectory(), parameters.getProcessType().getStopRequestFileName());
   }
 
   @Override
@@ -102,8 +101,12 @@ public class FileProcessController implements ProcessController {
         LocalizedStrings.Launcher_ATTACH_API_NOT_FOUND_ERROR_MESSAGE.toLocalizedString());
   }
 
+  long getStatusTimeoutMillis() {
+    return statusTimeoutMillis;
+  }
+
   private void stop(final File workingDir, final String stopRequestFileName) throws IOException {
-    final File stopRequestFile = new File(workingDir, stopRequestFileName);
+    File stopRequestFile = new File(workingDir, stopRequestFileName);
     if (!stopRequestFile.exists()) {
       stopRequestFile.createNewFile();
     }
@@ -112,56 +115,40 @@ public class FileProcessController implements ProcessController {
   private String status(final File workingDir, final String statusRequestFileName,
       final String statusFileName) throws IOException, InterruptedException, TimeoutException {
     // monitor for statusFile
-    final File statusFile = new File(workingDir, statusFileName);
-    final AtomicReference<String> statusRef = new AtomicReference<>();
-
-    final ControlRequestHandler statusHandler = new ControlRequestHandler() {
-      @Override
-      public void handleRequest() throws IOException {
-        // read the statusFile
-        final BufferedReader reader = new BufferedReader(new FileReader(statusFile));
-        final StringBuilder lines = new StringBuilder();
-        try {
-          String line = null;
-          while ((line = reader.readLine()) != null) {
-            lines.append(line);
-          }
-        } finally {
-          statusRef.set(lines.toString());
-          reader.close();
-        }
+    File statusFile = new File(workingDir, statusFileName);
+    AtomicReference<String> statusRef = new AtomicReference<>();
+
+    ControlRequestHandler statusHandler = () -> {
+      // read the statusFile
+      StringBuilder lines = new StringBuilder();
+      try (BufferedReader reader = new BufferedReader(new FileReader(statusFile))) {
+        reader.lines().forEach(lines::append);
+      } finally {
+        statusRef.set(lines.toString());
       }
     };
 
-    final ControlFileWatchdog statusFileWatchdog =
+    ControlFileWatchdog statusFileWatchdog =
         new ControlFileWatchdog(workingDir, statusFileName, statusHandler, true);
     statusFileWatchdog.start();
 
-    final File statusRequestFile = new File(workingDir, statusRequestFileName);
+    File statusRequestFile = new File(workingDir, statusRequestFileName);
     if (!statusRequestFile.exists()) {
       statusRequestFile.createNewFile();
     }
 
     // if timeout invoke stop and then throw TimeoutException
-    final long start = System.currentTimeMillis();
+    long start = System.currentTimeMillis();
     while (statusFileWatchdog.isAlive()) {
       Thread.sleep(10);
-      if (System.currentTimeMillis() >= start + this.statusTimeoutMillis) {
-        final TimeoutException te =
-            new TimeoutException("Timed out waiting for process to create " + statusFile);
-        try {
-          statusFileWatchdog.stop();
-        } catch (InterruptedException e) {
-          logger.info("Interrupted while stopping status file watchdog.", e);
-        } catch (RuntimeException e) {
-          logger.info("Unexpected failure while stopping status file watchdog.", e);
-        }
-        throw te;
+      if (System.currentTimeMillis() >= start + statusTimeoutMillis) {
+        statusFileWatchdog.stop();
+        throw new TimeoutException("Timed out waiting for process to create " + statusFile);
       }
     }
 
-    final String lines = statusRef.get();
-    if (StringUtils.isBlank(lines)) {
+    String lines = statusRef.get();
+    if (isBlank(lines)) {
       throw new IllegalStateException("Failed to read status file");
     }
     return lines;

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/main/java/org/apache/geode/internal/process/LocalProcessController.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/process/LocalProcessController.java b/geode-core/src/main/java/org/apache/geode/internal/process/LocalProcessController.java
deleted file mode 100755
index fbea19e..0000000
--- a/geode-core/src/main/java/org/apache/geode/internal/process/LocalProcessController.java
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.apache.geode.internal.process;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.lang.management.ManagementFactory;
-import java.lang.management.RuntimeMXBean;
-import java.util.Properties;
-import java.util.Set;
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanException;
-import javax.management.MBeanServerConnection;
-import javax.management.ObjectName;
-import javax.management.Query;
-import javax.management.QueryExp;
-import javax.management.ReflectionException;
-import javax.management.remote.JMXConnector;
-import javax.management.remote.JMXConnectorFactory;
-import javax.management.remote.JMXServiceURL;
-
-import org.apache.geode.internal.util.IOUtils;
-import com.sun.tools.attach.AgentInitializationException;
-import com.sun.tools.attach.AgentLoadException;
-import com.sun.tools.attach.AttachNotSupportedException;
-import com.sun.tools.attach.VirtualMachine;
-
-/**
- * Attaches to a local process to control it via JMX.
- * 
- * @since GemFire 7.0
- * @deprecated as of 8.0 please use {@link ControllableProcess} instead
- */
-public class LocalProcessController {
-
-  /** Property name for the JMX local connector address (from sun.management.Agent) */
-  private static final String LOCAL_CONNECTOR_ADDRESS_PROP =
-      "com.sun.management.jmxremote.localConnectorAddress";
-
-  private final int pid;
-
-  protected JMXConnector jmxc;
-  protected MBeanServerConnection server;
-
-  /**
-   * Constructs an instance for controlling a local process.
-   * 
-   * @param pid process id identifying the process to attach to
-   * 
-   * @throws IllegalArgumentException if pid is not a positive integer
-   */
-  public LocalProcessController(final int pid) {
-    if (pid < 1) {
-      throw new IllegalArgumentException("Invalid pid '" + pid + "' specified");
-    }
-    this.pid = pid;
-  }
-
-  /**
-   * Constructs an instance for controlling a local process.
-   * 
-   * @param pidFile file containing the pid of the process to attach to
-   * 
-   * @throws FileNotFoundException if the specified file name is not found within the directory
-   * @throws IOException if unable to read from the specified file
-   * @throws IllegalArgumentException if the pid in the pidFile is not a positive integer
-   * @throws NumberFormatException if the pid file does not contain a parsable integer
-   */
-  public LocalProcessController(final File pidFile) throws IOException {
-    this(readPid(pidFile));
-  }
-
-  /**
-   * Constructs an instance for controlling a local process.
-   * 
-   * @param directory directory containing a file of name pidFileName
-   * @param pidFilename name of the file containing the pid of the process to attach to
-   * 
-   * @throws FileNotFoundException if the specified file name is not found within the directory
-   * @throws IOException if an I/O error occurs
-   * @throws IllegalArgumentException if the pid in the pidFile is not a positive integer
-   * @throws IllegalStateException if dir is not an existing directory
-   * @throws NumberFormatException if the pid file does not contain a parsable integer
-   */
-  public LocalProcessController(final File directory, final String pidFilename) throws IOException {
-    this(readPid(directory, pidFilename));
-  }
-
-  /**
-   * Connects to the process and tells it to shut down.
-   * 
-   * @param namePattern the name pattern of the MBean to use for stopping
-   * @param pidAttribute the name of the MBean attribute with the process id to compare against
-   * @param stopMethod the name of the MBean operation to invoke
-   * @param attributes the names of the MBean attributes to compare with expected values
-   * @param values the expected values of the specified MBean attributes
-   *
-   * @throws ConnectionFailedException if there was a failure to connect to the local JMX connector
-   *         in the process
-   * @throws IOException if a communication problem occurred when talking to the MBean server
-   * @throws MBeanInvocationFailedException if failed to invoke stop on the MBean for any reason
-   * @throws PidUnavailableException if parsing the pid from the RuntimeMXBean name fails
-   */
-  public void stop(final ObjectName namePattern, final String pidAttribute, final String stopMethod,
-      final String[] attributes, final Object[] values) throws ConnectionFailedException,
-      IOException, MBeanInvocationFailedException, PidUnavailableException {
-    invokeOperationOnTargetMBean(namePattern, pidAttribute, stopMethod, attributes, values);
-  }
-
-  /**
-   * Connects to the process and acquires its status.
-   * 
-   * @param namePattern the name pattern of the MBean to use for stopping
-   * @param pidAttribute the name of the MBean attribute with the process id to compare against
-   * @param statusMethod the name of the MBean operation to invoke
-   * @param attributes the names of the MBean attributes to compare with expected values
-   * @param values the expected values of the specified MBean attributes
-   * 
-   * @return string describing the status of the process
-   *
-   * @throws ConnectionFailedException if there was a failure to connect to the local JMX connector
-   *         in the process
-   * @throws IOException if a communication problem occurred when talking to the MBean server
-   * @throws MBeanInvocationFailedException if failed to invoke stop on the MBean for any reason
-   * @throws PidUnavailableException if parsing the pid from the RuntimeMXBean name fails
-   */
-  public String status(final ObjectName namePattern, final String pidAttribute,
-      final String statusMethod, final String[] attributes, final Object[] values)
-      throws ConnectionFailedException, IOException, MBeanInvocationFailedException,
-      PidUnavailableException {
-    return invokeOperationOnTargetMBean(namePattern, pidAttribute, statusMethod, attributes, values)
-        .toString();
-  }
-
-  /**
-   * Connects to the process and use its MBean to stop it.
-   * 
-   * @param namePattern the name pattern of the MBean to use for stopping
-   * @param pidAttribute the name of the MBean attribute with the process id to compare against
-   * @param methodName the name of the MBean operation to invoke
-   * @param attributes the names of the MBean attributes to compare with expected values
-   * @param values the expected values of the specified MBean attributes
-   *
-   * @throws ConnectionFailedException if there was a failure to connect to the local JMX connector
-   *         in the process
-   * @throws IOException if a communication problem occurred when talking to the MBean server
-   * @throws MBeanInvocationFailedException if failed to invoke stop on the MBean for any reason
-   * @throws PidUnavailableException if parsing the pid from the RuntimeMXBean name fails
-   */
-  private Object invokeOperationOnTargetMBean(final ObjectName namePattern,
-      final String pidAttribute, final String methodName, final String[] attributes,
-      final Object[] values) throws ConnectionFailedException, IOException,
-      MBeanInvocationFailedException, PidUnavailableException {
-    ObjectName objectName = namePattern;
-    connect();
-    try {
-      final QueryExp constraint = buildQueryExp(pidAttribute, attributes, values);
-      final Set<ObjectName> mbeanNames = this.server.queryNames(namePattern, constraint);
-
-      if (mbeanNames.isEmpty()) {
-        throw new MBeanInvocationFailedException("Failed to find mbean matching '" + namePattern
-            + "' with attribute '" + pidAttribute + "' of value '" + this.pid + "'");
-      }
-      if (mbeanNames.size() > 1) {
-        throw new MBeanInvocationFailedException("Found more than one mbean matching '"
-            + namePattern + "' with attribute '" + pidAttribute + "' of value '" + this.pid + "'");
-      }
-
-      objectName = mbeanNames.iterator().next();
-      return invoke(objectName, methodName);
-    } catch (InstanceNotFoundException e) {
-      throw new MBeanInvocationFailedException(
-          "Failed to invoke " + methodName + " on " + objectName, e);
-    } catch (MBeanException e) {
-      throw new MBeanInvocationFailedException(
-          "Failed to invoke " + methodName + " on " + objectName, e);
-    } catch (ReflectionException e) {
-      throw new MBeanInvocationFailedException(
-          "Failed to invoke " + methodName + " on " + objectName, e);
-    } finally {
-      disconnect();
-    }
-  }
-
-  /**
-   * Returns the process id (pid) of the process.
-   * 
-   * @return the process id (pid) of the process
-   */
-  public int getProcessId() {
-    return this.pid;
-  }
-
-  /**
-   * Connects to the JMX agent in the local process.
-   * 
-   * @throws ConnectionFailedException if there was a failure to connect to the local JMX connector
-   *         in the process
-   * @throws IOException if the JDK management agent cannot be found and loaded
-   */
-  void connect() throws ConnectionFailedException, IOException {
-    try {
-      final JMXServiceURL jmxUrl = getJMXServiceURL();
-      this.jmxc = JMXConnectorFactory.connect(jmxUrl);
-      this.server = this.jmxc.getMBeanServerConnection();
-    } catch (AttachNotSupportedException e) {
-      throw new ConnectionFailedException("Failed to connect to process '" + this.pid + "'", e);
-    }
-  }
-
-  /**
-   * Disconnects from the JMX agent in the local process.
-   */
-  void disconnect() {
-    this.server = null;
-    if (this.jmxc != null) {
-      try {
-        this.jmxc.close();
-      } catch (IOException e) {
-        // ignore
-      }
-    }
-    this.jmxc = null;
-  }
-
-  /**
-   * Ensures that the other process identifies itself by the same pid used by this stopper to
-   * connect to that process. NOT USED EXCEPT IN TEST.
-   * 
-   * @return true if the pid matches
-   * 
-   * @throws IllegalStateException if the other process identifies itself by a different pid
-   * @throws IOException if a communication problem occurred when accessing the
-   *         MBeanServerConnection
-   * @throws PidUnavailableException if parsing the pid from the RuntimeMXBean name fails
-   */
-  boolean checkPidMatches() throws IllegalStateException, IOException, PidUnavailableException {
-    final RuntimeMXBean proxy = ManagementFactory.newPlatformMXBeanProxy(this.server,
-        ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class);
-    final int remotePid = ProcessUtils.identifyPid(proxy.getName());
-    if (remotePid != this.pid) {
-      throw new IllegalStateException(
-          "Process has different pid '" + remotePid + "' than expected pid '" + this.pid + "'");
-    } else {
-      return true;
-    }
-  }
-
-  /**
-   * Uses the Attach API to connect to the local process and ensures that it has loaded the JMX
-   * management agent. The JMXServiceURL identifying the local connector address for the JMX agent
-   * in the process is returned.
-   * 
-   * @return the address of the JMX API connector server for connecting to the local process
-   * 
-   * @throws AttachNotSupportedException if unable to use the Attach API to connect to the process
-   * @throws IOException if the JDK management agent cannot be found and loaded
-   */
-  private JMXServiceURL getJMXServiceURL() throws AttachNotSupportedException, IOException {
-    String connectorAddress = null;
-    final VirtualMachine vm = VirtualMachine.attach(String.valueOf(this.pid));
-    try {
-      Properties agentProps = vm.getAgentProperties();
-      connectorAddress = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
-
-      if (connectorAddress == null) {
-        // need to load the management-agent and get the address
-
-        final String javaHome = vm.getSystemProperties().getProperty("java.home");
-
-        // assume java.home is JDK and look in JRE for agent
-        String managementAgentPath = javaHome + File.separator + "jre" + File.separator + "lib"
-            + File.separator + "management-agent.jar";
-        File managementAgent = new File(managementAgentPath);
-        if (!managementAgent.exists()) {
-          // assume java.home is JRE and look in lib for agent
-          managementAgentPath =
-              javaHome + File.separator + "lib" + File.separator + "management-agent.jar";
-          managementAgent = new File(managementAgentPath);
-          if (!managementAgent.exists()) {
-            throw new IOException("JDK management agent not found");
-          }
-        }
-
-        // attempt to load the management agent
-        managementAgentPath = managementAgent.getCanonicalPath();
-        try {
-          vm.loadAgent(managementAgentPath, "com.sun.management.jmxremote");
-        } catch (AgentLoadException e) {
-          IOException ioe = new IOException(e.getMessage());
-          ioe.initCause(e);
-          throw ioe;
-        } catch (AgentInitializationException e) {
-          IOException ioe = new IOException(e.getMessage());
-          ioe.initCause(e);
-          throw ioe;
-        }
-
-        // get the connector address
-        agentProps = vm.getAgentProperties();
-        connectorAddress = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
-      }
-    } finally {
-      vm.detach();
-    }
-
-    if (connectorAddress == null) {
-      // should never reach here
-      throw new IOException("Failed to find address to attach to process");
-    }
-
-    return new JMXServiceURL(connectorAddress);
-  }
-
-  /**
-   * Builds the QueryExp used to identify the target MBean.
-   * 
-   * @param pidAttribute the name of the MBean attribute with the process id to compare against
-   * @param attributes the names of additional MBean attributes to compare with expected values
-   * @param values the expected values of the specified MBean attributes
-   *
-   * @return the main QueryExp for matching the target MBean
-   */
-  private QueryExp buildQueryExp(final String pidAttribute, final String[] attributes,
-      final Object[] values) {
-    final QueryExp optionalAttributes = buildOptionalQueryExp(attributes, values);
-    QueryExp constraint;
-    if (optionalAttributes != null) {
-      constraint =
-          Query.and(optionalAttributes, Query.eq(Query.attr(pidAttribute), Query.value(this.pid)));
-    } else {
-      constraint = Query.eq(Query.attr(pidAttribute), Query.value(this.pid));
-    }
-    return constraint;
-  }
-
-  /**
-   * Builds an optional QueryExp to aid in matching the correct MBean using additional attributes
-   * with the specified values. Returns null if no attributes and values were specified during
-   * construction.
-   * 
-   * @param attributes the names of additional MBean attributes to compare with expected values
-   * @param values the expected values of the specified MBean attributes
-   *
-   * @return optional QueryExp to aid in matching the correct MBean
-   */
-  private QueryExp buildOptionalQueryExp(final String[] attributes, final Object[] values) {
-    QueryExp queryExp = null;
-    for (int i = 0; i < attributes.length; i++) {
-      if (values[i] instanceof Boolean) {
-        if (queryExp == null) {
-          queryExp = Query.eq(Query.attr(attributes[i]), Query.value(((Boolean) values[i])));
-        } else {
-          queryExp = Query.and(queryExp,
-              Query.eq(Query.attr(attributes[i]), Query.value(((Boolean) values[i]))));
-        }
-      } else if (values[i] instanceof Number) {
-        if (queryExp == null) {
-          queryExp = Query.eq(Query.attr(attributes[i]), Query.value((Number) values[i]));
-        } else {
-          queryExp = Query.and(queryExp,
-              Query.eq(Query.attr(attributes[i]), Query.value((Number) values[i])));
-        }
-      } else if (values[i] instanceof String) {
-        if (queryExp == null) {
-          queryExp = Query.eq(Query.attr(attributes[i]), Query.value((String) values[i]));
-        } else {
-          queryExp = Query.and(queryExp,
-              Query.eq(Query.attr(attributes[i]), Query.value((String) values[i])));
-        }
-      }
-    }
-    return queryExp;
-  }
-
-  /**
-   * Invokes an operation on the specified MBean.
-   * 
-   * @param objectName identifies the MBean
-   * @param method the name of the operation method invoke
-   * 
-   * @return the result of invoking the operation on the MBean specified or null
-   * 
-   * @throws InstanceNotFoundException if the specified MBean is not registered in the MBean server
-   * @throws IOException if a communication problem occurred when talking to the MBean server
-   * @throws MBeanException if the MBean operation throws an exception
-   * @throws ReflectionException if the MBean does not have the specified operation
-   */
-  private Object invoke(final ObjectName objectName, final String method)
-      throws InstanceNotFoundException, IOException, MBeanException, ReflectionException {
-    return this.server.invoke(objectName, method, new Object[] {}, new String[] {});
-  }
-
-  /**
-   * Reads in the pid from the specified file.
-   * 
-   * @param pidFile the file containing the pid of the process to stop
-   * 
-   * @return the process id (pid) contained within the pidFile
-   * 
-   * @throws IllegalArgumentException if the pid in the pidFile is not a positive integer
-   * @throws IOException if unable to read from the specified file
-   * @throws NumberFormatException if the pid file does not contain a parsable integer
-   */
-  private static int readPid(final File pidFile) throws IOException {
-    BufferedReader fileReader = null;
-    String pidValue = null;
-
-    try {
-      fileReader = new BufferedReader(new FileReader(pidFile));
-      pidValue = fileReader.readLine();
-
-      final int pid = Integer.parseInt(pidValue);
-
-      if (pid < 1) {
-        throw new IllegalArgumentException("Invalid pid '" + pid + "' found in " + pidFile);
-      }
-
-      return pid;
-    } catch (NumberFormatException e) {
-      throw new IllegalArgumentException("Invalid pid '" + pidValue + "' found in " + pidFile);
-    } finally {
-      IOUtils.close(fileReader);
-    }
-  }
-
-  /**
-   * Reads in the pid from the named file contained within the specified directory.
-   * 
-   * @param directory directory containing a file of name pidFileName
-   * @param pidFilename name of the file containing the pid of the process to stop
-   * 
-   * @return the process id (pid) contained within the pidFile
-   * 
-   * @throws FileNotFoundException if the specified file name is not found within the directory
-   * @throws IllegalArgumentException if the pid in the pidFile is not a positive integer
-   * @throws IllegalStateException if dir is not an existing directory
-   * @throws IOException if an I/O error occurs
-   * @throws NumberFormatException if the pid file does not contain a parsable integer
-   */
-  private static int readPid(final File directory, final String pidFilename) throws IOException {
-    if (!directory.isDirectory() && directory.exists()) {
-      throw new IllegalArgumentException(
-          "Argument '" + directory + "' must be an existing directory!");
-    }
-
-    final File[] files = directory.listFiles(new FilenameFilter() {
-      @Override
-      public boolean accept(File file, String filename) {
-        return filename.equals(pidFilename);
-      }
-    });
-
-    if (files.length == 0) {
-      throw new FileNotFoundException(
-          "Unable to find PID file '" + pidFilename + "' in directory " + directory);
-    }
-
-    return readPid(files[0]);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/main/java/org/apache/geode/internal/process/LocalProcessLauncher.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/process/LocalProcessLauncher.java b/geode-core/src/main/java/org/apache/geode/internal/process/LocalProcessLauncher.java
index 04809c2..598a75e 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/process/LocalProcessLauncher.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/process/LocalProcessLauncher.java
@@ -14,16 +14,21 @@
  */
 package org.apache.geode.internal.process;
 
-import org.apache.geode.distributed.internal.DistributionConfig;
+import static org.apache.commons.lang.Validate.notNull;
+import static org.apache.geode.internal.process.ProcessUtils.identifyPid;
 
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
 
+import org.apache.geode.distributed.internal.DistributionConfig;
+
 /**
  * Creates a pid file and writes the process id to the pid file.
- * <p/>
+ *
+ * <p>
  * Related articles and libraries:
+ *
  * <ul>
  * <li>http://barelyenough.org/blog/2005/03/java-daemon/
  * <li>http://stackoverflow.com/questions/534648/how-to-daemonize-a-java-program
@@ -31,12 +36,13 @@ import java.io.IOException;
  * <li>http://wrapper.tanukisoftware.com/
  * <li>http://weblogs.java.net/blog/kohsuke/archive/2009/01/writing_a_unix.html
  * <li>http://www.enderunix.org/docs/eng/daemon.php
+ * </ul>
  * 
  * @since GemFire 7.0
  */
-public class LocalProcessLauncher {
+class LocalProcessLauncher {
 
-  public static final String PROPERTY_IGNORE_IS_PID_ALIVE =
+  static final String PROPERTY_IGNORE_IS_PID_ALIVE =
       DistributionConfig.GEMFIRE_PREFIX + "test.LocalProcessLauncher.ignoreIsPidAlive";
 
   private final int pid;
@@ -55,9 +61,11 @@ public class LocalProcessLauncher {
    * 
    * @see java.lang.management.RuntimeMXBean
    */
-  public LocalProcessLauncher(final File pidFile, final boolean force)
+  LocalProcessLauncher(final File pidFile, final boolean force)
       throws FileAlreadyExistsException, IOException, PidUnavailableException {
-    this.pid = ProcessUtils.identifyPid();
+    notNull(pidFile, "Invalid pidFile '" + pidFile + "' specified");
+
+    this.pid = identifyPid();
     this.pidFile = pidFile;
     writePid(force);
   }
@@ -67,8 +75,8 @@ public class LocalProcessLauncher {
    * 
    * @return the process id (pid)
    */
-  public int getPid() {
-    return this.pid;
+  int getPid() {
+    return pid;
   }
 
   /**
@@ -76,15 +84,28 @@ public class LocalProcessLauncher {
    * 
    * @return the pid file
    */
-  public File getPidFile() {
-    return this.pidFile;
+  File getPidFile() {
+    return pidFile;
   }
 
   /**
    * Delete the pid file now. {@link java.io.File#deleteOnExit()} is set on the pid file.
+   *
    */
   void close() {
-    this.pidFile.delete();
+    pidFile.delete();
+  }
+
+  /**
+   * Delete the pid file now. {@link java.io.File#deleteOnExit()} is set on the pid file.
+   *
+   * @param deletePidFileOnClose if true then the pid file will be deleted now instead of during JVM
+   *        exit
+   */
+  void close(final boolean deletePidFileOnClose) {
+    if (deletePidFileOnClose) {
+      pidFile.delete();
+    }
   }
 
   /**
@@ -96,30 +117,44 @@ public class LocalProcessLauncher {
    * @throws IOException if unable to create or write to the file
    */
   private void writePid(final boolean force) throws FileAlreadyExistsException, IOException {
-    final boolean created = this.pidFile.createNewFile();
-    if (!created && !force) {
-      int otherPid = 0;
-      try {
-        otherPid = ProcessUtils.readPid(this.pidFile);
-      } catch (IOException e) {
-        // suppress
-      } catch (NumberFormatException e) {
-        // suppress
-      }
-      boolean ignorePidFile = false;
-      if (otherPid != 0 && !ignoreIsPidAlive()) {
-        ignorePidFile = !ProcessUtils.isProcessAlive(otherPid);
-      }
-      if (!ignorePidFile) {
-        throw new FileAlreadyExistsException("Pid file already exists: " + this.pidFile + " for "
-            + (otherPid > 0 ? "process " + otherPid : "unknown process"));
+    if (pidFile.exists()) {
+      if (!force) {
+        checkOtherPid(readOtherPid());
       }
+      pidFile.delete();
+    }
+
+    File tempPidFile = new File(pidFile.getParent(), pidFile.getName() + ".tmp");
+    tempPidFile.createNewFile();
+
+    try (FileWriter writer = new FileWriter(tempPidFile)) {
+      writer.write(String.valueOf(pid));
+      writer.flush();
     }
-    this.pidFile.deleteOnExit();
-    final FileWriter writer = new FileWriter(this.pidFile);
-    writer.write(String.valueOf(this.pid));
-    writer.flush();
-    writer.close();
+
+    tempPidFile.renameTo(pidFile);
+    pidFile.deleteOnExit();
+  }
+
+  private int readOtherPid() {
+    int otherPid = 0;
+    try {
+      otherPid = ProcessUtils.readPid(pidFile);
+    } catch (NumberFormatException | IOException ignore) {
+      // suppress
+    }
+    return otherPid;
+  }
+
+  private void checkOtherPid(final int otherPid) throws FileAlreadyExistsException {
+    if (ignoreIsPidAlive() || otherPid != 0 && isProcessAlive(otherPid)) {
+      throw new FileAlreadyExistsException("Pid file already exists: " + pidFile + " for "
+          + (otherPid > 0 ? "process " + otherPid : "unknown process"));
+    }
+  }
+
+  private boolean isProcessAlive(final int pid) {
+    return ignoreIsPidAlive() || ProcessUtils.isProcessAlive(pid);
   }
 
   private static boolean ignoreIsPidAlive() {

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/main/java/org/apache/geode/internal/process/MBeanControllerParameters.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/process/MBeanControllerParameters.java b/geode-core/src/main/java/org/apache/geode/internal/process/MBeanControllerParameters.java
index 857c52d..2ea0fa4 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/process/MBeanControllerParameters.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/process/MBeanControllerParameters.java
@@ -25,15 +25,16 @@ import org.apache.geode.internal.process.ProcessController.Arguments;
  * @since GemFire 8.0
  */
 interface MBeanControllerParameters extends Arguments {
-  public ObjectName getNamePattern();
 
-  public String getPidAttribute();
+  ObjectName getNamePattern();
 
-  public String getStatusMethod();
+  String getPidAttribute();
 
-  public String getStopMethod();
+  String getStatusMethod();
 
-  public String[] getAttributes();
+  String getStopMethod();
 
-  public Object[] getValues();
+  String[] getAttributes();
+
+  Object[] getValues();
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/main/java/org/apache/geode/internal/process/MBeanInvocationFailedException.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/process/MBeanInvocationFailedException.java b/geode-core/src/main/java/org/apache/geode/internal/process/MBeanInvocationFailedException.java
index 724a4d7..d4ba3ec 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/process/MBeanInvocationFailedException.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/process/MBeanInvocationFailedException.java
@@ -23,23 +23,23 @@ public class MBeanInvocationFailedException extends Exception {
   private static final long serialVersionUID = 7991096466859690801L;
 
   /**
-   * Creates a new <code>MBeanInvocationFailedException</code>.
+   * Creates a new {@code MBeanInvocationFailedException}.
    */
   public MBeanInvocationFailedException(final String message) {
     super(message);
   }
 
   /**
-   * Creates a new <code>MBeanInvocationFailedException</code> that was caused by a given exception
+   * Creates a new {@code MBeanInvocationFailedException} that was caused by a given exception
    */
-  public MBeanInvocationFailedException(final String message, final Throwable thr) {
-    super(message, thr);
+  public MBeanInvocationFailedException(final String message, final Throwable cause) {
+    super(message, cause);
   }
 
   /**
-   * Creates a new <code>MBeanInvocationFailedException</code> that was caused by a given exception
+   * Creates a new {@code MBeanInvocationFailedException} that was caused by a given exception
    */
-  public MBeanInvocationFailedException(final Throwable thr) {
-    super(thr.getMessage(), thr);
+  public MBeanInvocationFailedException(final Throwable cause) {
+    super(cause.getMessage(), cause);
   }
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/main/java/org/apache/geode/internal/process/MBeanProcessController.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/process/MBeanProcessController.java b/geode-core/src/main/java/org/apache/geode/internal/process/MBeanProcessController.java
index ea5946e..1a19719 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/process/MBeanProcessController.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/process/MBeanProcessController.java
@@ -14,10 +14,11 @@
  */
 package org.apache.geode.internal.process;
 
+import static org.apache.commons.lang.Validate.isTrue;
+import static org.apache.commons.lang.Validate.notNull;
+
 import java.io.File;
 import java.io.IOException;
-import java.lang.management.ManagementFactory;
-import java.lang.management.RuntimeMXBean;
 import java.util.Properties;
 import java.util.Set;
 
@@ -42,17 +43,20 @@ import com.sun.tools.attach.VirtualMachine;
  * 
  * @since GemFire 8.0
  */
-public class MBeanProcessController implements ProcessController {
+class MBeanProcessController implements ProcessController {
 
   /** Property name for the JMX local connector address (from sun.management.Agent) */
-  private static final String LOCAL_CONNECTOR_ADDRESS_PROP =
+  private static final String PROPERTY_LOCAL_CONNECTOR_ADDRESS =
       "com.sun.management.jmxremote.localConnectorAddress";
 
+  private static final Object[] PARAMS = {};
+  private static final String[] SIGNATURE = {};
+
   private final MBeanControllerParameters arguments;
   private final int pid;
 
-  protected JMXConnector jmxc;
-  protected MBeanServerConnection server;
+  private JMXConnector jmxc;
+  private MBeanServerConnection server;
 
   /**
    * Constructs an instance for controlling a local process.
@@ -61,36 +65,37 @@ public class MBeanProcessController implements ProcessController {
    * 
    * @throws IllegalArgumentException if pid is not a positive integer
    */
-  public MBeanProcessController(final MBeanControllerParameters arguments, final int pid) {
-    if (pid < 1) {
-      throw new IllegalArgumentException("Invalid pid '" + pid + "' specified");
-    }
+  MBeanProcessController(final MBeanControllerParameters arguments, final int pid) {
+    notNull(arguments, "Invalid arguments '" + arguments + "' specified");
+    isTrue(pid > 0, "Invalid pid '" + pid + "' specified");
+
     this.pid = pid;
     this.arguments = arguments;
   }
 
   @Override
   public int getProcessId() {
-    return this.pid;
+    return pid;
   }
 
   @Override
   public String status() throws UnableToControlProcessException, ConnectionFailedException,
       IOException, MBeanInvocationFailedException {
-    return status(this.arguments.getNamePattern(), this.arguments.getPidAttribute(),
-        this.arguments.getStatusMethod(), this.arguments.getAttributes(),
-        this.arguments.getValues());
+    return status(arguments.getNamePattern(), arguments.getPidAttribute(),
+        arguments.getStatusMethod(), arguments.getAttributes(), arguments.getValues());
   }
 
   @Override
   public void stop() throws UnableToControlProcessException, ConnectionFailedException, IOException,
       MBeanInvocationFailedException {
-    stop(this.arguments.getNamePattern(), this.arguments.getPidAttribute(),
-        this.arguments.getStopMethod(), this.arguments.getAttributes(), this.arguments.getValues());
+    stop(arguments.getNamePattern(), arguments.getPidAttribute(), arguments.getStopMethod(),
+        arguments.getAttributes(), arguments.getValues());
   }
 
   @Override
-  public void checkPidSupport() {}
+  public void checkPidSupport() {
+    // nothing
+  }
 
   /**
    * Connects to the process and tells it to shut down.
@@ -156,27 +161,21 @@ public class MBeanProcessController implements ProcessController {
     ObjectName objectName = namePattern;
     connect();
     try {
-      final QueryExp constraint = buildQueryExp(pidAttribute, attributes, values);
-      final Set<ObjectName> mbeanNames = this.server.queryNames(namePattern, constraint);
+      QueryExp constraint = buildQueryExp(pidAttribute, attributes, values);
+      Set<ObjectName> mbeanNames = server.queryNames(namePattern, constraint);
 
       if (mbeanNames.isEmpty()) {
         throw new MBeanInvocationFailedException("Failed to find mbean matching '" + namePattern
-            + "' with attribute '" + pidAttribute + "' of value '" + this.pid + "'");
+            + "' with attribute '" + pidAttribute + "' of value '" + pid + "'");
       }
       if (mbeanNames.size() > 1) {
         throw new MBeanInvocationFailedException("Found more than one mbean matching '"
-            + namePattern + "' with attribute '" + pidAttribute + "' of value '" + this.pid + "'");
+            + namePattern + "' with attribute '" + pidAttribute + "' of value '" + pid + "'");
       }
 
       objectName = mbeanNames.iterator().next();
       return invoke(objectName, methodName);
-    } catch (InstanceNotFoundException e) {
-      throw new MBeanInvocationFailedException(
-          "Failed to invoke " + methodName + " on " + objectName, e);
-    } catch (MBeanException e) {
-      throw new MBeanInvocationFailedException(
-          "Failed to invoke " + methodName + " on " + objectName, e);
-    } catch (ReflectionException e) {
+    } catch (InstanceNotFoundException | MBeanException | ReflectionException e) {
       throw new MBeanInvocationFailedException(
           "Failed to invoke " + methodName + " on " + objectName, e);
     } finally {
@@ -193,11 +192,11 @@ public class MBeanProcessController implements ProcessController {
    */
   private void connect() throws ConnectionFailedException, IOException {
     try {
-      final JMXServiceURL jmxUrl = getJMXServiceURL();
-      this.jmxc = JMXConnectorFactory.connect(jmxUrl);
-      this.server = this.jmxc.getMBeanServerConnection();
+      JMXServiceURL jmxUrl = getJMXServiceURL();
+      jmxc = JMXConnectorFactory.connect(jmxUrl);
+      server = jmxc.getMBeanServerConnection();
     } catch (AttachNotSupportedException e) {
-      throw new ConnectionFailedException("Failed to connect to process '" + this.pid + "'", e);
+      throw new ConnectionFailedException("Failed to connect to process '" + pid + "'", e);
     }
   }
 
@@ -205,38 +204,15 @@ public class MBeanProcessController implements ProcessController {
    * Disconnects from the JMX agent in the local process.
    */
   private void disconnect() {
-    this.server = null;
-    if (this.jmxc != null) {
+    server = null;
+    if (jmxc != null) {
       try {
-        this.jmxc.close();
-      } catch (IOException e) {
+        jmxc.close();
+      } catch (IOException ignored) {
         // ignore
       }
     }
-    this.jmxc = null;
-  }
-
-  /**
-   * Ensures that the other process identifies itself by the same pid used by this stopper to
-   * connect to that process. NOT USED EXCEPT IN TEST.
-   * 
-   * @return true if the pid matches
-   * 
-   * @throws IllegalStateException if the other process identifies itself by a different pid
-   * @throws IOException if a communication problem occurred when accessing the
-   *         MBeanServerConnection
-   * @throws PidUnavailableException if parsing the pid from the RuntimeMXBean name fails
-   */
-  boolean checkPidMatches() throws IllegalStateException, IOException, PidUnavailableException {
-    final RuntimeMXBean proxy = ManagementFactory.newPlatformMXBeanProxy(this.server,
-        ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class);
-    final int remotePid = ProcessUtils.identifyPid(proxy.getName());
-    if (remotePid != this.pid) {
-      throw new IllegalStateException(
-          "Process has different pid '" + remotePid + "' than expected pid '" + this.pid + "'");
-    } else {
-      return true;
-    }
+    jmxc = null;
   }
 
   /**
@@ -250,16 +226,16 @@ public class MBeanProcessController implements ProcessController {
    * @throws IOException if the JDK management agent cannot be found and loaded
    */
   private JMXServiceURL getJMXServiceURL() throws AttachNotSupportedException, IOException {
-    String connectorAddress = null;
-    final VirtualMachine vm = VirtualMachine.attach(String.valueOf(this.pid));
+    String connectorAddress;
+    VirtualMachine vm = VirtualMachine.attach(String.valueOf(pid));
     try {
       Properties agentProps = vm.getAgentProperties();
-      connectorAddress = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
+      connectorAddress = agentProps.getProperty(PROPERTY_LOCAL_CONNECTOR_ADDRESS);
 
       if (connectorAddress == null) {
         // need to load the management-agent and get the address
 
-        final String javaHome = vm.getSystemProperties().getProperty("java.home");
+        String javaHome = vm.getSystemProperties().getProperty("java.home");
 
         // assume java.home is JDK and look in JRE for agent
         String managementAgentPath = javaHome + File.separator + "jre" + File.separator + "lib"
@@ -279,19 +255,13 @@ public class MBeanProcessController implements ProcessController {
         managementAgentPath = managementAgent.getCanonicalPath();
         try {
           vm.loadAgent(managementAgentPath, "com.sun.management.jmxremote");
-        } catch (AgentLoadException e) {
-          IOException ioe = new IOException(e.getMessage());
-          ioe.initCause(e);
-          throw ioe;
-        } catch (AgentInitializationException e) {
-          IOException ioe = new IOException(e.getMessage());
-          ioe.initCause(e);
-          throw ioe;
+        } catch (AgentLoadException | AgentInitializationException e) {
+          throw new IOException(e);
         }
 
         // get the connector address
         agentProps = vm.getAgentProperties();
-        connectorAddress = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
+        connectorAddress = agentProps.getProperty(PROPERTY_LOCAL_CONNECTOR_ADDRESS);
       }
     } finally {
       vm.detach();
@@ -316,13 +286,13 @@ public class MBeanProcessController implements ProcessController {
    */
   private QueryExp buildQueryExp(final String pidAttribute, final String[] attributes,
       final Object[] values) {
-    final QueryExp optionalAttributes = buildOptionalQueryExp(attributes, values);
+    QueryExp optionalAttributes = buildOptionalQueryExp(attributes, values);
     QueryExp constraint;
     if (optionalAttributes != null) {
       constraint =
-          Query.and(optionalAttributes, Query.eq(Query.attr(pidAttribute), Query.value(this.pid)));
+          Query.and(optionalAttributes, Query.eq(Query.attr(pidAttribute), Query.value(pid)));
     } else {
-      constraint = Query.eq(Query.attr(pidAttribute), Query.value(this.pid));
+      constraint = Query.eq(Query.attr(pidAttribute), Query.value(pid));
     }
     return constraint;
   }
@@ -342,10 +312,10 @@ public class MBeanProcessController implements ProcessController {
     for (int i = 0; i < attributes.length; i++) {
       if (values[i] instanceof Boolean) {
         if (queryExp == null) {
-          queryExp = Query.eq(Query.attr(attributes[i]), Query.value(((Boolean) values[i])));
+          queryExp = Query.eq(Query.attr(attributes[i]), Query.value((Boolean) values[i]));
         } else {
           queryExp = Query.and(queryExp,
-              Query.eq(Query.attr(attributes[i]), Query.value(((Boolean) values[i]))));
+              Query.eq(Query.attr(attributes[i]), Query.value((Boolean) values[i])));
         }
       } else if (values[i] instanceof Number) {
         if (queryExp == null) {
@@ -381,6 +351,6 @@ public class MBeanProcessController implements ProcessController {
    */
   private Object invoke(final ObjectName objectName, final String method)
       throws InstanceNotFoundException, IOException, MBeanException, ReflectionException {
-    return this.server.invoke(objectName, method, new Object[] {}, new String[] {});
+    return server.invoke(objectName, method, PARAMS, SIGNATURE);
   }
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/main/java/org/apache/geode/internal/process/NativeProcessUtils.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/process/NativeProcessUtils.java b/geode-core/src/main/java/org/apache/geode/internal/process/NativeProcessUtils.java
index 34cf81f..cea73de 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/process/NativeProcessUtils.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/process/NativeProcessUtils.java
@@ -14,6 +14,8 @@
  */
 package org.apache.geode.internal.process;
 
+import static org.apache.commons.lang.Validate.isTrue;
+
 import org.apache.geode.internal.process.ProcessUtils.InternalProcessUtils;
 import org.apache.geode.internal.shared.NativeCalls;
 
@@ -24,17 +26,19 @@ import org.apache.geode.internal.shared.NativeCalls;
  */
 class NativeProcessUtils implements InternalProcessUtils {
 
-  private final static NativeCalls nativeCalls = NativeCalls.getInstance();
-
-  NativeProcessUtils() {}
+  private static final NativeCalls nativeCalls = NativeCalls.getInstance();
 
   @Override
-  public boolean isProcessAlive(int pid) {
+  public boolean isProcessAlive(final int pid) {
+    isTrue(pid > 0, "Invalid pid '" + pid + "' specified");
+
     return nativeCalls.isProcessActive(pid);
   }
 
   @Override
-  public boolean killProcess(int pid) {
+  public boolean killProcess(final int pid) {
+    isTrue(pid > 0, "Invalid pid '" + pid + "' specified");
+
     return nativeCalls.killProcess(pid);
   }
 

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/main/java/org/apache/geode/internal/process/NonBlockingProcessStreamReader.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/process/NonBlockingProcessStreamReader.java b/geode-core/src/main/java/org/apache/geode/internal/process/NonBlockingProcessStreamReader.java
index d5c1116..9096fae 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/process/NonBlockingProcessStreamReader.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/process/NonBlockingProcessStreamReader.java
@@ -30,7 +30,7 @@ import org.apache.geode.internal.util.StopWatch;
  * 
  * @since GemFire 8.2
  */
-public class NonBlockingProcessStreamReader extends ProcessStreamReader {
+class NonBlockingProcessStreamReader extends ProcessStreamReader {
   private static final Logger logger = LogService.getLogger();
 
   /**
@@ -39,61 +39,65 @@ public class NonBlockingProcessStreamReader extends ProcessStreamReader {
    */
   private final long continueReadingMillis;
 
-  protected NonBlockingProcessStreamReader(final Builder builder) {
+  private final StopWatch continueReading;
+
+  private StringBuilder stringBuilder;
+  private int character;
+  private boolean ready;
+
+  NonBlockingProcessStreamReader(final Builder builder) {
     super(builder);
-    continueReadingMillis = builder.continueReadingMillis;
+
+    this.continueReadingMillis = builder.continueReadingMillis;
+    this.continueReading = new StopWatch();
+    this.stringBuilder = new StringBuilder();
+    this.character = 0;
+    this.ready = false;
   }
 
   @Override
   public void run() {
-    final boolean isDebugEnabled = logger.isDebugEnabled();
-    if (isDebugEnabled) {
-      logger.debug("Running {}", this);
-    }
-    StopWatch continueReading = new StopWatch();
-    BufferedReader reader = null;
-    try {
-      reader = new BufferedReader(new InputStreamReader(inputStream));
-      StringBuilder sb = new StringBuilder();
-      boolean ready = false;
-      int ch = 0;
-      while (ch != -1) {
-        while ((ready = reader.ready()) && (ch = reader.read()) != -1) {
-          sb.append((char) ch);
-          if ((char) ch == '\n') {
-            this.inputListener.notifyInputLine(sb.toString());
-            sb = new StringBuilder();
-          }
-        }
-        if (!ready) {
-          if (!ProcessUtils.isProcessAlive(process)) {
-            if (!continueReading.isRunning()) {
-              continueReading.start();
-            } else if (continueReading.elapsedTimeMillis() > continueReadingMillis) {
-              return;
-            }
-          }
-          Thread.sleep(10);
+    try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
+      while (character != -1) {
+        readWhileReady(reader);
+        if (shouldTerminate()) {
+          break;
         }
       }
     } catch (IOException e) {
-      if (isDebugEnabled) {
+      if (logger.isDebugEnabled()) {
         logger.debug("Failure reading from buffered input stream: {}", e.getMessage(), e);
       }
     } catch (InterruptedException e) {
-      if (isDebugEnabled) {
+      if (logger.isDebugEnabled()) {
         logger.debug("Interrupted reading from buffered input stream: {}", e.getMessage(), e);
       }
-    } finally {
-      try {
-        reader.close();
-      } catch (IOException e) {
-        if (isDebugEnabled) {
-          logger.debug("Failure closing buffered input stream reader: {}", e.getMessage(), e);
-        }
+    }
+  }
+
+  private boolean shouldTerminate() throws InterruptedException {
+    if (!ProcessUtils.isProcessAlive(process)) {
+      if (!continueReading.isRunning()) {
+        continueReading.start();
+      } else if (continueReading.elapsedTimeMillis() > continueReadingMillis) {
+        return true;
       }
-      if (isDebugEnabled) {
-        logger.debug("Terminating {}", this);
+    }
+    Thread.sleep(10);
+    return false;
+  }
+
+  /**
+   * This is a hot reader while there are characters ready to read. As soon as there are no more
+   * characters to read, it returns and the loop invokes shouldTerminate which has a 10 millisecond
+   * sleep until there are more characters ready to read.
+   */
+  private void readWhileReady(BufferedReader reader) throws IOException {
+    while ((ready = reader.ready()) && (character = reader.read()) != -1) {
+      stringBuilder.append((char) character);
+      if ((char) character == '\n') {
+        this.inputListener.notifyInputLine(stringBuilder.toString());
+        stringBuilder = new StringBuilder();
       }
     }
   }

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/main/java/org/apache/geode/internal/process/PidFile.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/process/PidFile.java b/geode-core/src/main/java/org/apache/geode/internal/process/PidFile.java
index 291c202..0e7adf2 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/process/PidFile.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/process/PidFile.java
@@ -14,17 +14,15 @@
  */
 package org.apache.geode.internal.process;
 
+import static org.apache.commons.lang.Validate.isTrue;
+import static org.apache.commons.lang.Validate.notEmpty;
+import static org.apache.commons.lang.Validate.notNull;
+
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
-import java.io.FilenameFilter;
 import java.io.IOException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.apache.geode.internal.util.IOUtils;
-import org.apache.geode.internal.util.StopWatch;
 
 /**
  * File wrapper that adds support for reading process id (pid) from a pid file written to disk by
@@ -34,8 +32,6 @@ import org.apache.geode.internal.util.StopWatch;
  */
 public class PidFile {
 
-  private static final long SLEEP_INTERVAL_MILLIS = 10;
-
   private final File pidFile;
 
   /**
@@ -43,17 +39,13 @@ public class PidFile {
    * 
    * @param file the file containing the pid of the process
    * 
-   * @throws FileNotFoundException if the specified file name is not found within the directory
+   * @throws IllegalArgumentException if the specified file is null or does not exist
    */
-  public PidFile(final File file) throws FileNotFoundException {
-    if (!file.exists() || !file.isFile()) {
-      throw new FileNotFoundException("Unable to find PID file '" + file + "'");
-    }
-    this.pidFile = file;
-  }
+  public PidFile(final File file) {
+    notNull(file, "Invalid file '" + file + "' specified");
+    isTrue(file.exists(), "Nonexistent file '" + file + "' specified");
 
-  File getFile() {
-    return this.pidFile;
+    this.pidFile = file;
   }
 
   /**
@@ -62,19 +54,19 @@ public class PidFile {
    * @param directory directory containing a file of name pidFileName
    * @param filename name of the file containing the pid of the process to stop
    * 
-   * @throws FileNotFoundException if the specified file name is not found within the directory
-   * @throws IllegalStateException if dir is not an existing directory
+   * @throws FileNotFoundException if the specified filename is not found within the directory
+   * @throws IllegalArgumentException if directory is null, does not exist or is not a directory
    */
   public PidFile(final File directory, final String filename) throws FileNotFoundException {
-    if (!directory.isDirectory() && directory.exists()) {
-      throw new IllegalArgumentException(
-          "Argument '" + directory + "' must be an existing directory!");
-    }
+    notNull(directory, "Invalid directory '" + directory + "' specified");
+    notEmpty(filename, "Invalid filename '" + filename + "' specified");
+    isTrue(directory.isDirectory() && directory.exists(),
+        "Nonexistent directory '" + directory + "' specified");
 
-    final File file = new File(directory, filename);
+    File file = new File(directory, filename);
     if (!file.exists() || file.isDirectory()) {
       throw new FileNotFoundException(
-          "Unable to find PID file '" + filename + "' in directory " + directory);
+          "Unable to find PID file '" + filename + "' in directory '" + directory + "'");
     }
 
     this.pidFile = file;
@@ -89,81 +81,26 @@ public class PidFile {
    * @throws IOException if unable to read from the specified file
    */
   public int readPid() throws IOException {
-    BufferedReader fileReader = null;
     String pidValue = null;
-
-    try {
-      fileReader = new BufferedReader(new FileReader(this.pidFile));
+    try (BufferedReader fileReader = new BufferedReader(new FileReader(pidFile))) {
       pidValue = fileReader.readLine();
 
-      final int pid = Integer.parseInt(pidValue);
+      int pid = Integer.parseInt(pidValue);
 
       if (pid < 1) {
         throw new IllegalArgumentException(
-            "Invalid pid '" + pid + "' found in " + this.pidFile.getCanonicalPath());
+            "Invalid pid '" + pid + "' found in " + pidFile.getCanonicalPath());
       }
 
       return pid;
-    } catch (NumberFormatException e) {
+    } catch (NumberFormatException ignored) {
       throw new IllegalArgumentException(
-          "Invalid pid '" + pidValue + "' found in " + this.pidFile.getCanonicalPath());
-    } finally {
-      IOUtils.close(fileReader);
+          "Invalid pid '" + pidValue + "' found in " + pidFile.getCanonicalPath());
     }
   }
 
-  /**
-   * Reads in the pid from the specified file, retrying until the specified timeout.
-   * 
-   * @param timeout the maximum time to spend trying to read the pidFile
-   * @param unit the unit of timeout
-   * 
-   * @return the process id (pid) contained within the pidFile
-   * 
-   * @throws IllegalArgumentException if the pid in the pidFile is not a positive integer
-   * @throws IOException if unable to read from the specified file
-   * @throws InterruptedException if interrupted
-   * @throws TimeoutException if operation times out
-   */
-  public int readPid(final long timeout, final TimeUnit unit)
-      throws IOException, InterruptedException, TimeoutException {
-    IllegalArgumentException iae = null;
-    IOException ioe = null;
-    int pid = 0;
-
-    final long timeoutMillis = unit.toMillis(timeout);
-    final StopWatch stopWatch = new StopWatch(true);
-
-    while (pid <= 0) {
-      try {
-        pid = readPid();
-      } catch (IllegalArgumentException e) {
-        iae = e;
-      } catch (IOException e) {
-        ioe = e;
-      }
-      if (stopWatch.elapsedTimeMillis() > timeoutMillis) {
-        if (iae != null) {
-          throw new TimeoutException(iae.getMessage());
-        }
-        if (ioe != null) {
-          throw new TimeoutException(ioe.getMessage());
-        }
-      } else {
-        try {
-          Thread.sleep(SLEEP_INTERVAL_MILLIS);
-        } catch (InterruptedException e) {
-          Thread.currentThread().interrupt();
-          if (iae != null) {
-            throw new InterruptedException(iae.getMessage());
-          }
-          if (ioe != null) {
-            throw new InterruptedException(ioe.getMessage());
-          }
-          throw e;
-        }
-      }
-    }
-    return pid;
+  File getFile() {
+    return pidFile;
   }
+
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/main/java/org/apache/geode/internal/process/PidUnavailableException.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/process/PidUnavailableException.java b/geode-core/src/main/java/org/apache/geode/internal/process/PidUnavailableException.java
index 6fa1c9f..934e65c 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/process/PidUnavailableException.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/process/PidUnavailableException.java
@@ -24,23 +24,23 @@ public class PidUnavailableException extends Exception {
   private static final long serialVersionUID = -1660269538268828059L;
 
   /**
-   * Creates a new <code>PidUnavailableException</code>.
+   * Creates a new {@code PidUnavailableException}.
    */
   public PidUnavailableException(final String message) {
     super(message);
   }
 
   /**
-   * Creates a new <code>PidUnavailableException</code> that was caused by a given exception
+   * Creates a new {@code PidUnavailableException} that was caused by a given exception
    */
-  public PidUnavailableException(final String message, final Throwable thr) {
-    super(message, thr);
+  public PidUnavailableException(final String message, final Throwable cause) {
+    super(message, cause);
   }
 
   /**
-   * Creates a new <code>PidUnavailableException</code> that was caused by a given exception
+   * Creates a new {@code PidUnavailableException} that was caused by a given exception
    */
-  public PidUnavailableException(final Throwable thr) {
-    super(thr.getMessage(), thr);
+  public PidUnavailableException(final Throwable cause) {
+    super(cause.getMessage(), cause);
   }
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/main/java/org/apache/geode/internal/process/ProcessController.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/process/ProcessController.java b/geode-core/src/main/java/org/apache/geode/internal/process/ProcessController.java
index 2aa4732..2e5cb0c 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/process/ProcessController.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/process/ProcessController.java
@@ -27,19 +27,19 @@ public interface ProcessController {
   /**
    * Returns the status of a running GemFire {@link ControllableProcess}.
    */
-  public String status() throws UnableToControlProcessException, ConnectionFailedException,
-      IOException, MBeanInvocationFailedException, InterruptedException, TimeoutException;
+  String status() throws UnableToControlProcessException, ConnectionFailedException, IOException,
+      MBeanInvocationFailedException, InterruptedException, TimeoutException;
 
   /**
    * Stops a running GemFire {@link ControllableProcess}.
    */
-  public void stop() throws UnableToControlProcessException, ConnectionFailedException, IOException,
+  void stop() throws UnableToControlProcessException, ConnectionFailedException, IOException,
       MBeanInvocationFailedException;
 
   /**
    * Returns the PID of a running GemFire {@link ControllableProcess}.
    */
-  public int getProcessId();
+  int getProcessId();
 
   /**
    * Checks if {@link #status} and {@link #stop} are supported if only the PID is provided. Only the
@@ -48,14 +48,15 @@ public interface ProcessController {
    * 
    * @throws org.apache.geode.lang.AttachAPINotFoundException if the Attach API is not found
    */
-  public void checkPidSupport();
+  void checkPidSupport();
 
   /**
    * Defines the arguments that a client must provide to the ProcessController.
    */
-  static interface Arguments {
-    public int getProcessId();
+  interface Arguments {
 
-    public ProcessType getProcessType();
+    int getProcessId();
+
+    ProcessType getProcessType();
   }
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/main/java/org/apache/geode/internal/process/ProcessControllerFactory.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/process/ProcessControllerFactory.java b/geode-core/src/main/java/org/apache/geode/internal/process/ProcessControllerFactory.java
index 38fdcf8..ef276c3 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/process/ProcessControllerFactory.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/process/ProcessControllerFactory.java
@@ -14,13 +14,16 @@
  */
 package org.apache.geode.internal.process;
 
-import org.apache.geode.distributed.internal.DistributionConfig;
+import static org.apache.commons.lang.Validate.isTrue;
+import static org.apache.commons.lang.Validate.notEmpty;
+import static org.apache.commons.lang.Validate.notNull;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
+import org.apache.geode.distributed.internal.DistributionConfig;
+
 /**
  * Manages which implementation of {@link ProcessController} will be used and constructs the
  * instance.
@@ -29,6 +32,9 @@ import java.util.concurrent.TimeoutException;
  */
 public class ProcessControllerFactory {
 
+  /**
+   * For testing only
+   */
   public static final String PROPERTY_DISABLE_ATTACH_API =
       DistributionConfig.GEMFIRE_PREFIX + "test.ProcessControllerFactory.DisableAttachApi";
 
@@ -38,64 +44,44 @@ public class ProcessControllerFactory {
     this.disableAttachApi = Boolean.getBoolean(PROPERTY_DISABLE_ATTACH_API);
   }
 
-  public ProcessController createProcessController(final ProcessControllerParameters arguments,
+  public ProcessController createProcessController(final ProcessControllerParameters parameters,
       final int pid) {
-    if (arguments == null) {
-      throw new NullPointerException("ProcessControllerParameters must not be null");
-    }
-    if (pid < 1) {
-      throw new IllegalArgumentException("Invalid pid '" + pid + "' specified");
-    }
-    try {
-      if (isAttachAPIFound()) {
-        return new MBeanProcessController((MBeanControllerParameters) arguments, pid);
-      } else {
-        return new FileProcessController((FileControllerParameters) arguments, pid);
+    notNull(parameters, "Invalid parameters '" + parameters + "' specified");
+    isTrue(pid > 0, "Invalid pid '" + pid + "' specified");
+
+    if (isAttachAPIFound()) {
+      try {
+        return new MBeanProcessController(parameters, pid);
+      } catch (ExceptionInInitializerError ignore) {
       }
-    } catch (final ExceptionInInitializerError e) {
-      // LOGGER.warn("Attach API class not found", e);
     }
-    return null;
+    return new FileProcessController(parameters, pid);
   }
 
-  public ProcessController createProcessController(final ProcessControllerParameters arguments,
-      final File pidFile, final long timeout, final TimeUnit unit)
+  public ProcessController createProcessController(final ProcessControllerParameters parameters,
+      final File directory, final String pidFileName)
       throws IOException, InterruptedException, TimeoutException {
-    if (arguments == null) {
-      throw new NullPointerException("ProcessControllerParameters must not be null");
-    }
-    if (pidFile == null) {
-      throw new NullPointerException("Pid file must not be null");
-    }
-    return createProcessController(arguments, new PidFile(pidFile).readPid(timeout, unit));
-  }
+    notNull(parameters, "Invalid parameters '" + parameters + "' specified");
+    notNull(directory, "Invalid directory '" + directory + "' specified");
+    notEmpty(pidFileName, "Invalid pidFileName '" + pidFileName + "' specified");
 
-  public ProcessController createProcessController(final ProcessControllerParameters arguments,
-      final File directory, final String pidFilename, final long timeout, final TimeUnit unit)
-      throws IOException, InterruptedException, TimeoutException {
-    if (arguments == null) {
-      throw new NullPointerException("ProcessControllerParameters must not be null");
-    }
-    if (directory == null) {
-      throw new NullPointerException("Directory must not be null");
-    }
-    if (pidFilename == null) {
-      throw new NullPointerException("Pid file name must not be null");
-    }
-    return createProcessController(arguments,
-        new PidFile(directory, pidFilename).readPid(timeout, unit));
+    return createProcessController(parameters, readPid(directory, pidFileName));
   }
 
   public boolean isAttachAPIFound() {
-    if (this.disableAttachApi) {
+    if (disableAttachApi) {
       return false;
     }
     boolean found = false;
     try {
       final Class<?> virtualMachineClass = Class.forName("com.sun.tools.attach.VirtualMachine");
       found = virtualMachineClass != null;
-    } catch (ClassNotFoundException e) {
+    } catch (ClassNotFoundException ignore) {
     }
     return found;
   }
+
+  private int readPid(final File directory, final String pidFileName) throws IOException {
+    return new PidFile(directory, pidFileName).readPid();
+  }
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/main/java/org/apache/geode/internal/process/ProcessControllerParameters.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/process/ProcessControllerParameters.java b/geode-core/src/main/java/org/apache/geode/internal/process/ProcessControllerParameters.java
index eb3deb9..a20faf1 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/process/ProcessControllerParameters.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/process/ProcessControllerParameters.java
@@ -15,10 +15,10 @@
 package org.apache.geode.internal.process;
 
 /**
- * Defines the methods for providing input arguments to the <code>ProcessController</code>.
+ * Defines the methods for providing input arguments to the {@code ProcessController}.
  * 
- * Implementations of <code>ProcessController</code> are in this package. Classes that implement
- * <code>ProcessControllerArguments</code> would typically be in a different package.
+ * Implementations of {@code ProcessController} are in this package. Classes that implement
+ * {@code ProcessController} would typically be in a different package.
  * 
  * @since GemFire 8.0
  */

http://git-wip-us.apache.org/repos/asf/geode/blob/894f3ee7/geode-core/src/main/java/org/apache/geode/internal/process/ProcessLauncherContext.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/process/ProcessLauncherContext.java b/geode-core/src/main/java/org/apache/geode/internal/process/ProcessLauncherContext.java
index 463fd18..9b10550 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/process/ProcessLauncherContext.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/process/ProcessLauncherContext.java
@@ -12,16 +12,14 @@
  * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
-
 package org.apache.geode.internal.process;
 
-import org.apache.geode.distributed.internal.DistributionConfig;
-import org.apache.geode.internal.io.TeeOutputStream;
-import org.apache.geode.internal.io.TeePrintStream;
+import static org.apache.commons.lang.Validate.notNull;
 
-import java.io.*;
 import java.util.Properties;
 
+import org.apache.geode.distributed.internal.DistributionConfig;
+
 /**
  * Thread based context for launching a process. GemFire internals can acquire optional
  * configuration details from a process launcher via this context.
@@ -43,8 +41,11 @@ public class ProcessLauncherContext {
    */
   private static final Properties OVERRIDDEN_DEFAULTS_DEFAULT = new Properties();
 
-  private static final ThreadLocal<ProcessLauncherContext> DATA =
-      new ThreadLocal<ProcessLauncherContext>();
+  private static final ThreadLocal<ProcessLauncherContext> DATA = new ThreadLocal<>();
+
+  private final boolean redirectOutput;
+  private final Properties overriddenDefaults;
+  private final StartupStatusListener startupListener;
 
   private static ProcessLauncherContext get() {
     return DATA.get();
@@ -56,7 +57,7 @@ public class ProcessLauncherContext {
    * @return true if this process should redirect output to the system log
    */
   public static boolean isRedirectingOutput() {
-    final ProcessLauncherContext context = get();
+    ProcessLauncherContext context = get();
     if (context == null) {
       return REDIRECT_OUTPUT_DEFAULT;
     }
@@ -71,16 +72,15 @@ public class ProcessLauncherContext {
    * @return the contingent gemfire properties values to be used as an alternative default value
    */
   public static Properties getOverriddenDefaults() {
-    final ProcessLauncherContext context = get();
+    ProcessLauncherContext context = get();
     if (context == null) {
       return OVERRIDDEN_DEFAULTS_DEFAULT;
     }
     return context.overriddenDefaults();
   }
 
-
   public static StartupStatusListener getStartupListener() {
-    final ProcessLauncherContext context = get();
+    ProcessLauncherContext context = get();
     if (context == null) {
       return null;
     }
@@ -91,9 +91,12 @@ public class ProcessLauncherContext {
   /**
    * Sets the ProcessLauncherContext data for the calling thread.
    */
-  public static void set(final boolean redirectOutput, final Properties contingentProperties,
+  public static void set(final boolean redirectOutput, final Properties overriddenDefaults,
       final StartupStatusListener startupListener) {
-    DATA.set(new ProcessLauncherContext(redirectOutput, contingentProperties, startupListener));
+    notNull(overriddenDefaults,
+        "Invalid overriddenDefaults '" + overriddenDefaults + "' specified");
+
+    DATA.set(new ProcessLauncherContext(redirectOutput, overriddenDefaults, startupListener));
     installLogListener(startupListener);
   }
 
@@ -101,12 +104,11 @@ public class ProcessLauncherContext {
    * Clears the current ProcessLauncherContext for the calling thread.
    */
   public static void remove() {
-    // DATA.get().restoreErrorStream();
     DATA.remove();
     clearLogListener();
   }
 
-  private static void installLogListener(StartupStatusListener startupListener) {
+  private static void installLogListener(final StartupStatusListener startupListener) {
     if (startupListener != null) {
       StartupStatus.setListener(startupListener);
     }
@@ -116,11 +118,6 @@ public class ProcessLauncherContext {
     StartupStatus.clearListener();
   }
 
-  private final boolean redirectOutput;
-  private final Properties overriddenDefaults;
-  private final StartupStatusListener startupListener;
-  private PrintStream err;
-
   private ProcessLauncherContext(final boolean redirectOutput, final Properties overriddenDefaults,
       final StartupStatusListener startupListener) {
     this.redirectOutput = redirectOutput;
@@ -129,39 +126,14 @@ public class ProcessLauncherContext {
   }
 
   private boolean redirectOutput() {
-    return this.redirectOutput;
+    return redirectOutput;
   }
 
   private Properties overriddenDefaults() {
-    return this.overriddenDefaults;
+    return overriddenDefaults;
   }
 
   private StartupStatusListener startupListener() {
-    return this.startupListener;
-  }
-
-  @SuppressWarnings("unused")
-  private void teeErrorStream() {
-    final FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
-    this.err = new PrintStream(new BufferedOutputStream(fdErr, 128), true);
-    System.setErr(new TeePrintStream(new TeeOutputStream(new BufferedOutputStream(fdErr, 128))));
-  }
-
-  @SuppressWarnings("unused")
-  private void restoreErrorStream() {
-    if (System.err instanceof TeePrintStream) {
-      final TeePrintStream tee = ((TeePrintStream) System.err);
-      final OutputStream branch = tee.getTeeOutputStream().getBranchOutputStream();
-
-      PrintStream newStdErr = null;
-      if (branch == null) {
-        newStdErr = this.err;
-      } else if (branch instanceof PrintStream) {
-        newStdErr = (PrintStream) branch;
-      } else {
-        newStdErr = new PrintStream(new BufferedOutputStream(branch, 128), true);
-      }
-      System.setErr(newStdErr);
-    }
+    return startupListener;
   }
 }