This is an automated email from the ASF dual-hosted git repository.

jensdeppe pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new 1e7c05c  GEODE-5011: Convert ExecuteFunctionCommand and 
ExportConfigCommand to use ResultModel (#1901)
1e7c05c is described below

commit 1e7c05c1832705d48fd035d180331418b7bb0d81
Author: Jens Deppe <jde...@pivotal.io>
AuthorDate: Tue May 8 08:11:02 2018 -0700

    GEODE-5011: Convert ExecuteFunctionCommand and ExportConfigCommand to use 
ResultModel (#1901)
---
 .../internal/cli/CliAroundInterceptor.java         |   5 +-
 .../cli/commands/ExecuteFunctionCommand.java       |  26 ++--
 .../internal/cli/commands/ExportConfigCommand.java |  46 +++---
 .../ExportImportClusterConfigurationCommands.java  |   7 +-
 .../cli/commands/ExportLogsInterceptor.java        |   8 +-
 .../internal/cli/commands/QueryInterceptor.java    |   6 +-
 .../internal/cli/result/AbstractResultData.java    |  12 --
 .../internal/cli/result/CompositeResultData.java   |   4 +-
 .../internal/cli/result/LegacyCommandResult.java   |  12 +-
 .../internal/cli/result/ModelCommandResult.java    |   7 +-
 .../management/internal/cli/result/ResultData.java |  12 +-
 .../cli/result/model/AbstractResultModel.java      |   1 +
 .../internal/cli/result/model/FileResultModel.java | 162 +++++++++++++++++++++
 .../internal/cli/result/model/ResultModel.java     |  23 +++
 .../internal/cli/shell/GfshExecutionStrategy.java  |   6 +-
 .../cli/commands/ExecuteFunctionCommandTest.java   |  52 +++++++
 .../cli/commands/ExportConfigCommandTest.java      |  52 +++++++
 .../internal/cli/commands/CommandOverHttpTest.java |   4 +-
 .../cli/commands/ExportConfigCommandDUnitTest.java |   1 +
 19 files changed, 376 insertions(+), 70 deletions(-)

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 ccd60a0..59431fe 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
@@ -16,7 +16,7 @@ package org.apache.geode.management.internal.cli;
 
 import java.nio.file.Path;
 
-import org.apache.geode.management.cli.Result;
+import org.apache.geode.management.internal.cli.result.CommandResult;
 import org.apache.geode.management.internal.cli.result.ResultBuilder;
 import org.apache.geode.management.internal.cli.shell.GfshExecutionStrategy;
 
@@ -42,7 +42,8 @@ public interface CliAroundInterceptor {
    * @param tempFile if the command's isFileDownloadOverHttp is true, the is 
the File downloaded
    *        after the http response is processed.
    */
-  default Result postExecution(GfshParseResult parseResult, Result 
commandResult, Path tempFile) {
+  default CommandResult postExecution(GfshParseResult parseResult, 
CommandResult commandResult,
+      Path tempFile) {
     return commandResult;
   }
 
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExecuteFunctionCommand.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExecuteFunctionCommand.java
index 909e053..4611503 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExecuteFunctionCommand.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExecuteFunctionCommand.java
@@ -35,15 +35,14 @@ import 
org.apache.geode.management.internal.cli.GfshParseResult;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import 
org.apache.geode.management.internal.cli.functions.UserFunctionExecution;
 import org.apache.geode.management.internal.cli.i18n.CliStrings;
-import org.apache.geode.management.internal.cli.result.CompositeResultData;
-import org.apache.geode.management.internal.cli.result.ResultBuilder;
-import org.apache.geode.management.internal.cli.result.TabularResultData;
+import org.apache.geode.management.internal.cli.result.model.ResultModel;
+import 
org.apache.geode.management.internal.cli.result.model.TabularResultModel;
 
 public class ExecuteFunctionCommand extends InternalGfshCommand {
   @CliCommand(value = CliStrings.EXECUTE_FUNCTION, help = 
CliStrings.EXECUTE_FUNCTION__HELP)
   @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_FUNCTION},
       interceptor = 
"org.apache.geode.management.internal.cli.commands.ExecuteFunctionCommand$ExecuteFunctionCommandInterceptor")
-  public Result executeFunction(
+  public ResultModel executeFunction(
       @CliOption(key = CliStrings.EXECUTE_FUNCTION__ID, mandatory = true,
           help = CliStrings.EXECUTE_FUNCTION__ID__HELP) String functionId,
       @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
@@ -62,8 +61,8 @@ public class ExecuteFunctionCommand extends 
InternalGfshCommand {
       @CliOption(key = CliStrings.EXECUTE_FUNCTION__FILTER,
           help = CliStrings.EXECUTE_FUNCTION__FILTER__HELP) String 
filterString) {
 
-    CompositeResultData executeFunctionResultTable = 
ResultBuilder.createCompositeResultData();
-    TabularResultData resultTable = 
executeFunctionResultTable.addSection().addTable("Table1");
+    ResultModel resultModel = new ResultModel();
+    TabularResultModel resultTable = resultModel.addTable("Table1");
     String headerText = "Execution summary";
     resultTable.setHeader(headerText);
 
@@ -78,7 +77,7 @@ public class ExecuteFunctionCommand extends 
InternalGfshCommand {
     }
 
     if (dsMembers.size() == 0) {
-      return ResultBuilder.createUserErrorResult("No members found.");
+      return new ResultModel().createError("No members found.");
     }
 
     // Build up our argument list
@@ -116,16 +115,16 @@ public class ExecuteFunctionCommand extends 
InternalGfshCommand {
       resultTable.accumulate("Member ID/Name", r.getMemberIdOrName());
       resultTable.accumulate("Function Execution Result", r.getMessage());
       if (!r.isSuccessful()) {
-        resultTable.setStatus(Result.Status.ERROR);
+        resultModel.setStatus(Result.Status.ERROR);
       }
     }
 
-    return ResultBuilder.buildResult(resultTable);
+    return resultModel;
   }
 
   public static class ExecuteFunctionCommandInterceptor implements 
CliAroundInterceptor {
     @Override
-    public Result preExecution(GfshParseResult parseResult) {
+    public ResultModel preExecution(GfshParseResult parseResult) {
       String onRegion = 
parseResult.getParamValueAsString(CliStrings.EXECUTE_FUNCTION__ONREGION);
       String onMember = parseResult.getParamValueAsString(CliStrings.MEMBER);
       String onGroup = parseResult.getParamValueAsString(CliStrings.GROUP);
@@ -134,16 +133,17 @@ public class ExecuteFunctionCommand extends 
InternalGfshCommand {
       boolean moreThanOne =
           Stream.of(onRegion, onMember, 
onGroup).filter(Objects::nonNull).count() > 1;
 
+      ResultModel result = new ResultModel();
       if (moreThanOne) {
-        return 
ResultBuilder.createUserErrorResult(CliStrings.EXECUTE_FUNCTION__MSG__OPTIONS);
+        return result.createError(CliStrings.EXECUTE_FUNCTION__MSG__OPTIONS);
       }
 
       if (onRegion == null && filter != null) {
-        return ResultBuilder.createUserErrorResult(
+        return result.createError(
             
CliStrings.EXECUTE_FUNCTION__MSG__MEMBER_SHOULD_NOT_HAVE_FILTER_FOR_EXECUTION);
       }
 
-      return ResultBuilder.createInfoResult("");
+      return result;
     }
   }
 }
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommand.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommand.java
index 81fc924..bb82b3c 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommand.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommand.java
@@ -28,15 +28,16 @@ import org.apache.geode.cache.execute.ResultCollector;
 import org.apache.geode.distributed.DistributedMember;
 import org.apache.geode.management.cli.CliMetaData;
 import org.apache.geode.management.cli.ConverterHint;
-import org.apache.geode.management.cli.Result;
 import org.apache.geode.management.internal.cli.AbstractCliAroundInterceptor;
 import org.apache.geode.management.internal.cli.CliUtil;
 import org.apache.geode.management.internal.cli.GfshParseResult;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import org.apache.geode.management.internal.cli.functions.ExportConfigFunction;
 import org.apache.geode.management.internal.cli.i18n.CliStrings;
-import org.apache.geode.management.internal.cli.result.InfoResultData;
-import org.apache.geode.management.internal.cli.result.ResultBuilder;
+import org.apache.geode.management.internal.cli.result.CommandResult;
+import org.apache.geode.management.internal.cli.result.ResultData;
+import org.apache.geode.management.internal.cli.result.model.InfoResultModel;
+import org.apache.geode.management.internal.cli.result.model.ResultModel;
 import org.apache.geode.management.internal.cli.shell.Gfsh;
 import org.apache.geode.management.internal.security.ResourceOperation;
 import org.apache.geode.security.ResourcePermission;
@@ -57,7 +58,7 @@ public class ExportConfigCommand extends InternalGfshCommand {
       relatedTopic = {CliStrings.TOPIC_GEODE_CONFIG})
   @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
       operation = ResourcePermission.Operation.READ)
-  public Result exportConfig(
+  public ResultModel exportConfig(
       @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS},
           optionContext = ConverterHint.ALL_MEMBER_IDNAME,
           help = CliStrings.EXPORT_CONFIG__MEMBER__HELP) String[] member,
@@ -66,11 +67,14 @@ public class ExportConfigCommand extends 
InternalGfshCommand {
           help = CliStrings.EXPORT_CONFIG__GROUP__HELP) String[] group,
       @CliOption(key = {CliStrings.EXPORT_CONFIG__DIR},
           help = CliStrings.EXPORT_CONFIG__DIR__HELP) String dir) {
-    InfoResultData infoData = ResultBuilder.createInfoResultData();
+
+    ResultModel crm = new ResultModel();
+    InfoResultModel infoData = crm.addInfo();
 
     Set<DistributedMember> targetMembers = findMembers(group, member);
     if (targetMembers.isEmpty()) {
-      return 
ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
+      crm.createError(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
+      return crm;
     }
 
     ResultCollector<?, ?> rc =
@@ -85,13 +89,14 @@ public class ExportConfigCommand extends 
InternalGfshCommand {
         String cacheFileName = result.getMemberIdOrName() + "-cache.xml";
         String propsFileName = result.getMemberIdOrName() + "-gf.properties";
         String[] fileContent = (String[]) result.getSerializables();
-        infoData.addAsFile(cacheFileName, fileContent[0], "Downloading Cache 
XML file: {0}", false);
-        infoData.addAsFile(propsFileName, fileContent[1], "Downloading 
properties file: {0}",
-            false);
+        crm.addFile(cacheFileName, fileContent[0].getBytes(), 
ResultData.FILE_TYPE_TEXT,
+            "Downloading Cache XML file: ", false);
+        crm.addFile(propsFileName, fileContent[1].getBytes(), 
ResultData.FILE_TYPE_TEXT,
+            "Downloading properties file: ", false);
       }
     }
-    return ResultBuilder.buildResult(infoData);
 
+    return crm;
   }
 
   /**
@@ -101,41 +106,42 @@ public class ExportConfigCommand extends 
InternalGfshCommand {
     private String saveDirString;
 
     @Override
-    public Result preExecution(GfshParseResult parseResult) {
+    public ResultModel preExecution(GfshParseResult parseResult) {
       String dir = parseResult.getParamValueAsString("dir");
       if (StringUtils.isBlank(dir)) {
         saveDirString = new File(".").getAbsolutePath();
-        return ResultBuilder.createInfoResult("OK");
+        return new ResultModel();
       }
 
       File saveDirFile = new File(dir.trim());
 
       if (!saveDirFile.exists() && !saveDirFile.mkdirs()) {
-        return ResultBuilder.createGemFireErrorResult(
-            
CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__CANNOT_CREATE_DIR, dir));
+        return ResultModel
+            
.createError(CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__CANNOT_CREATE_DIR,
 dir));
       }
 
       if (!saveDirFile.isDirectory()) {
-        return ResultBuilder.createGemFireErrorResult(
-            CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__NOT_A_DIRECTORY, 
dir));
+        return ResultModel
+            
.createError(CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__NOT_A_DIRECTORY, 
dir));
       }
 
       try {
         if (!saveDirFile.canWrite()) {
-          return ResultBuilder.createGemFireErrorResult(CliStrings.format(
+          return ResultModel.createError(CliStrings.format(
               CliStrings.EXPORT_CONFIG__MSG__NOT_WRITEABLE, 
saveDirFile.getCanonicalPath()));
         }
       } catch (IOException ioex) {
-        return ResultBuilder.createGemFireErrorResult(
+        return ResultModel.createError(
             CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__NOT_WRITEABLE, 
saveDirFile.getName()));
       }
 
       saveDirString = saveDirFile.getAbsolutePath();
-      return ResultBuilder.createInfoResult("OK");
+      return new ResultModel();
     }
 
     @Override
-    public Result postExecution(GfshParseResult parseResult, Result 
commandResult, Path tempFile) {
+    public CommandResult postExecution(GfshParseResult parseResult, 
CommandResult commandResult,
+        Path tempFile) {
       if (commandResult.hasIncomingFiles()) {
         try {
           commandResult.saveIncomingFiles(saveDirString);
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportClusterConfigurationCommands.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportClusterConfigurationCommands.java
index 162b33d..797d935 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportClusterConfigurationCommands.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportClusterConfigurationCommands.java
@@ -48,10 +48,12 @@ import 
org.apache.geode.management.internal.cli.GfshParseResult;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import org.apache.geode.management.internal.cli.i18n.CliStrings;
 import org.apache.geode.management.internal.cli.remote.CommandExecutionContext;
+import org.apache.geode.management.internal.cli.result.CommandResult;
 import org.apache.geode.management.internal.cli.result.ErrorResultData;
 import org.apache.geode.management.internal.cli.result.FileResult;
 import org.apache.geode.management.internal.cli.result.InfoResultData;
 import org.apache.geode.management.internal.cli.result.ResultBuilder;
+import org.apache.geode.management.internal.cli.result.ResultData;
 import org.apache.geode.management.internal.cli.shell.Gfsh;
 import org.apache.geode.management.internal.configuration.domain.Configuration;
 import 
org.apache.geode.management.internal.configuration.functions.GetRegionNamesFunction;
@@ -105,7 +107,7 @@ public class ExportImportClusterConfigurationCommands 
extends InternalGfshComman
 
       InfoResultData infoData = ResultBuilder.createInfoResultData();
       byte[] byteData = FileUtils.readFileToByteArray(zipFile);
-      infoData.addAsFile(zipFileName, byteData, 
InfoResultData.FILE_TYPE_BINARY,
+      infoData.addAsFile(zipFileName, byteData, ResultData.FILE_TYPE_BINARY,
           CliStrings.EXPORT_SHARED_CONFIG__DOWNLOAD__MSG, false);
       result = ResultBuilder.buildResult(infoData);
     } catch (Exception e) {
@@ -237,7 +239,8 @@ public class ExportImportClusterConfigurationCommands 
extends InternalGfshComman
     }
 
     @Override
-    public Result postExecution(GfshParseResult parseResult, Result 
commandResult, Path tempFile) {
+    public CommandResult postExecution(GfshParseResult parseResult, 
CommandResult commandResult,
+        Path tempFile) {
       if (commandResult.hasIncomingFiles()) {
         try {
           commandResult.saveIncomingFiles(System.getProperty("user.dir"));
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportLogsInterceptor.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportLogsInterceptor.java
index 5f13784..1d2da28 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportLogsInterceptor.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportLogsInterceptor.java
@@ -30,6 +30,7 @@ import org.apache.geode.management.cli.Result;
 import org.apache.geode.management.internal.cli.AbstractCliAroundInterceptor;
 import org.apache.geode.management.internal.cli.GfshParseResult;
 import org.apache.geode.management.internal.cli.functions.ExportLogsFunction;
+import org.apache.geode.management.internal.cli.result.CommandResult;
 import org.apache.geode.management.internal.cli.result.ResultBuilder;
 
 /**
@@ -77,7 +78,8 @@ public class ExportLogsInterceptor extends 
AbstractCliAroundInterceptor {
   }
 
   @Override
-  public Result postExecution(GfshParseResult parseResult, Result 
commandResult, Path tempFile) {
+  public CommandResult postExecution(GfshParseResult parseResult, 
CommandResult commandResult,
+      Path tempFile) {
     // in the command over http case, the command result is in the downloaded 
temp file
     if (tempFile != null) {
       Path dirPath;
@@ -92,14 +94,14 @@ public class ExportLogsInterceptor extends 
AbstractCliAroundInterceptor {
       try {
         FileUtils.copyFile(tempFile.toFile(), exportedLogFile);
         FileUtils.deleteQuietly(tempFile.toFile());
-        commandResult = ResultBuilder
+        commandResult = (CommandResult) ResultBuilder
             .createInfoResult("Logs exported to: " + 
exportedLogFile.getAbsolutePath());
       } catch (IOException e) {
         logger.error(e.getMessage(), e);
         commandResult = ResultBuilder.createGemFireErrorResult(e.getMessage());
       }
     } else if (commandResult.getStatus() == Result.Status.OK) {
-      commandResult = ResultBuilder.createInfoResult(
+      commandResult = (CommandResult) ResultBuilder.createInfoResult(
           "Logs exported to the connected member's file system: " + 
commandResult.nextLine());
     }
     return commandResult;
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/QueryInterceptor.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/QueryInterceptor.java
index 53f4ad9..e9f8ce2 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/QueryInterceptor.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/QueryInterceptor.java
@@ -50,15 +50,15 @@ public class QueryInterceptor extends 
AbstractCliAroundInterceptor {
   }
 
   @Override
-  public Result postExecution(GfshParseResult parseResult, Result result, Path 
tempFile) {
+  public CommandResult postExecution(GfshParseResult parseResult, 
CommandResult result,
+      Path tempFile) {
     File outputFile = getOutputFile(parseResult);
 
     if (outputFile == null) {
       return result;
     }
 
-    CommandResult commandResult = (CommandResult) result;
-    CompositeResultData resultData = (CompositeResultData) 
commandResult.getResultData();
+    CompositeResultData resultData = (CompositeResultData) 
result.getResultData();
     CompositeResultData.SectionResultData sectionResultData = 
resultData.retrieveSectionByIndex(0);
 
     String limit = sectionResultData.retrieveString("Limit");
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/AbstractResultData.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/AbstractResultData.java
index c19b569..fd3c636 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/AbstractResultData.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/AbstractResultData.java
@@ -39,18 +39,6 @@ import org.apache.geode.management.internal.cli.shell.Gfsh;
  * @since GemFire 7.0
  */
 public abstract class AbstractResultData implements ResultData {
-  public static final String SECTION_DATA_ACCESSOR = "__sections__";
-  public static final String TABLE_DATA_ACCESSOR = "__tables__";
-  public static final String BYTE_DATA_ACCESSOR = "__bytes__";
-
-  public static final int FILE_TYPE_BINARY = 0;
-  public static final int FILE_TYPE_TEXT = 1;
-  private static final String FILE_NAME_FIELD = "fileName";
-  private static final String FILE_TYPE_FIELD = "fileType";
-  private static final String FILE_DATA_FIELD = "fileData";
-  private static final String DATA_FIELD = "data";
-  private static final String DATA_LENGTH_FIELD = "dataLength";
-  private static final String FILE_MESSAGE = "fileMessage";
 
   protected GfJsonObject gfJsonObject;
   protected GfJsonObject contentObject;
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/CompositeResultData.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/CompositeResultData.java
index b947621..3b73f52 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/CompositeResultData.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/CompositeResultData.java
@@ -93,7 +93,7 @@ public class CompositeResultData extends AbstractResultData {
     int i = 0;
     for (Iterator<String> iterator = contentObject.keys(); 
iterator.hasNext();) {
       String key = iterator.next();
-      if (key.startsWith(CompositeResultData.SECTION_DATA_ACCESSOR)) {
+      if (key.startsWith(ResultData.SECTION_DATA_ACCESSOR)) {
         if (i == index) {
           sectionToRetrieve = new 
SectionResultData(contentObject.getJSONObject(key));
           break;
@@ -204,7 +204,7 @@ public class CompositeResultData extends AbstractResultData 
{
       int i = 0;
       for (Iterator<String> iterator = sectionGfJsonObject.keys(); 
iterator.hasNext();) {
         String key = iterator.next();
-        if (key.startsWith(CompositeResultData.TABLE_DATA_ACCESSOR)) {
+        if (key.startsWith(ResultData.TABLE_DATA_ACCESSOR)) {
           if (i == index) {
             tabularResultData = new 
TabularResultData(sectionGfJsonObject.getJSONObject(key));
             break;
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/LegacyCommandResult.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/LegacyCommandResult.java
index a56fe67..353e7e0 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/LegacyCommandResult.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/LegacyCommandResult.java
@@ -183,7 +183,7 @@ public class LegacyCommandResult implements CommandResult {
 
         for (Iterator<String> it = content.keys(); it.hasNext();) {
           String key = it.next();
-          if (key.startsWith(CompositeResultData.SECTION_DATA_ACCESSOR)) {
+          if (key.startsWith(ResultData.SECTION_DATA_ACCESSOR)) {
             GfJsonObject subSection = content.getJSONObject(key);
             buildSection(resultTable, null, subSection, 0);
           } else if (key.equals(CompositeResultData.SEPARATOR)) {
@@ -218,7 +218,7 @@ public class LegacyCommandResult implements CommandResult {
     while (keys.hasNext()) {
       String key = keys.next();
       Object object = section.get(key);
-      if (key.startsWith(CompositeResultData.TABLE_DATA_ACCESSOR)) {
+      if (key.startsWith(ResultData.TABLE_DATA_ACCESSOR)) {
         GfJsonObject tableObject = section.getJSONObject(key);
 
         addHeaderInTable(table, tableObject);
@@ -273,7 +273,7 @@ public class LegacyCommandResult implements CommandResult {
     // build Table Header first
     for (int i = 0; i < numOfColumns; i++) {
       Object object = columnNames.get(i);
-      if (AbstractResultData.BYTE_DATA_ACCESSOR.equals(object)) {
+      if (ResultData.BYTE_DATA_ACCESSOR.equals(object)) {
         // skip file data if any
         continue;
       }
@@ -284,7 +284,7 @@ public class LegacyCommandResult implements CommandResult {
     Row[] dataRows = null;
     for (int i = 0; i < numOfColumns; i++) {
       Object object = columnNames.get(i);
-      if (AbstractResultData.BYTE_DATA_ACCESSOR.equals(object)) {
+      if (ResultData.BYTE_DATA_ACCESSOR.equals(object)) {
         // skip file data if any
         continue;
       }
@@ -320,7 +320,7 @@ public class LegacyCommandResult implements CommandResult {
     try {
       GfJsonObject content = getContent();
       if (content != null) {
-        fileDataArray = 
content.getJSONArray(CompositeResultData.BYTE_DATA_ACCESSOR);
+        fileDataArray = content.getJSONArray(ResultData.BYTE_DATA_ACCESSOR);
       }
     } catch (GfJsonException e) {
       e.printStackTrace();
@@ -339,7 +339,7 @@ public class LegacyCommandResult implements CommandResult {
     try {
       GfJsonObject content = getContent();
       if (content != null) {
-        GfJsonArray bytesArray = 
content.getJSONArray(CompositeResultData.BYTE_DATA_ACCESSOR);
+        GfJsonArray bytesArray = 
content.getJSONArray(ResultData.BYTE_DATA_ACCESSOR);
         AbstractResultData.readFileDataAndDump(bytesArray, directory);
       } else {
         throw new RuntimeException("No associated files to save .. ");
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ModelCommandResult.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ModelCommandResult.java
index 092c3b2..0824910 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ModelCommandResult.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ModelCommandResult.java
@@ -27,6 +27,7 @@ import org.apache.geode.management.internal.cli.GfshParser;
 import org.apache.geode.management.internal.cli.json.GfJsonObject;
 import 
org.apache.geode.management.internal.cli.result.model.AbstractResultModel;
 import org.apache.geode.management.internal.cli.result.model.DataResultModel;
+import org.apache.geode.management.internal.cli.result.model.FileResultModel;
 import org.apache.geode.management.internal.cli.result.model.InfoResultModel;
 import org.apache.geode.management.internal.cli.result.model.ResultModel;
 import 
org.apache.geode.management.internal.cli.result.model.TabularResultModel;
@@ -72,7 +73,7 @@ public class ModelCommandResult implements CommandResult {
 
   @Override
   public boolean hasIncomingFiles() {
-    return false;
+    return result.getFiles().size() > 0;
   }
 
   @Override
@@ -82,7 +83,9 @@ public class ModelCommandResult implements CommandResult {
 
   @Override
   public void saveIncomingFiles(String directory) throws IOException {
-
+    for (FileResultModel file : result.getFiles().values()) {
+      file.writeFile(directory);
+    }
   }
 
   @Override
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ResultData.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ResultData.java
index a4ca7eb..6b2656a 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ResultData.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/ResultData.java
@@ -25,12 +25,22 @@ public interface ResultData {
   String RESULT_CONTENT = "content";
   String RESULT_FOOTER = "footer";
 
-
   String TYPE_COMPOSITE = "composite";
   String TYPE_ERROR = "error";
   String TYPE_INFO = "info";
   String TYPE_TABULAR = "table";
 
+  String SECTION_DATA_ACCESSOR = "__sections__";
+  String TABLE_DATA_ACCESSOR = "__tables__";
+  String BYTE_DATA_ACCESSOR = "__bytes__";
+  int FILE_TYPE_BINARY = 0;
+  int FILE_TYPE_TEXT = 1;
+  String FILE_NAME_FIELD = "fileName";
+  String FILE_TYPE_FIELD = "fileType";
+  String FILE_DATA_FIELD = "fileData";
+  String DATA_LENGTH_FIELD = "dataLength";
+  String FILE_MESSAGE = "fileMessage";
+
   String getHeader();
 
   String getFooter();
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/model/AbstractResultModel.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/model/AbstractResultModel.java
index aee54aa..709a481 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/model/AbstractResultModel.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/model/AbstractResultModel.java
@@ -50,4 +50,5 @@ public abstract class AbstractResultModel {
   public void setFooter(String footer) {
     this.footer = footer;
   }
+
 }
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/model/FileResultModel.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/model/FileResultModel.java
new file mode 100644
index 0000000..0712a14
--- /dev/null
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/model/FileResultModel.java
@@ -0,0 +1,162 @@
+/*
+ * 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.result.model;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.text.MessageFormat;
+
+import org.apache.geode.management.internal.cli.i18n.CliStrings;
+import org.apache.geode.management.internal.cli.result.ResultData;
+import org.apache.geode.management.internal.cli.shell.Gfsh;
+
+public class FileResultModel {
+
+  private String filename;
+  private int type;
+  private String message;
+  private byte[] data;
+  private int length;
+
+  public FileResultModel() {}
+
+  public FileResultModel(String fileName, byte[] data, int fileType, String 
message) {
+    this.filename = fileName;
+    this.data = data;
+    this.length = data.length;
+    this.type = fileType;
+    this.message = message;
+  }
+
+  public String getFilename() {
+    return filename;
+  }
+
+  public void setFilename(String filename) {
+    this.filename = filename;
+  }
+
+  public int getType() {
+    return type;
+  }
+
+  public void setType(int type) {
+    this.type = type;
+  }
+
+  public String getMessage() {
+    return message;
+  }
+
+  public void setMessage(String message) {
+    this.message = message;
+  }
+
+  public byte[] getData() {
+    return data;
+  }
+
+  public void setData(byte[] data) {
+    this.data = data;
+  }
+
+  public int getLength() {
+    return length;
+  }
+
+  public void setLength(int length) {
+    this.length = length;
+  }
+
+  public void writeFile(String directory) throws IOException {
+    String options = "(y/N)";
+
+    File fileToDumpData = new File(filename);
+    if (!fileToDumpData.isAbsolute()) {
+      if (directory == null || directory.isEmpty()) {
+        directory = System.getProperty("user.dir", ".");
+      }
+      fileToDumpData = new File(directory, filename);
+    }
+
+    File parentDirectory = fileToDumpData.getParentFile();
+    if (parentDirectory != null) {
+      parentDirectory.mkdirs();
+    }
+    Gfsh gfsh = Gfsh.getCurrentInstance();
+    if (fileToDumpData.exists()) {
+      String fileExistsMessage =
+          
CliStrings.format(CliStrings.ABSTRACTRESULTDATA__MSG__FILE_WITH_NAME_0_EXISTS_IN_1,
+              filename, fileToDumpData.getParent(), options);
+      if (gfsh != null && !gfsh.isQuietMode()) {
+        fileExistsMessage = fileExistsMessage + " Overwrite? " + options + " : 
";
+        String interaction = gfsh.interact(fileExistsMessage);
+        if (!"y".equalsIgnoreCase(interaction.trim())) {
+          // do not save file & continue
+          return;
+        }
+      } else {
+        throw new IOException(fileExistsMessage);
+      }
+    } else if (!parentDirectory.exists()) {
+      handleCondition(CliStrings.format(
+          
CliStrings.ABSTRACTRESULTDATA__MSG__PARENT_DIRECTORY_OF_0_DOES_NOT_EXIST,
+          fileToDumpData.getAbsolutePath()));
+      return;
+    } else if (!parentDirectory.canWrite()) {
+      handleCondition(CliStrings.format(
+          
CliStrings.ABSTRACTRESULTDATA__MSG__PARENT_DIRECTORY_OF_0_IS_NOT_WRITABLE,
+          fileToDumpData.getAbsolutePath()));
+      return;
+    } else if (!parentDirectory.isDirectory()) {
+      handleCondition(
+          
CliStrings.format(CliStrings.ABSTRACTRESULTDATA__MSG__PARENT_OF_0_IS_NOT_DIRECTORY,
+              fileToDumpData.getAbsolutePath()));
+      return;
+    }
+    if (type == ResultData.FILE_TYPE_TEXT) {
+      FileWriter fw = new FileWriter(fileToDumpData);
+      BufferedWriter bw = new BufferedWriter(fw);
+      bw.write(new String(data));
+      bw.flush();
+      fw.flush();
+      fw.close();
+    } else if (type == ResultData.FILE_TYPE_BINARY) {
+      FileOutputStream fos = new FileOutputStream(fileToDumpData);
+      fos.write(data);
+      fos.flush();
+      fos.close();
+    }
+    if (message != null && !message.isEmpty()) {
+      if (gfsh != null) {
+        Gfsh.println(MessageFormat.format(message, 
fileToDumpData.getAbsolutePath()));
+      }
+    }
+  }
+
+  private void handleCondition(String message) throws IOException {
+    Gfsh gfsh = Gfsh.getCurrentInstance();
+    // null check required in GfshVM too to avoid test issues
+    if (gfsh != null && !gfsh.isQuietMode()) {
+      gfsh.logWarning(message, null);
+    } else {
+      throw new IOException(message);
+    }
+  }
+}
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/model/ResultModel.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/model/ResultModel.java
index a132ac9..7097958 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/model/ResultModel.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/model/ResultModel.java
@@ -15,6 +15,9 @@
 
 package org.apache.geode.management.internal.cli.result.model;
 
+import static 
org.apache.geode.management.internal.cli.result.AbstractResultData.FILE_TYPE_BINARY;
+import static 
org.apache.geode.management.internal.cli.result.AbstractResultData.FILE_TYPE_TEXT;
+
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.util.LinkedHashMap;
@@ -49,12 +52,14 @@ import 
org.apache.geode.management.internal.cli.functions.CliFunctionResult;
  *
  */
 public class ResultModel {
+
   private String header;
   private String footer;
   private Map<String, AbstractResultModel> sections = new LinkedHashMap<>();
   private int sectionCount = 0;
   private Result.Status status = Result.Status.OK;
   private Object configObject;
+  private Map<String, FileResultModel> files = new LinkedHashMap<>();
 
   @JsonIgnore
   public Object getConfigObject() {
@@ -113,6 +118,24 @@ public class ResultModel {
     this.sections = content;
   }
 
+  public Map<String, FileResultModel> getFiles() {
+    return files;
+  }
+
+  public void setFiles(Map<String, FileResultModel> files) {
+    this.files = files;
+  }
+
+  public void addFile(String fileName, byte[] data, int fileType, String 
message,
+      boolean addTimestampToName) {
+    if (fileType != FILE_TYPE_BINARY && fileType != FILE_TYPE_TEXT) {
+      throw new IllegalArgumentException("Unsupported file type is 
specified.");
+    }
+
+    FileResultModel fileModel = new FileResultModel(fileName, data, fileType, 
message + fileName);
+    files.put(fileName, fileModel);
+  }
+
   public InfoResultModel addInfo() {
     return addInfo(Integer.toString(sectionCount++));
   }
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 7402c24..7b7dedc 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
@@ -38,6 +38,7 @@ import 
org.apache.geode.management.internal.cli.GfshParseResult;
 import org.apache.geode.management.internal.cli.LogWrapper;
 import org.apache.geode.management.internal.cli.i18n.CliStrings;
 import org.apache.geode.management.internal.cli.remote.CommandExecutor;
+import org.apache.geode.management.internal.cli.result.CommandResult;
 import org.apache.geode.management.internal.cli.result.FileResult;
 import org.apache.geode.management.internal.cli.result.ModelCommandResult;
 import org.apache.geode.management.internal.cli.result.ResultBuilder;
@@ -144,7 +145,7 @@ public class GfshExecutionStrategy implements 
ExecutionStrategy {
    * @throws IllegalStateException if gfsh doesn't have an active connection.
    */
   private Result executeOnRemote(GfshParseResult parseResult) {
-    Result commandResult = null;
+    CommandResult commandResult = null;
     Object response = null;
     Path tempFile = null;
 
@@ -250,7 +251,8 @@ public class GfshExecutionStrategy implements 
ExecutionStrategy {
 
     // 3. Post Remote Execution
     if (interceptor != null) {
-      Result postExecResult = interceptor.postExecution(parseResult, 
commandResult, tempFile);
+      CommandResult postExecResult =
+          interceptor.postExecution(parseResult, commandResult, tempFile);
       if (postExecResult != null) {
         if (Status.ERROR.equals(postExecResult.getStatus())) {
           if (logWrapper.infoEnabled()) {
diff --git 
a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ExecuteFunctionCommandTest.java
 
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ExecuteFunctionCommandTest.java
new file mode 100644
index 0000000..6ff375e
--- /dev/null
+++ 
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ExecuteFunctionCommandTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.mockito.Mockito.spy;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.UnitTest;
+import org.apache.geode.test.junit.rules.GfshParserRule;
+
+@Category(UnitTest.class)
+public class ExecuteFunctionCommandTest {
+
+  @ClassRule
+  public static GfshParserRule gfsh = new GfshParserRule();
+
+  private ExecuteFunctionCommand command;
+
+  @Before
+  public void before() throws Exception {
+    command = spy(ExecuteFunctionCommand.class);
+  }
+
+  @Test
+  public void conflictingExecutionLocations() {
+    gfsh.executeAndAssertThat(command, "execute function --id=foo --region=bar 
--member=baz")
+        .statusIsError().containsOutput("Provide Only one of 
region/member/groups");
+  }
+
+  @Test
+  public void filterWithoutRegion() {
+    gfsh.executeAndAssertThat(command, "execute function --id=foo 
--filter=bar").statusIsError()
+        .containsOutput("Filters for executing on member or group is not 
supported");
+  }
+}
diff --git 
a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommandTest.java
 
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommandTest.java
new file mode 100644
index 0000000..abc21c3
--- /dev/null
+++ 
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommandTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.mockito.Mockito.spy;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TemporaryFolder;
+
+import org.apache.geode.test.junit.categories.UnitTest;
+import org.apache.geode.test.junit.rules.GfshParserRule;
+
+@Category(UnitTest.class)
+public class ExportConfigCommandTest {
+
+  @ClassRule
+  public static GfshParserRule gfsh = new GfshParserRule();
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  private ExportConfigCommand command;
+
+  @Before
+  public void before() throws Exception {
+    command = spy(ExportConfigCommand.class);
+  }
+
+  @Test
+  public void incorrectDirectoryShowsError() throws Exception {
+    String wrongDir = temp.newFile().getAbsolutePath();
+    gfsh.executeAndAssertThat(command, "export config --dir=" + 
wrongDir).statusIsError()
+        .containsOutput(wrongDir + " is not a directory");
+  }
+}
diff --git 
a/geode-web/src/test/java/org/apache/geode/management/internal/cli/commands/CommandOverHttpTest.java
 
b/geode-web/src/test/java/org/apache/geode/management/internal/cli/commands/CommandOverHttpTest.java
index 9ed1321..c890476 100644
--- 
a/geode-web/src/test/java/org/apache/geode/management/internal/cli/commands/CommandOverHttpTest.java
+++ 
b/geode-web/src/test/java/org/apache/geode/management/internal/cli/commands/CommandOverHttpTest.java
@@ -84,7 +84,7 @@ public class CommandOverHttpTest {
   public void exportConfig() throws Exception {
     String dir = temporaryFolder.getRoot().getAbsolutePath();
     gfshRule.executeAndAssertThat("export config --dir=" + 
dir).statusIsSuccess()
-        .containsOutput("Downloading Cache XML file: " + dir + 
"/server-cache.xml")
-        .containsOutput("Downloading properties file: " + dir + 
"/server-gf.properties");
+        .containsOutput("Downloading Cache XML file: server-cache.xml")
+        .containsOutput("Downloading properties file: server-gf.properties");
   }
 }
diff --git 
a/geode-web/src/test/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommandDUnitTest.java
 
b/geode-web/src/test/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommandDUnitTest.java
index 4a44fcb..763af13 100644
--- 
a/geode-web/src/test/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommandDUnitTest.java
+++ 
b/geode-web/src/test/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommandDUnitTest.java
@@ -39,6 +39,7 @@ import org.apache.geode.test.junit.rules.GfshCommandRule;
 @Category(DistributedTest.class)
 @RunWith(JUnitParamsRunner.class)
 public class ExportConfigCommandDUnitTest {
+
   @Rule
   public ClusterStartupRule startupRule = new 
ClusterStartupRule().withLogFile();
 

-- 
To stop receiving notification emails like this one, please contact
jensde...@apache.org.

Reply via email to