You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ji...@apache.org on 2017/03/04 00:04:14 UTC

[4/7] geode git commit: GEODE-2267: enable gfsh to download file from http connection (GEODE-2418)

GEODE-2267: enable gfsh to download file from http connection (GEODE-2418)


Project: http://git-wip-us.apache.org/repos/asf/geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/92582fbd
Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/92582fbd
Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/92582fbd

Branch: refs/heads/develop
Commit: 92582fbde6e8feb2c119bbdf937ee91a62946277
Parents: 4c6f369
Author: Jinmei Liao <ji...@pivotal.io>
Authored: Tue Feb 21 15:54:12 2017 -0800
Committer: Jinmei Liao <ji...@pivotal.io>
Committed: Fri Mar 3 16:03:50 2017 -0800

----------------------------------------------------------------------
 .../geode/management/cli/CliMetaData.java       |   8 +
 .../cli/AbstractCliAroundInterceptor.java       |   4 +-
 .../internal/cli/CliAroundInterceptor.java      |  26 +++-
 .../geode/management/internal/cli/CliUtil.java  |  12 +-
 .../management/internal/cli/CommandRequest.java |  15 +-
 .../cli/commands/MiscellaneousCommands.java     | 137 ++++++++++-------
 .../cli/functions/ExportLogsFunction.java       |   7 +-
 .../internal/cli/i18n/CliStrings.java           |  30 +++-
 .../cli/shell/GfshExecutionStrategy.java        |  59 +++++---
 .../cli/util/ExportLogsCacheWriter.java         |  10 +-
 .../internal/cli/util/ExportLogsRepository.java |  22 ++-
 .../management/internal/cli/util/MergeLogs.java |  15 +-
 .../MiscellaneousCommandsController.java        |  27 +++-
 .../web/shell/AbstractHttpOperationInvoker.java |  51 +++++--
 .../web/shell/RestHttpOperationInvoker.java     |  34 +++--
 .../web/shell/SimpleHttpOperationInvoker.java   |  12 +-
 .../internal/cli/CommandRequestTest.java        |  16 +-
 .../internal/cli/commands/ExportLogsDUnit.java  |  55 +++----
 .../ExportLogsOnServerManagerDUnit.java         |  91 +++++++++++
 .../ExportLogsFunctionIntegrationTest.java      |   8 +-
 .../internal/cli/util/LogExporterTest.java      |   6 -
 .../internal/cli/util/MergeLogsDUnitTest.java   | 113 ++++++++++++++
 .../internal/cli/util/MergeLogsTest.java        | 114 --------------
 .../security/GfshCommandsSecurityTest.java      |   6 +-
 .../dunit/rules/GfshShellConnectionRule.java    |  36 ++++-
 .../rules/LocatorServerConfigurationRule.java   | 151 -------------------
 .../dunit/rules/LocatorServerStartupRule.java   |  29 +++-
 .../codeAnalysis/sanctionedSerializables.txt    |   4 +
 .../cli/commands/golden-help-offline.properties |  10 +-
 geode-web/build.gradle                          |   4 +
 .../cli/commands/CommandOverHttpDUnitTest.java  |   6 +-
 .../commands/ExportLogsOverHttpDUnitTest.java   | 116 ++++++++++++++
 .../RestHttpOperationInvokerJUnitTest.java      |  50 +++---
 .../SimpleHttpOperationInvokerJUnitTest.java    |  20 ++-
 34 files changed, 766 insertions(+), 538 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/cli/CliMetaData.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/cli/CliMetaData.java b/geode-core/src/main/java/org/apache/geode/management/cli/CliMetaData.java
index a20fba5..e69d78a 100644
--- a/geode-core/src/main/java/org/apache/geode/management/cli/CliMetaData.java
+++ b/geode-core/src/main/java/org/apache/geode/management/cli/CliMetaData.java
@@ -44,6 +44,14 @@ public @interface CliMetaData {
   boolean shellOnly() default false;
 
   /**
+   * Indicates when executed over http, is this command downloading files from the member. When this
+   * is set to true, the RestHttpOperationInvoker will use an extractor to extract the inputstream
+   * in the response to a temporary file and it's up to your command's interceptor's postExecution
+   * to use that temp file to fit your need.
+   **/
+  boolean isFileDownloadOverHttp() default false;
+
+  /**
    * Indicates that the effect of the command is persisted or the commands affects the persistent
    * configuration
    */

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/internal/cli/AbstractCliAroundInterceptor.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/AbstractCliAroundInterceptor.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/AbstractCliAroundInterceptor.java
index de24727..3e1357d 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/AbstractCliAroundInterceptor.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/AbstractCliAroundInterceptor.java
@@ -14,10 +14,10 @@
  */
 package org.apache.geode.management.internal.cli;
 
-import java.io.IOException;
-
 import org.apache.geode.management.internal.cli.shell.Gfsh;
 
+import java.io.IOException;
+
 /**
  * Semi-complete implementation of {@link CliAroundInterceptor} for convenience for implementors.
  * 

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/internal/cli/CliAroundInterceptor.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/CliAroundInterceptor.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/CliAroundInterceptor.java
index 11d74c1..2e26efd 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/CliAroundInterceptor.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/CliAroundInterceptor.java
@@ -15,8 +15,11 @@
 package org.apache.geode.management.internal.cli;
 
 import org.apache.geode.management.cli.Result;
+import org.apache.geode.management.internal.cli.result.ResultBuilder;
 import org.apache.geode.management.internal.cli.shell.GfshExecutionStrategy;
 
+import java.nio.file.Path;
+
 /**
  * Interceptor interface which {@link GfshExecutionStrategy} can use to intercept before & after
  * actual command execution.
@@ -26,8 +29,27 @@ import org.apache.geode.management.internal.cli.shell.GfshExecutionStrategy;
  */
 public interface CliAroundInterceptor {
 
-  public Result preExecution(GfshParseResult parseResult);
+  /**
+   * called by the OperationInvoker before the command is executed
+   */
+  default public Result preExecution(GfshParseResult parseResult) {
+    return ResultBuilder.createInfoResult("");
+  }
+
+  @Deprecated
+  default public Result postExecution(GfshParseResult parseResult, Result commandResult) {
+    return commandResult;
+  }
 
-  public Result postExecution(GfshParseResult parseResult, Result commandResult);
+  /**
+   * called by the OperationInvoker after the command is executed
+   * 
+   * @param tempFile: if the command's isFileDownloadOverHttp is true, the is the File downloaded
+   *        after the http response is processed.
+   */
+  default public Result postExecution(GfshParseResult parseResult, Result commandResult,
+      Path tempFile) {
+    return postExecution(parseResult, commandResult);
+  }
 
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/internal/cli/CliUtil.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/CliUtil.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/CliUtil.java
index 87a07a6..ad3f3df 100755
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/CliUtil.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/CliUtil.java
@@ -302,9 +302,11 @@ public class CliUtil {
   }
 
   /**
-   * Finds all Members (including both servers and locators) which belong to the given arrays of groups or members.
+   * Finds all Members (including both servers and locators) which belong to the given arrays of
+   * groups or members.
    */
-  public static Set<DistributedMember> findMembersIncludingLocators(String[] groups, String[] members) {
+  public static Set<DistributedMember> findMembersIncludingLocators(String[] groups,
+      String[] members) {
     Cache cache = CacheFactory.getAnyInstance();
     Set<DistributedMember> allMembers = getAllMembers(cache);
 
@@ -312,7 +314,8 @@ public class CliUtil {
   }
 
   /**
-   * Finds all Servers which belong to the given arrays of groups or members.  Does not include locators.
+   * Finds all Servers which belong to the given arrays of groups or members. Does not include
+   * locators.
    */
   public static Set<DistributedMember> findMembers(String[] groups, String[] members) {
     Cache cache = CacheFactory.getAnyInstance();
@@ -321,7 +324,8 @@ public class CliUtil {
     return findMembers(allNormalMembers, groups, members);
   }
 
-  private static Set<DistributedMember> findMembers(Set<DistributedMember> membersToConsider, String[] groups, String[] members) {
+  private static Set<DistributedMember> findMembers(Set<DistributedMember> membersToConsider,
+      String[] groups, String[] members) {
     if (groups == null) {
       groups = new String[] {};
     }

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandRequest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandRequest.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandRequest.java
index b0242c9..046499e 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandRequest.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandRequest.java
@@ -14,12 +14,13 @@
  */
 package org.apache.geode.management.internal.cli;
 
+import org.apache.geode.internal.lang.StringUtils;
+import org.apache.geode.management.cli.CliMetaData;
+
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.geode.internal.lang.StringUtils;
-
 /**
  * The CommandRequest class encapsulates information pertaining to the command the user entered in
  * Gfsh.
@@ -39,6 +40,7 @@ public class CommandRequest {
 
   private final Map<String, String> customParameters = new HashMap<String, String>();
   private final Map<String, String> env;
+  private boolean downloadFile = false;
 
   private String customInput;
 
@@ -65,6 +67,11 @@ public class CommandRequest {
     this.env = env;
     this.fileData = fileData;
     this.parseResult = parseResult;
+
+    CliMetaData metaData = parseResult.getMethod().getDeclaredAnnotation(CliMetaData.class);
+    if (metaData != null && metaData.isFileDownloadOverHttp()) {
+      downloadFile = true;
+    }
   }
 
   public String getName() {
@@ -88,6 +95,10 @@ public class CommandRequest {
     return customInput;
   }
 
+  public boolean isDownloadFile() {
+    return downloadFile;
+  }
+
   public void setCustomInput(final String input) {
     this.customInput = input;
   }

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/MiscellaneousCommands.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/MiscellaneousCommands.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/MiscellaneousCommands.java
index e720d09..e921031 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/MiscellaneousCommands.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/MiscellaneousCommands.java
@@ -14,42 +14,8 @@
  */
 package org.apache.geode.management.internal.cli.commands;
 
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.zip.DataFormatException;
-import java.util.zip.GZIPInputStream;
-import javax.management.ObjectName;
-
 import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
 import org.apache.geode.LogWriter;
 import org.apache.geode.cache.Cache;
 import org.apache.geode.cache.CacheFactory;
@@ -108,19 +74,49 @@ import org.apache.geode.management.internal.cli.result.ResultData;
 import org.apache.geode.management.internal.cli.result.ResultDataException;
 import org.apache.geode.management.internal.cli.result.TabularResultData;
 import org.apache.geode.management.internal.cli.shell.Gfsh;
-import org.apache.geode.management.internal.cli.util.MergeLogs;
 import org.apache.geode.management.internal.cli.util.ExportLogsCacheWriter;
 import org.apache.geode.management.internal.configuration.utils.ZipUtils;
 import org.apache.geode.management.internal.security.ResourceOperation;
 import org.apache.geode.security.ResourcePermission.Operation;
 import org.apache.geode.security.ResourcePermission.Resource;
-
 import org.apache.logging.log4j.Logger;
 import org.springframework.shell.core.CommandMarker;
 import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
 import org.springframework.shell.core.annotation.CliCommand;
 import org.springframework.shell.core.annotation.CliOption;
 
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.zip.DataFormatException;
+import java.util.zip.GZIPInputStream;
+import javax.management.ObjectName;
+
 /**
  * @since GemFire 7.0
  */
@@ -129,6 +125,7 @@ public class MiscellaneousCommands implements CommandMarker {
   public final static String FORMAT = "yyyy/MM/dd/HH/mm/ss/SSS/z";
   public final static String ONLY_DATE_FORMAT = "yyyy/MM/dd";
   public final static String DEFAULT_TIME_OUT = "10";
+  private final static Logger logger = LogService.getLogger();
 
   private final GetStackTracesFunction getStackTracesFunction = new GetStackTracesFunction();
 
@@ -139,8 +136,6 @@ public class MiscellaneousCommands implements CommandMarker {
 
   public void shutdownNode(final long timeout, final Set<DistributedMember> includeMembers)
       throws TimeoutException, InterruptedException, ExecutionException {
-    Cache cache = CacheFactory.getAnyInstance();
-    LogWriter logger = cache.getLogger();
     ExecutorService exec = Executors.newSingleThreadExecutor();
     try {
       final Function shutDownFunction = new ShutDownFunction();
@@ -690,12 +685,13 @@ public class MiscellaneousCommands implements CommandMarker {
   }
 
   @CliCommand(value = CliStrings.EXPORT_LOGS, help = CliStrings.EXPORT_LOGS__HELP)
-  @CliMetaData(shellOnly = false,
+  @CliMetaData(shellOnly = false, isFileDownloadOverHttp = true,
+      interceptor = "org.apache.geode.management.internal.cli.commands.MiscellaneousCommands$ExportLogsInterceptor",
       relatedTopic = {CliStrings.TOPIC_GEODE_SERVER, CliStrings.TOPIC_GEODE_DEBUG_UTIL})
   @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ)
   public Result exportLogs(
       @CliOption(key = CliStrings.EXPORT_LOGS__DIR, help = CliStrings.EXPORT_LOGS__DIR__HELP,
-          mandatory = true) String dirName,
+          mandatory = false) String dirName,
       @CliOption(key = CliStrings.EXPORT_LOGS__GROUP,
           unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
           optionContext = ConverterHint.MEMBERGROUP,
@@ -719,12 +715,9 @@ public class MiscellaneousCommands implements CommandMarker {
           unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
           help = CliStrings.EXPORT_LOGS__ENDTIME__HELP) String end) {
     Result result = null;
-    Logger logger = LogService.getLogger();
-
     try {
-      GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
-
-      Set<DistributedMember> targetMembers = CliUtil.findMembersIncludingLocators(groups, memberIds);
+      Set<DistributedMember> targetMembers =
+          CliUtil.findMembersIncludingLocators(groups, memberIds);
 
 
       Map<String, Path> zipFilesFromMembers = new HashMap<>();
@@ -736,7 +729,8 @@ public class MiscellaneousCommands implements CommandMarker {
 
         cacheWriter.startFile(server.getName());
 
-        CliUtil.executeFunction(new ExportLogsFunction(),
+        CliUtil
+            .executeFunction(new ExportLogsFunction(),
                 new ExportLogsFunction.Args(start, end, logLevel, onlyLogLevel), server)
             .getResult();
         Path zipFile = cacheWriter.endFile();
@@ -756,25 +750,57 @@ public class MiscellaneousCommands implements CommandMarker {
       }
 
       Path workingDir = Paths.get(System.getProperty("user.dir"));
-      Path exportedLogsZipFile = workingDir.resolve("exportedLogs[" + System.currentTimeMillis() + "].zip").toAbsolutePath();
+      Path exportedLogsZipFile = workingDir
+          .resolve("exportedLogs_" + System.currentTimeMillis() + ".zip").toAbsolutePath();
 
       logger.info("Zipping into: " + exportedLogsZipFile.toString());
       ZipUtils.zipDirectory(exportedLogsDir, exportedLogsZipFile);
       FileUtils.deleteDirectory(tempDir.toFile());
-      result = ResultBuilder.createInfoResult("File exported to: " + exportedLogsZipFile.toString());
+      result = ResultBuilder.createInfoResult(exportedLogsZipFile.toString());
     } catch (Exception ex) {
-      ex.printStackTrace();
       logger.error(ex, ex);
       result = ResultBuilder.createUserErrorResult(ex.getMessage());
     } finally {
       ExportLogsFunction.destroyExportLogsRegion();
     }
-
-    LogWrapper.getInstance().fine("Exporting logs returning =" + result);
+    logger.debug("Exporting logs returning = {}", result);
     return result;
   }
 
-
+  /**
+   * after the export logs, will need to copy the tempFile to the desired location and delete the
+   * temp file.
+   */
+  public static class ExportLogsInterceptor extends AbstractCliAroundInterceptor {
+    @Override
+    public Result postExecution(GfshParseResult parseResult, Result commandResult, Path tempFile) {
+      // in the command over http case, the command result is in the downloaded temp file
+      if (tempFile != null) {
+        Path dirPath;
+        String dirName = parseResult.getParamValueStrings().get("dir");
+        if (StringUtils.isBlank(dirName)) {
+          dirPath = Paths.get(System.getProperty("user.dir"));
+        } else {
+          dirPath = Paths.get(dirName);
+        }
+        String fileName = "exportedLogs_" + System.currentTimeMillis() + ".zip";
+        File exportedLogFile = dirPath.resolve(fileName).toFile();
+        try {
+          FileUtils.copyFile(tempFile.toFile(), exportedLogFile);
+          FileUtils.deleteQuietly(tempFile.toFile());
+          commandResult = ResultBuilder
+              .createInfoResult("Logs exported to: " + exportedLogFile.getAbsolutePath());
+        } catch (IOException e) {
+          logger.error(e.getMessage(), e);
+          commandResult = ResultBuilder.createGemFireErrorResult(e.getMessage());
+        }
+      } else {
+        commandResult = ResultBuilder.createInfoResult(
+            "Logs exported to the connected member's file system: " + commandResult.nextLine());
+      }
+      return commandResult;
+    }
+  }
 
   /****
    * Current implementation supports writing it to a file and returning the location of the file
@@ -996,16 +1022,15 @@ public class MiscellaneousCommands implements CommandMarker {
           result = ResultBuilder.buildResult(erd);
         }
       } else {
-
         if (!org.apache.geode.internal.lang.StringUtils.isBlank(cacheServerPortString)) {
           return ResultBuilder
               .createUserErrorResult(CliStrings.SHOW_METRICS__CANNOT__USE__CACHESERVERPORT);
         }
-
         result = ResultBuilder.buildResult(getSystemWideMetrics(export_to_report_to, categories));
       }
     } catch (Exception e) {
-      return ResultBuilder.createGemFireErrorResult("#SB" + CliUtil.stackTraceAsString(e));
+      logger.error(e.getMessage(), e);
+      return ResultBuilder.createGemFireErrorResult(CliUtil.stackTraceAsString(e));
     }
     return result;
   }

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ExportLogsFunction.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ExportLogsFunction.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ExportLogsFunction.java
index 1dc89e9..560e8aa 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ExportLogsFunction.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/ExportLogsFunction.java
@@ -17,7 +17,6 @@
 package org.apache.geode.management.internal.cli.functions;
 
 import static java.util.stream.Collectors.toSet;
-import static org.apache.geode.distributed.internal.DistributionManager.LOCATOR_DM_TYPE;
 
 import org.apache.geode.cache.AttributesFactory;
 import org.apache.geode.cache.DataPolicy;
@@ -99,10 +98,6 @@ public class ExportLogsFunction implements Function, InternalEntity {
     }
   }
 
-  protected static boolean isLocator(GemFireCacheImpl cache) {
-    return cache.getMyId().getVmKind() == LOCATOR_DM_TYPE;
-  }
-
   public static Region createOrGetExistingExportLogsRegion(boolean isInitiatingMember)
       throws IOException, ClassNotFoundException {
     GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
@@ -134,7 +129,7 @@ public class ExportLogsFunction implements Function, InternalEntity {
       return;
     }
 
-      exportLogsRegion.destroyRegion();
+    exportLogsRegion.destroyRegion();
 
   }
 

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/internal/cli/i18n/CliStrings.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/i18n/CliStrings.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/i18n/CliStrings.java
index c536e8e..3dc42d6 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/i18n/CliStrings.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/i18n/CliStrings.java
@@ -14,18 +14,38 @@
  */
 package org.apache.geode.management.internal.cli.i18n;
 
-import static org.apache.geode.distributed.ConfigurationProperties.*;
-
-import java.text.MessageFormat;
+import static org.apache.geode.distributed.ConfigurationProperties.ARCHIVE_DISK_SPACE_LIMIT;
+import static org.apache.geode.distributed.ConfigurationProperties.ARCHIVE_FILE_SIZE_LIMIT;
+import static org.apache.geode.distributed.ConfigurationProperties.CACHE_XML_FILE;
+import static org.apache.geode.distributed.ConfigurationProperties.DURABLE_CLIENT_ID;
+import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_CLUSTER_CONFIGURATION;
+import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_TIME_STATISTICS;
+import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER;
+import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
+import static org.apache.geode.distributed.ConfigurationProperties.LOG_DISK_SPACE_LIMIT;
+import static org.apache.geode.distributed.ConfigurationProperties.LOG_FILE_SIZE_LIMIT;
+import static org.apache.geode.distributed.ConfigurationProperties.LOG_LEVEL;
+import static org.apache.geode.distributed.ConfigurationProperties.MCAST_ADDRESS;
+import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
+import static org.apache.geode.distributed.ConfigurationProperties.MEMCACHED_BIND_ADDRESS;
+import static org.apache.geode.distributed.ConfigurationProperties.MEMCACHED_PORT;
+import static org.apache.geode.distributed.ConfigurationProperties.MEMCACHED_PROTOCOL;
+import static org.apache.geode.distributed.ConfigurationProperties.SERVER_BIND_ADDRESS;
+import static org.apache.geode.distributed.ConfigurationProperties.SOCKET_BUFFER_SIZE;
+import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_ARCHIVE_FILE;
+import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_SAMPLE_RATE;
+import static org.apache.geode.distributed.ConfigurationProperties.USE_CLUSTER_CONFIGURATION;
 
 import org.apache.geode.cache.PartitionAttributesFactory;
 import org.apache.geode.cache.server.CacheServer;
 import org.apache.geode.distributed.ConfigurationProperties;
-import org.apache.geode.distributed.internal.DistributionConfig;
 import org.apache.geode.distributed.internal.ClusterConfigurationService;
+import org.apache.geode.distributed.internal.DistributionConfig;
 import org.apache.geode.internal.cache.xmlcache.CacheXml;
 import org.apache.geode.management.internal.cli.shell.Gfsh;
 
+import java.text.MessageFormat;
+
 /**
  * - * Contains 'String' constants used as key to the Localized strings to be used in classes under
  * <code>org.apache.geode.management.internal.cli</code> for Command Line Interface (CLI). NOTES: 1.
@@ -1371,7 +1391,7 @@ public class CliStrings {
   public static final String EXPORT_LOGS__HELP = "Export the log files for a member or members.";
   public static final String EXPORT_LOGS__DIR = "dir";
   public static final String EXPORT_LOGS__DIR__HELP =
-      "Directory to which log files will be written.";
+      "Local directory to which log files will be written. This is only used when you are exporting logs using http connection. If not specified, user.dir will be used.";
   public static final String EXPORT_LOGS__MEMBER = "member";
   public static final String EXPORT_LOGS__MEMBER__HELP =
       "Name/Id of the member whose log files will be exported.";

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/GfshExecutionStrategy.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/GfshExecutionStrategy.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/GfshExecutionStrategy.java
index b53c53f..6445454 100755
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/GfshExecutionStrategy.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/GfshExecutionStrategy.java
@@ -14,10 +14,7 @@
  */
 package org.apache.geode.management.internal.cli.shell;
 
-import static org.apache.geode.management.internal.cli.multistep.CLIMultiStepHelper.*;
-
-import java.lang.reflect.Method;
-import java.util.Map;
+import static org.apache.geode.management.internal.cli.multistep.CLIMultiStepHelper.execCLISteps;
 
 import org.apache.geode.internal.ClassPathLoader;
 import org.apache.geode.management.cli.CliMetaData;
@@ -35,13 +32,16 @@ import org.apache.geode.management.internal.cli.multistep.MultiStepCommand;
 import org.apache.geode.management.internal.cli.result.FileResult;
 import org.apache.geode.management.internal.cli.result.ResultBuilder;
 import org.apache.geode.security.NotAuthorizedException;
-
 import org.springframework.shell.core.ExecutionStrategy;
 import org.springframework.shell.core.Shell;
 import org.springframework.shell.event.ParseResult;
 import org.springframework.util.Assert;
 import org.springframework.util.ReflectionUtils;
 
+import java.lang.reflect.Method;
+import java.nio.file.Path;
+import java.util.Map;
+
 /**
  * Defines the {@link ExecutionStrategy} for commands that are executed in GemFire SHell (gfsh).
  * 
@@ -235,9 +235,12 @@ public class GfshExecutionStrategy implements ExecutionStrategy {
     try {
       response = shell.getOperationInvoker()
           .processCommand(new CommandRequest(parseResult, env, fileData));
+
     } catch (NotAuthorizedException e) {
       return ResultBuilder
           .createGemFireUnAuthorizedErrorResult("Unauthorized. Reason : " + e.getMessage());
+    } catch (Exception e) {
+      shell.logSevere(e.getMessage(), e);
     } finally {
       env.clear();
     }
@@ -250,33 +253,39 @@ public class GfshExecutionStrategy implements ExecutionStrategy {
               + "Please check manager logs for error.");
     }
 
-    if (logWrapper.fineEnabled()) {
-      logWrapper.fine("Received response :: " + response);
-    }
-    CommandResponse commandResponse =
-        CommandResponseBuilder.prepareCommandResponseFromJson((String) response);
+    // the response could be a string which is a json respresentation of the CommandResult object
+    // it can also be a Path to a temp file downloaded from the rest http request
+    if (response instanceof String) {
+      CommandResponse commandResponse =
+          CommandResponseBuilder.prepareCommandResponseFromJson((String) response);
 
-    if (commandResponse.isFailedToPersist()) {
-      shell.printAsSevere(CliStrings.SHARED_CONFIGURATION_FAILED_TO_PERSIST_COMMAND_CHANGES);
-      logWrapper.severe(CliStrings.SHARED_CONFIGURATION_FAILED_TO_PERSIST_COMMAND_CHANGES);
+      if (commandResponse.isFailedToPersist()) {
+        shell.printAsSevere(CliStrings.SHARED_CONFIGURATION_FAILED_TO_PERSIST_COMMAND_CHANGES);
+        logWrapper.severe(CliStrings.SHARED_CONFIGURATION_FAILED_TO_PERSIST_COMMAND_CHANGES);
+      }
+
+      String debugInfo = commandResponse.getDebugInfo();
+      if (debugInfo != null && !debugInfo.trim().isEmpty()) {
+        // TODO - Abhishek When debug is ON, log response in gfsh logs
+        // TODO - Abhishek handle \n better. Is it coming from GemFire formatter
+        debugInfo = debugInfo.replaceAll("\n\n\n", "\n");
+        debugInfo = debugInfo.replaceAll("\n\n", "\n");
+        debugInfo =
+            debugInfo.replaceAll("\n", "\n[From Manager : " + commandResponse.getSender() + "]");
+        debugInfo = "[From Manager : " + commandResponse.getSender() + "]" + debugInfo;
+        LogWrapper.getInstance().info(debugInfo);
+      }
+      commandResult = ResultBuilder.fromJson((String) response);
     }
 
-    String debugInfo = commandResponse.getDebugInfo();
-    if (debugInfo != null && !debugInfo.trim().isEmpty()) {
-      // TODO - Abhishek When debug is ON, log response in gfsh logs
-      // TODO - Abhishek handle \n better. Is it coming from GemFire formatter
-      debugInfo = debugInfo.replaceAll("\n\n\n", "\n");
-      debugInfo = debugInfo.replaceAll("\n\n", "\n");
-      debugInfo =
-          debugInfo.replaceAll("\n", "\n[From Manager : " + commandResponse.getSender() + "]");
-      debugInfo = "[From Manager : " + commandResponse.getSender() + "]" + debugInfo;
-      LogWrapper.getInstance().info(debugInfo);
+    Path tempFile = null;
+    if (response instanceof Path) {
+      tempFile = (Path) response;
     }
-    commandResult = ResultBuilder.fromJson((String) response);
 
     // 3. Post Remote Execution
     if (interceptor != null) {
-      Result postExecResult = interceptor.postExecution(parseResult, commandResult);
+      Result postExecResult = interceptor.postExecution(parseResult, commandResult, tempFile);
       if (postExecResult != null) {
         if (Status.ERROR.equals(postExecResult.getStatus())) {
           if (logWrapper.infoEnabled()) {

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/ExportLogsCacheWriter.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/ExportLogsCacheWriter.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/ExportLogsCacheWriter.java
index a8b7225..178bb4a 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/ExportLogsCacheWriter.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/ExportLogsCacheWriter.java
@@ -22,15 +22,11 @@ import org.apache.geode.cache.EntryEvent;
 import org.apache.geode.cache.util.CacheWriterAdapter;
 
 import java.io.BufferedOutputStream;
-import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.OutputStream;
 import java.io.Serializable;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Map;
 
 public class ExportLogsCacheWriter extends CacheWriterAdapter implements Serializable {
   private Path currentFile;
@@ -38,11 +34,9 @@ public class ExportLogsCacheWriter extends CacheWriterAdapter implements Seriali
 
   @Override
   public void beforeCreate(EntryEvent event) throws CacheWriterException {
-    if (currentFile.getFileName().endsWith("server-2.zip")) {
-      System.out.println("We got data from server 2");
-    }
     if (currentOutputStream == null) {
-      throw new IllegalStateException("No outputStream is open.  You must call startFile before sending data.");
+      throw new IllegalStateException(
+          "No outputStream is open.  You must call startFile before sending data.");
     }
 
     try {

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/ExportLogsRepository.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/ExportLogsRepository.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/ExportLogsRepository.java
index 9a79fc0..85ce1ad 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/ExportLogsRepository.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/ExportLogsRepository.java
@@ -1,18 +1,16 @@
 /*
- * 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
+ * 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
+ * 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.
+ * 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.
  *
  */
 

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/MergeLogs.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/MergeLogs.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/MergeLogs.java
index 67d5473..04a649b 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/MergeLogs.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/MergeLogs.java
@@ -50,14 +50,13 @@ public class MergeLogs {
     // create a new process for merging
     LogWrapper.getInstance().fine("Exporting logs merging logs" + logDirectory);
     List<String> commandList = new ArrayList<String>();
-    commandList.add(System.getProperty("java.home") + File.separatorChar + "bin"
-        + File.separatorChar + "java");
+    commandList.add(
+        System.getProperty("java.home") + File.separatorChar + "bin" + File.separatorChar + "java");
     commandList.add("-classpath");
     commandList.add(System.getProperty("java.class.path", "."));
     commandList.add(MergeLogs.class.getName());
 
-    commandList
-        .add(logDirectory.toAbsolutePath().toString());
+    commandList.add(logDirectory.toAbsolutePath().toString());
 
     ProcessBuilder procBuilder = new ProcessBuilder(commandList);
     StringBuilder output = new StringBuilder();
@@ -100,8 +99,8 @@ public class MergeLogs {
 
   }
 
-  protected static List<File> findLogFilesToMerge (File dir) {
-    return FileUtils.listFiles(dir, new String[]{"log"}, true).stream().collect(toList());
+  protected static List<File> findLogFilesToMerge(File dir) {
+    return FileUtils.listFiles(dir, new String[] {"log"}, true).stream().collect(toList());
   }
 
   static File mergeLogFile(String dirName) throws Exception {
@@ -122,8 +121,8 @@ public class MergeLogs {
     PrintWriter mergedLog = null;
     File mergedLogFile = null;
     try {
-      String mergeLog =
-          dirName + File.separator + "merge_" + new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new java.util.Date()) + ".log";
+      String mergeLog = dirName + File.separator + "merge_"
+          + new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new java.util.Date()) + ".log";
       mergedLogFile = new File(mergeLog);
       mergedLog = new PrintWriter(mergedLogFile);
       boolean flag = MergeLogFiles.mergeLogFiles(logFiles, logFileNames, mergedLog);

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/MiscellaneousCommandsController.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/MiscellaneousCommandsController.java b/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/MiscellaneousCommandsController.java
index ac912c8..e2f5307 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/MiscellaneousCommandsController.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/MiscellaneousCommandsController.java
@@ -14,11 +14,13 @@
  */
 package org.apache.geode.management.internal.web.controllers;
 
-import java.util.concurrent.Callable;
-
 import org.apache.geode.internal.lang.StringUtils;
 import org.apache.geode.management.internal.cli.i18n.CliStrings;
+import org.apache.geode.management.internal.cli.result.ResultBuilder;
 import org.apache.geode.management.internal.cli.util.CommandStringBuilder;
+import org.springframework.core.io.InputStreamResource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -27,6 +29,9 @@ import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 
+import java.io.File;
+import java.io.FileInputStream;
+
 /**
  * The MiscellaneousCommandsController class implements GemFire Management REST API web service
  * endpoints for the Gfsh Miscellaneous Commands.
@@ -48,8 +53,8 @@ import org.springframework.web.bind.annotation.ResponseBody;
 public class MiscellaneousCommandsController extends AbstractCommandsController {
 
   @RequestMapping(method = RequestMethod.GET, value = "/logs")
-  public Callable<ResponseEntity<String>> exportLogs(
-      @RequestParam(CliStrings.EXPORT_LOGS__DIR) final String directory,
+  public ResponseEntity<InputStreamResource> exportLogs(
+      @RequestParam(value = CliStrings.EXPORT_LOGS__DIR, required = false) final String directory,
       @RequestParam(value = CliStrings.EXPORT_LOGS__GROUP, required = false) final String[] groups,
       @RequestParam(value = CliStrings.EXPORT_LOGS__MEMBER,
           required = false) final String memberNameId,
@@ -93,7 +98,19 @@ public class MiscellaneousCommandsController extends AbstractCommandsController
       command.addOption(CliStrings.EXPORT_LOGS__ENDTIME, endTime);
     }
 
-    return getProcessCommandCallable(command.toString());
+    // the result is json string from CommandResult
+    String result = processCommand(command.toString());
+
+    // parse the result to get the file path
+    String filePath = ResultBuilder.fromJson(result).nextLine().trim();
+
+    HttpHeaders respHeaders = new HttpHeaders();
+    try {
+      InputStreamResource isr = new InputStreamResource(new FileInputStream(new File(filePath)));
+      return new ResponseEntity<InputStreamResource>(isr, respHeaders, HttpStatus.OK);
+    } catch (Exception ex) {
+      throw new RuntimeException("IOError writing file to output stream", ex);
+    }
   }
 
   // TODO determine whether Async functionality is required

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/AbstractHttpOperationInvoker.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/AbstractHttpOperationInvoker.java b/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/AbstractHttpOperationInvoker.java
index fa05248..f60aabc 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/AbstractHttpOperationInvoker.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/AbstractHttpOperationInvoker.java
@@ -15,6 +15,7 @@
 
 package org.apache.geode.management.internal.web.shell;
 
+import org.apache.commons.io.FileUtils;
 import org.apache.geode.internal.GemFireVersion;
 import org.apache.geode.internal.lang.StringUtils;
 import org.apache.geode.internal.logging.LogService;
@@ -34,6 +35,7 @@ import org.apache.geode.management.internal.web.util.UriUtils;
 import org.apache.geode.security.AuthenticationFailedException;
 import org.apache.geode.security.NotAuthorizedException;
 import org.apache.logging.log4j.Logger;
+import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
@@ -41,14 +43,18 @@ import org.springframework.http.client.ClientHttpResponse;
 import org.springframework.http.client.SimpleClientHttpRequestFactory;
 import org.springframework.http.converter.HttpMessageConverter;
 import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.client.RequestCallback;
 import org.springframework.web.client.ResourceAccessException;
 import org.springframework.web.client.ResponseErrorHandler;
+import org.springframework.web.client.ResponseExtractor;
 import org.springframework.web.client.RestTemplate;
 
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Iterator;
@@ -583,8 +589,7 @@ public abstract class AbstractHttpOperationInvoker implements HttpOperationInvok
    * @see org.apache.geode.management.internal.web.http.ClientHttpRequest
    * @see org.springframework.http.ResponseEntity
    */
-  protected <T> ResponseEntity<T> send(final ClientHttpRequest request,
-      final Class<T> responseType) {
+  protected <T> T send(final ClientHttpRequest request, final Class<T> responseType) {
     return send(request, responseType, Collections.<String, Object>emptyMap());
   }
 
@@ -603,10 +608,9 @@ public abstract class AbstractHttpOperationInvoker implements HttpOperationInvok
    * @see org.springframework.web.client.RestTemplate#exchange(java.net.URI,
    *      org.springframework.http.HttpMethod, org.springframework.http.HttpEntity, Class)
    */
-  protected <T> ResponseEntity<T> send(final ClientHttpRequest request, final Class<T> responseType,
+  protected <T> T send(final ClientHttpRequest request, final Class<T> responseType,
       final Map<String, ?> uriVariables) {
     final URI url = request.getURL(uriVariables);
-
     if (isDebugEnabled()) {
       printInfo("Link: %1$s", request.getLink().toHttpRequestLine());
       printInfo("HTTP URL: %1$s", url);
@@ -626,7 +630,31 @@ public abstract class AbstractHttpOperationInvoker implements HttpOperationInvok
       printInfo("HTTP response body: ", response.getBody());
     }
 
-    return response;
+    return response.getBody();
+  }
+
+  protected Path downloadResponseToTempFile(ClientHttpRequest request,
+      Map<String, ?> uriVariables) {
+    final URI url = request.getURL(uriVariables);
+
+    // Optional Accept header
+    RequestCallback requestCallback = r -> {
+      r.getHeaders().setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM));
+      HttpHeaders header = request.getHeaders();
+      r.getHeaders().setAll(request.getHeaders().toSingleValueMap());
+    };
+
+    // Streams the response instead of loading it all in memory
+    ResponseExtractor<Path> responseExtractor = resp -> {
+      Path tempFile = Files.createTempFile("fileDownload", "");
+      if (tempFile.toFile().exists()) {
+        FileUtils.deleteQuietly(tempFile.toFile());
+      }
+      Files.copy(resp.getBody(), tempFile);
+      return tempFile;
+    };
+    return getRestTemplate().execute(url, org.springframework.http.HttpMethod.GET, requestCallback,
+        responseExtractor);
   }
 
   /**
@@ -680,10 +708,8 @@ public abstract class AbstractHttpOperationInvoker implements HttpOperationInvok
       request.addParameterValues("resourceName", resourceName);
       request.addParameterValues("attributeName", attributeName);
 
-      final ResponseEntity<byte[]> response = send(request, byte[].class);
-
       try {
-        return IOUtils.deserializeObject(response.getBody());
+        return IOUtils.deserializeObject(send(request, byte[].class));
       } catch (IOException e) {
         throw new MBeanAccessException(String.format(
             "De-serializing the result of accessing attribute (%1$s) on MBean (%2$s) failed!",
@@ -785,10 +811,8 @@ public abstract class AbstractHttpOperationInvoker implements HttpOperationInvok
       request.addParameterValues("parameters", params); // TODO may need to convert method parameter
                                                         // arguments
 
-      final ResponseEntity<byte[]> response = send(request, byte[].class);
-
       try {
-        return IOUtils.deserializeObject(response.getBody());
+        return IOUtils.deserializeObject(send(request, byte[].class));
       } catch (IOException e) {
         throw new MBeanAccessException(String.format(
             "De-serializing the result from invoking operation (%1$s) on MBean (%2$s) failed!",
@@ -831,11 +855,8 @@ public abstract class AbstractHttpOperationInvoker implements HttpOperationInvok
       final ClientHttpRequest request = createHttpRequest(link);
 
       request.setContent(new QueryParameterSource(objectName, queryExpression));
-
-      final ResponseEntity<byte[]> response = send(request, byte[].class);
-
       try {
-        return (Set<ObjectName>) IOUtils.deserializeObject(response.getBody());
+        return (Set<ObjectName>) IOUtils.deserializeObject(send(request, byte[].class));
       } catch (Exception e) {
         throw new MBeanAccessException(String.format(
             "An error occurred while querying for MBean names using ObjectName pattern (%1$s) and Query expression (%2$s)!",

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/RestHttpOperationInvoker.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/RestHttpOperationInvoker.java b/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/RestHttpOperationInvoker.java
index 82b2b1f..eeedf40 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/RestHttpOperationInvoker.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/RestHttpOperationInvoker.java
@@ -15,14 +15,6 @@
 
 package org.apache.geode.management.internal.web.shell;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
 import org.apache.geode.internal.lang.Filter;
 import org.apache.geode.internal.lang.Initable;
 import org.apache.geode.internal.lang.StringUtils;
@@ -36,15 +28,21 @@ import org.apache.geode.management.internal.web.domain.LinkIndex;
 import org.apache.geode.management.internal.web.http.ClientHttpRequest;
 import org.apache.geode.management.internal.web.http.HttpHeader;
 import org.apache.geode.management.internal.web.util.ConvertUtils;
-
 import org.apache.logging.log4j.Logger;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
 import org.springframework.http.client.ClientHttpResponse;
 import org.springframework.web.client.ResourceAccessException;
 import org.springframework.web.util.UriTemplate;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
 /**
  * The RestHttpOperationInvoker class is an implementation of the OperationInvoker interface that
  * translates (adapts) GemFire shell command invocations into HTTP requests to a corresponding REST
@@ -376,7 +374,8 @@ public class RestHttpOperationInvoker extends AbstractHttpOperationInvoker imple
    * (execution).
    * 
    * @param command the command requested/entered by the user to be processed.
-   * @return the result of the command execution.
+   * @return either a json string of the CommandResult or a Path to a temp file if the response is a
+   *         InputStream
    * @see #createHttpRequest(org.apache.geode.management.internal.cli.CommandRequest)
    * @see #handleResourceAccessException(org.springframework.web.client.ResourceAccessException)
    * @see #isConnected()
@@ -388,15 +387,18 @@ public class RestHttpOperationInvoker extends AbstractHttpOperationInvoker imple
    * @see org.springframework.http.ResponseEntity
    */
   @Override
-  public String processCommand(final CommandRequest command) {
+  public Object processCommand(final CommandRequest command) {
     assertState(isConnected(),
         "Gfsh must be connected to the GemFire Manager in order to process commands remotely!");
 
+    Object result = null;
     try {
-      ResponseEntity<String> response =
-          send(createHttpRequest(command), String.class, command.getParameters());
-
-      return response.getBody();
+      if (command.isDownloadFile()) {
+        result = downloadResponseToTempFile(createHttpRequest(command), command.getParameters());
+      } else {
+        result = send(createHttpRequest(command), String.class, command.getParameters());
+      }
+      return result;
     } catch (RestApiCallForCommandNotFoundException e) {
       return simpleProcessCommand(command, e);
     } catch (ResourceAccessException e) {

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/SimpleHttpOperationInvoker.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/SimpleHttpOperationInvoker.java b/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/SimpleHttpOperationInvoker.java
index dcda27b..d11d824 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/SimpleHttpOperationInvoker.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/SimpleHttpOperationInvoker.java
@@ -15,19 +15,17 @@
 
 package org.apache.geode.management.internal.web.shell;
 
-import java.net.URI;
-import java.util.Map;
-
 import org.apache.geode.management.internal.cli.CommandRequest;
 import org.apache.geode.management.internal.cli.shell.Gfsh;
 import org.apache.geode.management.internal.web.domain.Link;
 import org.apache.geode.management.internal.web.http.ClientHttpRequest;
 import org.apache.geode.management.internal.web.http.HttpMethod;
-
-import org.springframework.http.ResponseEntity;
 import org.springframework.web.client.ResourceAccessException;
 import org.springframework.web.util.UriComponentsBuilder;
 
+import java.net.URI;
+import java.util.Map;
+
 /**
  * The SimpleHttpOperationInvoker class is an implementation of the OperationInvoker interface that
  * issues commands to the GemFire Manager via HTTP. The SimpleHttpOperationInvoker uses a single URL
@@ -156,9 +154,7 @@ public class SimpleHttpOperationInvoker extends AbstractHttpOperationInvoker {
         "Gfsh must be connected to the GemFire Manager in order to process commands remotely!");
 
     try {
-      final ResponseEntity<String> response = send(createHttpRequest(command), String.class);
-
-      return response.getBody();
+      return send(createHttpRequest(command), String.class);
     } catch (ResourceAccessException e) {
       return handleResourceAccessException(e);
     }

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/test/java/org/apache/geode/management/internal/cli/CommandRequestTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/CommandRequestTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/CommandRequestTest.java
index 5436237..5e60f0b 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/CommandRequestTest.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/CommandRequestTest.java
@@ -15,18 +15,18 @@
 package org.apache.geode.management.internal.cli;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.*;
-
-import java.util.HashMap;
-import java.util.Map;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+import org.apache.geode.management.internal.cli.commands.DataCommands;
 import org.apache.geode.test.junit.categories.UnitTest;
-
 import org.junit.Before;
 import org.junit.Test;
-import org.junit.experimental.categories.Categories.ExcludeCategory;
 import org.junit.experimental.categories.Category;
 
+import java.util.HashMap;
+import java.util.Map;
+
 @Category(UnitTest.class)
 public class CommandRequestTest {
 
@@ -36,12 +36,14 @@ public class CommandRequestTest {
   private CommandRequest commandRequest;
 
   @Before
-  public void setUp() {
+  public void setUp() throws Exception {
     this.paramValues = new HashMap<>();
 
     this.mockParseResult = mock(GfshParseResult.class);
     when(this.mockParseResult.getUserInput()).thenReturn("rebalance --simulate=true --time-out=-1");
     when(this.mockParseResult.getParamValueStrings()).thenReturn(this.paramValues);
+    when(this.mockParseResult.getMethod()).thenReturn(DataCommands.class.getMethod("rebalance",
+        String[].class, String[].class, long.class, boolean.class));
 
     this.mockEnvironment = new HashMap<>();
     this.commandRequest = new CommandRequest(this.mockParseResult, this.mockEnvironment, null);

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ExportLogsDUnit.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ExportLogsDUnit.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ExportLogsDUnit.java
index 43ee742..a64620a 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ExportLogsDUnit.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ExportLogsDUnit.java
@@ -111,7 +111,7 @@ public class ExportLogsDUnit {
     ZonedDateTime yesterday = now.minusDays(1);
     ZonedDateTime twoDaysAgo = now.minusDays(2);
 
-    DateTimeFormatter dateTimeFormatter =  DateTimeFormatter.ofPattern(ONLY_DATE_FORMAT);
+    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(ONLY_DATE_FORMAT);
 
     CommandStringBuilder commandStringBuilder = new CommandStringBuilder("export logs");
     commandStringBuilder.addOption("start-time", dateTimeFormatter.format(twoDaysAgo));
@@ -131,7 +131,7 @@ public class ExportLogsDUnit {
     ZonedDateTime yesterday = now.minusDays(1);
     ZonedDateTime tomorrow = now.plusDays(1);
 
-    DateTimeFormatter dateTimeFormatter =  DateTimeFormatter.ofPattern(ONLY_DATE_FORMAT);
+    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(ONLY_DATE_FORMAT);
 
     CommandStringBuilder commandStringBuilder = new CommandStringBuilder("export logs");
     commandStringBuilder.addOption("start-time", dateTimeFormatter.format(yesterday));
@@ -149,18 +149,20 @@ public class ExportLogsDUnit {
   public void testExportWithStartAndEndDateTimeFiltering() throws Exception {
     ZonedDateTime cutoffTime = LocalDateTime.now().atZone(ZoneId.systemDefault());
 
-    String messageAfterCutoffTime = "[this message should not show up since it is after cutoffTime]";
-    LogLine logLineAfterCutoffTime = new LogLine(messageAfterCutoffTime, "info",  true);
+    String messageAfterCutoffTime =
+        "[this message should not show up since it is after cutoffTime]";
+    LogLine logLineAfterCutoffTime = new LogLine(messageAfterCutoffTime, "info", true);
     server1.invoke(() -> {
       Logger logger = LogService.getLogger();
       logLineAfterCutoffTime.writeLog(logger);
     });
 
-    DateTimeFormatter dateTimeFormatter =  DateTimeFormatter.ofPattern(FORMAT);
+    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(FORMAT);
     String cutoffTimeString = dateTimeFormatter.format(cutoffTime);
 
     CommandStringBuilder commandStringBuilder = new CommandStringBuilder("export logs");
-    commandStringBuilder.addOption("start-time", dateTimeFormatter.format(cutoffTime.minusHours(1)));
+    commandStringBuilder.addOption("start-time",
+        dateTimeFormatter.format(cutoffTime.minusHours(1)));
     commandStringBuilder.addOption("end-time", cutoffTimeString);
     commandStringBuilder.addOption("log-level", "debug");
     commandStringBuilder.addOption("dir", "someDir");
@@ -175,9 +177,9 @@ public class ExportLogsDUnit {
   @Test
   public void testExportWithThresholdLogLevelFilter() throws Exception {
 
-    CommandResult result = gfshConnector.executeAndVerifyCommand(
-        "export logs --log-level=info --only-log-level=false --dir=" + lsRule.getTempFolder()
-            .getRoot().getCanonicalPath());
+    CommandResult result = gfshConnector
+        .executeAndVerifyCommand("export logs --log-level=info --only-log-level=false --dir="
+            + lsRule.getTempFolder().getRoot().getCanonicalPath());
 
     Set<String> acceptedLogLevels = Stream.of("info", "error").collect(toSet());
     verifyZipFileContents(acceptedLogLevels);
@@ -186,9 +188,9 @@ public class ExportLogsDUnit {
 
   @Test
   public void testExportWithExactLogLevelFilter() throws Exception {
-    CommandResult result = gfshConnector.executeAndVerifyCommand(
-        "export logs --log-level=info --only-log-level=true --dir=" + lsRule.getTempFolder()
-            .getRoot().getCanonicalPath());
+    CommandResult result = gfshConnector
+        .executeAndVerifyCommand("export logs --log-level=info --only-log-level=true --dir="
+            + lsRule.getTempFolder().getRoot().getCanonicalPath());
 
 
     Set<String> acceptedLogLevels = Stream.of("info").collect(toSet());
@@ -197,8 +199,8 @@ public class ExportLogsDUnit {
 
   @Test
   public void testExportWithNoFilters() throws Exception {
-    CommandResult result = gfshConnector.executeAndVerifyCommand(
-        "export logs  --dir=" + "someDir" /*  lsRule.getTempFolder().getRoot().getCanonicalPath() */);
+    CommandResult result = gfshConnector.executeAndVerifyCommand("export logs  --dir="
+        + "someDir" /* lsRule.getTempFolder().getRoot().getCanonicalPath() */);
 
     Set<String> acceptedLogLevels = Stream.of("info", "error", "debug").collect(toSet());
     verifyZipFileContents(acceptedLogLevels);
@@ -209,8 +211,8 @@ public class ExportLogsDUnit {
     locator.invoke(ExportLogsDUnit::verifyExportLogsRegionWasDestroyed);
   }
 
-@Test
-public void exportLogsRegionIsCleanedUpProperly() throws IOException, ClassNotFoundException {
+  @Test
+  public void exportLogsRegionIsCleanedUpProperly() throws IOException, ClassNotFoundException {
     locator.invoke(() -> {
       ExportLogsFunction.createOrGetExistingExportLogsRegion(true);
       Cache cache = GemFireCacheImpl.getInstance();
@@ -234,11 +236,10 @@ public void exportLogsRegionIsCleanedUpProperly() throws IOException, ClassNotFo
       Cache cache = GemFireCacheImpl.getInstance();
       assertThat(cache.getRegion(ExportLogsFunction.EXPORT_LOGS_REGION)).isNull();
     });
-}
+  }
 
 
-  public void verifyZipFileContents(Set<String> acceptedLogLevels)
-      throws IOException {
+  public void verifyZipFileContents(Set<String> acceptedLogLevels) throws IOException {
     File unzippedLogFileDir = unzipExportedLogs();
 
     Set<File> dirsFromZipFile =
@@ -261,9 +262,7 @@ public void exportLogsRegionIsCleanedUpProperly() throws IOException, ClassNotFo
 
     String memberName = dirForMember.getName();
     Member member = expectedMessages.keySet().stream()
-        .filter((Member aMember) -> aMember.getName().equals(memberName))
-        .findFirst()
-        .get();
+        .filter((Member aMember) -> aMember.getName().equals(memberName)).findFirst().get();
 
     assertThat(member).isNotNull();
 
@@ -276,12 +275,12 @@ public void exportLogsRegionIsCleanedUpProperly() throws IOException, ClassNotFo
     assertThat(logFileForMember).exists();
     assertThat(fileNamesInDir).hasSize(1);
 
-    String logFileContents =
-        FileUtils.readLines(logFileForMember, Charset.defaultCharset()).stream()
-            .collect(joining("\n"));
+    String logFileContents = FileUtils.readLines(logFileForMember, Charset.defaultCharset())
+        .stream().collect(joining("\n"));
 
     for (LogLine logLine : expectedMessages.get(member)) {
-      boolean shouldExpectLogLine = acceptedLogLevels.contains(logLine.level) && !logLine.shouldBeIgnoredDueToTimestamp;
+      boolean shouldExpectLogLine =
+          acceptedLogLevels.contains(logLine.level) && !logLine.shouldBeIgnoredDueToTimestamp;
 
       if (shouldExpectLogLine) {
         assertThat(logFileContents).contains(logLine.getMessage());
@@ -300,7 +299,9 @@ public void exportLogsRegionIsCleanedUpProperly() throws IOException, ClassNotFo
 
     List<File> zipFilesInDir = Stream.of(locatorWorkingDir.listFiles())
         .filter(f -> f.getName().endsWith(".zip")).collect(toList());
-    assertThat(zipFilesInDir).describedAs(filesInDir.stream().map(File::getAbsolutePath).collect(joining(","))).hasSize(1);
+    assertThat(zipFilesInDir)
+        .describedAs(filesInDir.stream().map(File::getAbsolutePath).collect(joining(",")))
+        .hasSize(1);
 
     File unzippedLogFileDir = lsRule.getTempFolder().newFolder("unzippedLogs");
     ZipUtils.unzip(zipFilesInDir.get(0).getCanonicalPath(), unzippedLogFileDir.getCanonicalPath());

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ExportLogsOnServerManagerDUnit.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ExportLogsOnServerManagerDUnit.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ExportLogsOnServerManagerDUnit.java
new file mode 100644
index 0000000..92ef5f5
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ExportLogsOnServerManagerDUnit.java
@@ -0,0 +1,91 @@
+/*
+ * 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.management.internal.cli.commands;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.common.collect.Sets;
+
+import org.apache.geode.internal.AvailablePortHelper;
+import org.apache.geode.test.dunit.rules.GfshShellConnectionRule;
+import org.apache.geode.test.dunit.rules.LocatorServerStartupRule;
+import org.apache.geode.test.dunit.rules.Server;
+import org.apache.geode.test.junit.categories.DistributedTest;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+
+@Category(DistributedTest.class)
+public class ExportLogsOnServerManagerDUnit {
+
+  @Rule
+  public LocatorServerStartupRule lsRule = new LocatorServerStartupRule();
+
+  @Rule
+  public GfshShellConnectionRule gfshConnector = new GfshShellConnectionRule();
+
+  @Test
+  public void testExportWithOneServer() throws Exception {
+    int jmxPort = AvailablePortHelper.getRandomAvailableTCPPort();
+    Server server0 = lsRule.startServerAsJmxManager(0, jmxPort);
+    gfshConnector.connect(jmxPort, GfshShellConnectionRule.PortType.jmxManger);
+    gfshConnector.executeAndVerifyCommand("export logs");
+
+    String message = gfshConnector.getGfshOutput();
+    assertThat(message).contains(server0.getWorkingDir().getAbsolutePath());
+
+    String zipPath = getZipPathFromCommandResult(message);
+
+    Set<String> expectedZipEntries = Sets.newHashSet("server-0/server-0.log");
+    Set<String> actualZipEnries =
+        new ZipFile(zipPath).stream().map(ZipEntry::getName).collect(Collectors.toSet());
+    assertThat(actualZipEnries).isEqualTo(expectedZipEntries);
+  }
+
+  @Test
+  public void testExportWithPeerLocator() throws Exception {
+    int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2);
+    int locatorPort = ports[0];
+    int jmxPort = ports[1];
+    Server server0 = lsRule.startServerAsEmbededLocator(0, locatorPort, jmxPort);
+    Server server1 = lsRule.startServerVM(1, locatorPort);
+    gfshConnector.connect(locatorPort, GfshShellConnectionRule.PortType.locator);
+    gfshConnector.executeAndVerifyCommand("export logs");
+
+    String message = gfshConnector.getGfshOutput();
+    assertThat(message).contains(server0.getWorkingDir().getAbsolutePath());
+
+    String zipPath = getZipPathFromCommandResult(message);
+
+    Set<String> expectedZipEntries =
+        Sets.newHashSet("server-0/server-0.log", "server-1/server-1.log");
+    Set<String> actualZipEnries =
+        new ZipFile(zipPath).stream().map(ZipEntry::getName).collect(Collectors.toSet());
+    assertThat(actualZipEnries).isEqualTo(expectedZipEntries);
+
+  }
+
+  private String getZipPathFromCommandResult(String message) {
+    return message.replaceAll("Logs exported to the connected member's file system: ", "").trim();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/ExportLogsFunctionIntegrationTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/ExportLogsFunctionIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/ExportLogsFunctionIntegrationTest.java
index abae1de..bb083be 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/ExportLogsFunctionIntegrationTest.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/ExportLogsFunctionIntegrationTest.java
@@ -56,7 +56,8 @@ public class ExportLogsFunctionIntegrationTest {
   public void setup() throws Exception {
     serverWorkingDir = temporaryFolder.newFolder("serverWorkingDir");
     System.setProperty("user.dir", serverWorkingDir.getCanonicalPath());
-
+    // fix a ci pipeline glitch
+    System.clearProperty("user.home");
     serverStarterRule.startServer();
   }
 
@@ -87,7 +88,7 @@ public class ExportLogsFunctionIntegrationTest {
     }
 
     Cache cache = GemFireCacheImpl.getInstance();
-    assertThat(cache.getRegion(ExportLogsFunction.EXPORT_LOGS_REGION)).isNull();
+    assertThat(cache.getRegion(ExportLogsFunction.EXPORT_LOGS_REGION)).isEmpty();
   }
 
   @Test
@@ -99,7 +100,8 @@ public class ExportLogsFunctionIntegrationTest {
   }
 
   @Test
-  public void destroyExportLogsRegionWorksAsExpectedForInitiatingMember() throws IOException, ClassNotFoundException {
+  public void destroyExportLogsRegionWorksAsExpectedForInitiatingMember()
+      throws IOException, ClassNotFoundException {
     ExportLogsFunction.createOrGetExistingExportLogsRegion(true);
     Cache cache = GemFireCacheImpl.getInstance();
     assertThat(cache.getRegion(ExportLogsFunction.EXPORT_LOGS_REGION)).isNotNull();

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/test/java/org/apache/geode/management/internal/cli/util/LogExporterTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/util/LogExporterTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/util/LogExporterTest.java
index bd8a6ac..4cb76d3 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/util/LogExporterTest.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/util/LogExporterTest.java
@@ -32,7 +32,6 @@ import org.junit.experimental.categories.Category;
 import org.junit.rules.TemporaryFolder;
 
 import java.io.File;
-import java.nio.file.Files;
 import java.nio.file.Path;
 import java.text.ParseException;
 import java.util.Comparator;
@@ -96,9 +95,4 @@ public class LogExporterTest {
     assertThat(logExporter.findLogFiles(workingDir.toPath())).doesNotContain(notALogFile.toPath());
   }
 
-  @Test
-  public void findStatFiles() throws Exception {
-
-  }
-
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/test/java/org/apache/geode/management/internal/cli/util/MergeLogsDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/util/MergeLogsDUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/util/MergeLogsDUnitTest.java
new file mode 100644
index 0000000..80b9868
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/util/MergeLogsDUnitTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.management.internal.cli.util;
+
+import static java.util.stream.Collectors.joining;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.geode.distributed.internal.DistributionConfig;
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.test.dunit.rules.Locator;
+import org.apache.geode.test.dunit.rules.LocatorServerStartupRule;
+import org.apache.geode.test.dunit.rules.Server;
+import org.apache.geode.test.junit.categories.DistributedTest;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.Properties;
+
+@Category(DistributedTest.class)
+public class MergeLogsDUnitTest {
+  @Rule
+  public LocatorServerStartupRule lsRule = new LocatorServerStartupRule();
+  private Locator locator;
+
+  private static final String MESSAGE_1 = "MergeLogsMessage1";
+  private static final String MESSAGE_2 = "MergeLogsMessage2";
+  private static final String MESSAGE_3 = "MergeLogsMessage3";
+  private static final String MESSAGE_4 = "MergeLogsMessage4";
+  private static final String MESSAGE_5 = "MergeLogsMessage5";
+  private static final String MESSAGE_6 = "MergeLogsMessage6";
+
+  @Before
+  public void setup() throws Exception {
+    Properties properties = new Properties();
+    properties.setProperty(DistributionConfig.LOG_LEVEL_NAME, "info");
+    locator = lsRule.startLocatorVM(0, properties);
+
+    properties.setProperty(DistributionConfig.LOCATORS_NAME,
+        "localhost[" + locator.getPort() + "]");
+
+    Server server = lsRule.startServerVM(1, properties);
+    Server server2 = lsRule.startServerVM(2, properties);
+
+    locator.invoke(() -> LogService.getLogger().info(MESSAGE_1));
+    server.invoke(() -> LogService.getLogger().info(MESSAGE_2));
+    server2.invoke(() -> LogService.getLogger().info(MESSAGE_3));
+
+    locator.invoke(() -> LogService.getLogger().info(MESSAGE_4));
+    server.invoke(() -> LogService.getLogger().info(MESSAGE_5));
+    server2.invoke(() -> LogService.getLogger().info(MESSAGE_6));
+  }
+
+  @Test
+  public void testExportInProcess() throws Exception {
+    assertThat(MergeLogs.findLogFilesToMerge(lsRule.getTempFolder().getRoot())).hasSize(3);
+
+    File result = MergeLogs.mergeLogFile(lsRule.getTempFolder().getRoot().getCanonicalPath());
+    assertOnLogContents(result);
+  }
+
+  @Test
+  public void testExportInNewProcess() throws Throwable {
+    assertThat(MergeLogs.findLogFilesToMerge(lsRule.getTempFolder().getRoot())).hasSize(3);
+
+    MergeLogs.mergeLogsInNewProcess(lsRule.getTempFolder().getRoot().toPath());
+    File result = Arrays.stream(lsRule.getTempFolder().getRoot().listFiles())
+        .filter((File f) -> f.getName().startsWith("merge")).findFirst().orElseThrow(() -> {
+          throw new AssertionError("No merged log file found");
+        });
+    assertOnLogContents(result);
+
+  }
+
+  private void assertOnLogContents(File mergedLogFile) throws IOException {
+    String mergedLines = FileUtils.readLines(mergedLogFile, Charset.defaultCharset()).stream()
+        .collect(joining("\n"));
+
+    assertThat(mergedLines).contains(MESSAGE_1);
+    assertThat(mergedLines).contains(MESSAGE_2);
+    assertThat(mergedLines).contains(MESSAGE_3);
+    assertThat(mergedLines).contains(MESSAGE_4);
+    assertThat(mergedLines).contains(MESSAGE_5);
+    assertThat(mergedLines).contains(MESSAGE_6);
+
+    // Make sure that our merged log file contains the proper ordering
+    assertThat(mergedLines.indexOf(MESSAGE_1)).isLessThan(mergedLines.indexOf(MESSAGE_2));
+    assertThat(mergedLines.indexOf(MESSAGE_2)).isLessThan(mergedLines.indexOf(MESSAGE_3));
+    assertThat(mergedLines.indexOf(MESSAGE_3)).isLessThan(mergedLines.indexOf(MESSAGE_4));
+    assertThat(mergedLines.indexOf(MESSAGE_4)).isLessThan(mergedLines.indexOf(MESSAGE_5));
+    assertThat(mergedLines.indexOf(MESSAGE_5)).isLessThan(mergedLines.indexOf(MESSAGE_6));
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/test/java/org/apache/geode/management/internal/cli/util/MergeLogsTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/util/MergeLogsTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/util/MergeLogsTest.java
deleted file mode 100644
index 7f4ffd4..0000000
--- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/util/MergeLogsTest.java
+++ /dev/null
@@ -1,114 +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.management.internal.cli.util;
-
-import static java.util.stream.Collectors.joining;
-import static org.assertj.core.api.Assertions.assertThat;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.geode.distributed.internal.DistributionConfig;
-import org.apache.geode.internal.logging.LogService;
-import org.apache.geode.management.cli.Result;
-import org.apache.geode.test.dunit.rules.Locator;
-import org.apache.geode.test.dunit.rules.LocatorServerStartupRule;
-import org.apache.geode.test.dunit.rules.Server;
-import org.apache.geode.test.junit.categories.DistributedTest;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.Arrays;
-import java.util.Properties;
-
-@Category(DistributedTest.class)
-public class MergeLogsTest {
-  @Rule
-  public LocatorServerStartupRule lsRule = new LocatorServerStartupRule();
-  private Locator locator;
-
-  private static final String MESSAGE_1 = "MergeLogsMessage1";
-  private static final String MESSAGE_2 = "MergeLogsMessage2";
-  private static final String MESSAGE_3 = "MergeLogsMessage3";
-  private static final String MESSAGE_4 = "MergeLogsMessage4";
-  private static final String MESSAGE_5 = "MergeLogsMessage5";
-  private static final String MESSAGE_6 = "MergeLogsMessage6";
-
-  @Before
-  public void setup() throws Exception {
-    Properties properties = new Properties();
-    properties.setProperty(DistributionConfig.LOG_LEVEL_NAME, "info");
-    locator = lsRule.startLocatorVM(0, properties);
-
-    properties
-        .setProperty(DistributionConfig.LOCATORS_NAME, "localhost[" + locator.getPort() + "]");
-
-    Server server = lsRule.startServerVM(1, properties);
-    Server server2 = lsRule.startServerVM(2, properties);
-
-    locator.invoke(() -> LogService.getLogger().info(MESSAGE_1));
-    server.invoke(() -> LogService.getLogger().info(MESSAGE_2));
-    server2.invoke(() -> LogService.getLogger().info(MESSAGE_3));
-
-    locator.invoke(() -> LogService.getLogger().info(MESSAGE_4));
-    server.invoke(() -> LogService.getLogger().info(MESSAGE_5));
-    server2.invoke(() -> LogService.getLogger().info(MESSAGE_6));
-  }
-
-  @Test
-  public void testExportInProcess() throws Exception {
-    assertThat(MergeLogs.findLogFilesToMerge(lsRule.getTempFolder().getRoot())).hasSize(3);
-
-    File result = MergeLogs.mergeLogFile(lsRule.getTempFolder().getRoot().getCanonicalPath());
-    assertOnLogContents(result);
-  }
-    @Test
-  public void testExportInNewProcess() throws Throwable {
-    assertThat(MergeLogs.findLogFilesToMerge(lsRule.getTempFolder().getRoot())).hasSize(3);
-
-    MergeLogs.mergeLogsInNewProcess(lsRule.getTempFolder().getRoot().toPath());
-      File result = Arrays.stream(lsRule.getTempFolder().getRoot().listFiles()).filter((File f) -> f.getName().startsWith("merge"))
-            .findFirst().orElseThrow(() -> {throw new AssertionError("No merged log file found");});
-    assertOnLogContents(result);
-
-  }
-
-  private void assertOnLogContents (File mergedLogFile) throws IOException {
-    String
-        mergedLines =
-        FileUtils.readLines(mergedLogFile, Charset.defaultCharset()).stream().collect(joining("\n"));
-
-    assertThat(mergedLines).contains(MESSAGE_1);
-    assertThat(mergedLines).contains(MESSAGE_2);
-    assertThat(mergedLines).contains(MESSAGE_3);
-    assertThat(mergedLines).contains(MESSAGE_4);
-    assertThat(mergedLines).contains(MESSAGE_5);
-    assertThat(mergedLines).contains(MESSAGE_6);
-
-    //Make sure that our merged log file contains the proper ordering
-    assertThat(mergedLines.indexOf(MESSAGE_1)).isLessThan(mergedLines.indexOf(MESSAGE_2));
-    assertThat(mergedLines.indexOf(MESSAGE_2)).isLessThan(mergedLines.indexOf(MESSAGE_3));
-    assertThat(mergedLines.indexOf(MESSAGE_3)).isLessThan(mergedLines.indexOf(MESSAGE_4));
-    assertThat(mergedLines.indexOf(MESSAGE_4)).isLessThan(mergedLines.indexOf(MESSAGE_5));
-    assertThat(mergedLines.indexOf(MESSAGE_5)).isLessThan(mergedLines.indexOf(MESSAGE_6));
-  }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/geode/blob/92582fbd/geode-core/src/test/java/org/apache/geode/management/internal/security/GfshCommandsSecurityTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/security/GfshCommandsSecurityTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/security/GfshCommandsSecurityTest.java
index d1750c3..ef8b7f1 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/security/GfshCommandsSecurityTest.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/security/GfshCommandsSecurityTest.java
@@ -156,9 +156,7 @@ public class GfshCommandsSecurityTest {
     List<TestCommand> allPermitted =
         TestCommand.getPermittedCommands(new WildcardPermission(permission, true));
     for (TestCommand permitted : allPermitted) {
-      LogService.getLogger().info("Processing authorized command: " + permitted.getCommand());
-
-
+      System.out.println("Processing authorized command: " + permitted.getCommand());
       CommandResult result = gfshConnection.executeCommand(permitted.getCommand());
       assertNotNull(result);
 
@@ -177,7 +175,7 @@ public class GfshCommandsSecurityTest {
       if (other.getPermission() == null)
         continue;
 
-      LogService.getLogger().info("Processing unauthorized command: " + other.getCommand());
+      System.out.println("Processing unauthorized command: " + other.getCommand());
       CommandResult result = (CommandResult) gfshConnection.executeCommand(other.getCommand());
       int errorCode = ((ErrorResultData) result.getResultData()).getErrorCode();