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 4f330c3 Revert "GEODE-5011: Convert 'Data' commands to ResultModel (#1945)" 4f330c3 is described below commit 4f330c3e6e6a5fafff3d5d32852c320b9729277b Author: Jens Deppe <jde...@pivotal.io> AuthorDate: Fri May 11 06:29:49 2018 -0700 Revert "GEODE-5011: Convert 'Data' commands to ResultModel (#1945)" This reverts commit f1c6b560442f2f23aa9240b3550d9d664e094c7c. --- .../internal/cli/commands/DataCommandsUtils.java | 14 +- .../internal/cli/commands/GetCommand.java | 9 +- .../internal/cli/commands/LocateEntryCommand.java | 9 +- .../internal/cli/commands/PutCommand.java | 11 +- .../internal/cli/commands/QueryCommand.java | 9 +- .../internal/cli/commands/QueryInterceptor.java | 46 +-- .../internal/cli/commands/RemoveCommand.java | 15 +- .../internal/cli/domain/DataCommandResult.java | 418 +++++++++++++++------ .../cli/functions/DataCommandFunction.java | 242 +++++++++--- .../management/internal/cli/i18n/CliStrings.java | 2 +- .../management/internal/cli/result/ResultData.java | 1 - .../internal/cli/shell/GfshExecutionStrategy.java | 5 +- .../sanctioned-geode-core-serializables.txt | 2 +- .../cli/commands/GemfireDataCommandsDUnitTest.java | 164 +++++++- .../cli/commands/GetCommandIntegrationTest.java | 226 ++--------- .../cli/commands/LocateEntryDUnitTest.java | 37 +- .../cli/commands/PutCommandIntegrationTest.java | 55 +-- .../cli/commands/QueryCommandIntegrationTest.java | 67 +--- .../cli/commands/RemoveCommandDUnitTest.java | 8 +- .../DataCommandFunctionWithPDXJUnitTest.java | 95 ++--- .../java/org/apache/geode/pdx/SimpleClass.java | 12 - 21 files changed, 815 insertions(+), 632 deletions(-) diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DataCommandsUtils.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DataCommandsUtils.java index b4da63d..7a6bfbc 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DataCommandsUtils.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DataCommandsUtils.java @@ -21,21 +21,19 @@ import java.util.Set; import org.apache.geode.cache.execute.FunctionService; import org.apache.geode.cache.execute.ResultCollector; import org.apache.geode.distributed.DistributedMember; +import org.apache.geode.management.cli.Result; import org.apache.geode.management.internal.cli.domain.DataCommandRequest; import org.apache.geode.management.internal.cli.domain.DataCommandResult; import org.apache.geode.management.internal.cli.functions.DataCommandFunction; +import org.apache.geode.management.internal.cli.result.ResultBuilder; public class DataCommandsUtils { - static String makeBrokenJsonCompliant(String json) { - if (json == null) { - return null; - } - - if (json.startsWith("(") && json.endsWith(")")) { - return "{" + json.substring(1, json.length() - 1) + "}"; + static Result makePresentationResult(DataCommandResult dataResult) { + if (dataResult != null) { + return dataResult.toCommandResult(); } else { - return json; + return ResultBuilder.createGemFireErrorResult("Error executing data command"); } } diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/GetCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/GetCommand.java index 085655c..cf34715 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/GetCommand.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/GetCommand.java @@ -16,6 +16,7 @@ package org.apache.geode.management.internal.cli.commands; import static org.apache.geode.management.internal.cli.commands.DataCommandsUtils.callFunctionForRegion; +import static org.apache.geode.management.internal.cli.commands.DataCommandsUtils.makePresentationResult; import java.util.Set; @@ -30,18 +31,18 @@ import org.apache.geode.distributed.DistributedMember; import org.apache.geode.internal.cache.InternalCache; 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.domain.DataCommandRequest; import org.apache.geode.management.internal.cli.domain.DataCommandResult; import org.apache.geode.management.internal.cli.functions.DataCommandFunction; import org.apache.geode.management.internal.cli.i18n.CliStrings; -import org.apache.geode.management.internal.cli.result.model.ResultModel; import org.apache.geode.security.ResourcePermission.Operation; import org.apache.geode.security.ResourcePermission.Resource; public class GetCommand extends InternalGfshCommand { @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_DATA, CliStrings.TOPIC_GEODE_REGION}) @CliCommand(value = {CliStrings.GET}, help = CliStrings.GET__HELP) - public ResultModel get( + public Result get( @CliOption(key = {CliStrings.GET__KEY}, mandatory = true, help = CliStrings.GET__KEY__HELP) String key, @CliOption(key = {CliStrings.GET__REGIONNAME}, mandatory = true, @@ -59,8 +60,6 @@ public class GetCommand extends InternalGfshCommand { authorize(Resource.DATA, Operation.READ, regionPath, key); DataCommandResult dataResult; - key = DataCommandsUtils.makeBrokenJsonCompliant(key); - @SuppressWarnings("rawtypes") Region region = cache.getRegion(regionPath); DataCommandFunction getfn = new DataCommandFunction(); @@ -93,6 +92,6 @@ public class GetCommand extends InternalGfshCommand { dataResult.setValueClass(valueClass); } - return dataResult.toResultModel(); + return makePresentationResult(dataResult); } } diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/LocateEntryCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/LocateEntryCommand.java index d70914f..07dd4d1 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/LocateEntryCommand.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/LocateEntryCommand.java @@ -16,6 +16,7 @@ package org.apache.geode.management.internal.cli.commands; import static org.apache.geode.management.internal.cli.commands.DataCommandsUtils.callFunctionForRegion; +import static org.apache.geode.management.internal.cli.commands.DataCommandsUtils.makePresentationResult; import java.util.Set; @@ -26,18 +27,18 @@ import org.springframework.shell.core.annotation.CliOption; 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.domain.DataCommandRequest; import org.apache.geode.management.internal.cli.domain.DataCommandResult; import org.apache.geode.management.internal.cli.functions.DataCommandFunction; import org.apache.geode.management.internal.cli.i18n.CliStrings; -import org.apache.geode.management.internal.cli.result.model.ResultModel; import org.apache.geode.security.ResourcePermission.Operation; import org.apache.geode.security.ResourcePermission.Resource; public class LocateEntryCommand extends InternalGfshCommand { @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_DATA, CliStrings.TOPIC_GEODE_REGION}) @CliCommand(value = {CliStrings.LOCATE_ENTRY}, help = CliStrings.LOCATE_ENTRY__HELP) - public ResultModel locateEntry( + public Result locateEntry( @CliOption(key = {CliStrings.LOCATE_ENTRY__KEY}, mandatory = true, help = CliStrings.LOCATE_ENTRY__KEY__HELP) String key, @CliOption(key = {CliStrings.LOCATE_ENTRY__REGIONNAME}, mandatory = true, @@ -55,8 +56,6 @@ public class LocateEntryCommand extends InternalGfshCommand { DataCommandResult dataResult; - key = DataCommandsUtils.makeBrokenJsonCompliant(key); - DataCommandFunction locateEntry = new DataCommandFunction(); Set<DistributedMember> memberList = findMembersForRegion(regionPath); if (CollectionUtils.isNotEmpty(memberList)) { @@ -77,6 +76,6 @@ public class LocateEntryCommand extends InternalGfshCommand { dataResult.setValueClass(valueClass); } - return dataResult.toResultModel(); + return makePresentationResult(dataResult); } } diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/PutCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/PutCommand.java index 4b13840..feb0056 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/PutCommand.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/PutCommand.java @@ -16,6 +16,7 @@ package org.apache.geode.management.internal.cli.commands; import static org.apache.geode.management.internal.cli.commands.DataCommandsUtils.callFunctionForRegion; +import static org.apache.geode.management.internal.cli.commands.DataCommandsUtils.makePresentationResult; import java.util.Set; @@ -29,18 +30,18 @@ import org.apache.geode.distributed.DistributedMember; import org.apache.geode.internal.cache.InternalCache; 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.domain.DataCommandRequest; import org.apache.geode.management.internal.cli.domain.DataCommandResult; import org.apache.geode.management.internal.cli.functions.DataCommandFunction; import org.apache.geode.management.internal.cli.i18n.CliStrings; -import org.apache.geode.management.internal.cli.result.model.ResultModel; import org.apache.geode.security.ResourcePermission.Operation; import org.apache.geode.security.ResourcePermission.Resource; public class PutCommand extends InternalGfshCommand { @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_DATA, CliStrings.TOPIC_GEODE_REGION}) @CliCommand(value = {CliStrings.PUT}, help = CliStrings.PUT__HELP) - public ResultModel put( + public Result put( @CliOption(key = {CliStrings.PUT__KEY}, mandatory = true, help = CliStrings.PUT__KEY__HELP) String key, @CliOption(key = {CliStrings.PUT__VALUE}, mandatory = true, @@ -62,10 +63,6 @@ public class PutCommand extends InternalGfshCommand { authorize(Resource.DATA, Operation.WRITE, regionPath); DataCommandResult dataResult; - // For some reason we decided to delimit JSON strings with '(' and ')' - key = DataCommandsUtils.makeBrokenJsonCompliant(key); - value = DataCommandsUtils.makeBrokenJsonCompliant(value); - @SuppressWarnings("rawtypes") Region region = cache.getRegion(regionPath); DataCommandFunction putfn = new DataCommandFunction(); @@ -94,6 +91,6 @@ public class PutCommand extends InternalGfshCommand { if (valueClass != null) { dataResult.setValueClass(valueClass); } - return dataResult.toResultModel(); + return makePresentationResult(dataResult); } } diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommand.java index b8d8f49..9d92c45 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommand.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommand.java @@ -38,13 +38,15 @@ import org.apache.geode.internal.cache.InternalCache; import org.apache.geode.internal.logging.LogService; 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.CliUtil; import org.apache.geode.management.internal.cli.domain.DataCommandRequest; import org.apache.geode.management.internal.cli.domain.DataCommandResult; import org.apache.geode.management.internal.cli.functions.DataCommandFunction; 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.model.ResultModel; +import org.apache.geode.management.internal.cli.result.CompositeResultData; +import org.apache.geode.management.internal.cli.result.ResultBuilder; import org.apache.geode.security.ResourcePermission.Operation; import org.apache.geode.security.ResourcePermission.Resource; @@ -53,7 +55,7 @@ public class QueryCommand extends InternalGfshCommand { @CliCommand(value = "query", help = CliStrings.QUERY__HELP) @CliMetaData(interceptor = "org.apache.geode.management.internal.cli.commands.QueryInterceptor") - public ResultModel query( + public Result query( @CliOption(key = CliStrings.QUERY__QUERY, help = CliStrings.QUERY__QUERY__HELP, mandatory = true) final String query, @CliOption(key = "file", help = "File in which to output the results.", @@ -61,7 +63,8 @@ public class QueryCommand extends InternalGfshCommand { @CliOption(key = CliStrings.QUERY__INTERACTIVE, unspecifiedDefaultValue = "false", help = CliStrings.QUERY__INTERACTIVE__HELP) final boolean interactive) { DataCommandResult dataResult = select(query); - return dataResult.toSelectCommandResult(); + CompositeResultData rd = dataResult.toSelectCommandResult(); + return ResultBuilder.buildResult(rd); } private DataCommandResult select(String query) { 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 8b5940e..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 @@ -19,32 +19,34 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.nio.file.Path; -import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.SystemUtils; import org.springframework.shell.event.ParseResult; +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.result.CommandResult; -import org.apache.geode.management.internal.cli.result.ModelCommandResult; -import org.apache.geode.management.internal.cli.result.model.DataResultModel; -import org.apache.geode.management.internal.cli.result.model.ResultModel; +import org.apache.geode.management.internal.cli.result.CompositeResultData; +import org.apache.geode.management.internal.cli.result.InfoResultData; +import org.apache.geode.management.internal.cli.result.LegacyCommandResult; +import org.apache.geode.management.internal.cli.result.ResultBuilder; +import org.apache.geode.management.internal.cli.result.TabularResultData; public class QueryInterceptor extends AbstractCliAroundInterceptor { public static final String FILE_ALREADY_EXISTS_MESSAGE = "The specified output file already exists."; @Override - public ResultModel preExecution(GfshParseResult parseResult) { + public Result preExecution(GfshParseResult parseResult) { File outputFile = getOutputFile(parseResult); if (outputFile != null && outputFile.exists()) { - return ResultModel.createError(FILE_ALREADY_EXISTS_MESSAGE); + return ResultBuilder.createUserErrorResult(FILE_ALREADY_EXISTS_MESSAGE); } - return new ResultModel(); + return ResultBuilder.createInfoResult(""); } @Override @@ -56,36 +58,36 @@ public class QueryInterceptor extends AbstractCliAroundInterceptor { return result; } - ResultModel model = ((ModelCommandResult) result).getResultData(); - Map<String, String> sectionResultData = model.getDataSection("0").getContent(); + CompositeResultData resultData = (CompositeResultData) result.getResultData(); + CompositeResultData.SectionResultData sectionResultData = resultData.retrieveSectionByIndex(0); - String limit = sectionResultData.get("Limit"); - String resultString = sectionResultData.get("Result"); - String rows = sectionResultData.get("Rows"); + String limit = sectionResultData.retrieveString("Limit"); + String resultString = sectionResultData.retrieveString("Result"); + String rows = sectionResultData.retrieveString("Rows"); if ("false".equalsIgnoreCase(resultString)) { return result; } + TabularResultData tabularResultData = sectionResultData.retrieveTableByIndex(0); + CommandResult resultTable = new LegacyCommandResult(tabularResultData); try { - writeResultTableToFile(outputFile, result); + writeResultTableToFile(outputFile, resultTable); // return a result w/ message explaining limit } catch (IOException e) { throw new RuntimeException(e); } - ResultModel newModel = new ResultModel(); - DataResultModel data = newModel.addData(); - - data.addData("Result", resultString); + InfoResultData infoResultData = ResultBuilder.createInfoResultData(); + infoResultData.addLine("Result : " + resultString); if (StringUtils.isNotBlank(limit)) { - data.addData("Limit", limit); + infoResultData.addLine("Limit : " + limit); } - data.addData("Rows", rows); - - newModel.addInfo().addLine("Query results output to " + outputFile.getAbsolutePath()); + infoResultData.addLine("Rows : " + rows); + infoResultData.addLine(SystemUtils.LINE_SEPARATOR); + infoResultData.addLine("Query results output to " + outputFile.getAbsolutePath()); - return new ModelCommandResult(newModel); + return new LegacyCommandResult(infoResultData); } private File getOutputFile(ParseResult parseResult) { diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/RemoveCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/RemoveCommand.java index d3c640f..a6612d8 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/RemoveCommand.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/RemoveCommand.java @@ -16,6 +16,8 @@ package org.apache.geode.management.internal.cli.commands; import static org.apache.geode.management.internal.cli.commands.DataCommandsUtils.callFunctionForRegion; +import static org.apache.geode.management.internal.cli.commands.DataCommandsUtils.makePresentationResult; +import static org.apache.geode.management.internal.cli.result.ResultBuilder.createUserErrorResult; import java.util.Set; @@ -29,11 +31,11 @@ import org.apache.geode.distributed.DistributedMember; import org.apache.geode.internal.cache.InternalCache; 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.domain.DataCommandRequest; import org.apache.geode.management.internal.cli.domain.DataCommandResult; import org.apache.geode.management.internal.cli.functions.DataCommandFunction; import org.apache.geode.management.internal.cli.i18n.CliStrings; -import org.apache.geode.management.internal.cli.result.model.ResultModel; import org.apache.geode.security.ResourcePermission.Operation; import org.apache.geode.security.ResourcePermission.Resource; @@ -42,7 +44,7 @@ public class RemoveCommand extends InternalGfshCommand { @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_DATA, CliStrings.TOPIC_GEODE_REGION}) @CliCommand(value = {CliStrings.REMOVE}, help = CliStrings.REMOVE__HELP) - public ResultModel remove( + public Result remove( @CliOption(key = {CliStrings.REMOVE__KEY}, help = CliStrings.REMOVE__KEY__HELP, specifiedDefaultValue = "") String key, @CliOption(key = {CliStrings.REMOVE__REGION}, mandatory = true, @@ -55,7 +57,7 @@ public class RemoveCommand extends InternalGfshCommand { Cache cache = getCache(); if (!removeAllKeys && (key == null)) { - return new ResultModel().createError(CliStrings.REMOVE__MSG__KEY_EMPTY); + return createUserErrorResult(CliStrings.REMOVE__MSG__KEY_EMPTY); } if (removeAllKeys) { @@ -64,8 +66,6 @@ public class RemoveCommand extends InternalGfshCommand { authorize(Resource.DATA, Operation.WRITE, regionPath, key); } - key = DataCommandsUtils.makeBrokenJsonCompliant(key); - Region region = cache.getRegion(regionPath); DataCommandFunction removefn = new DataCommandFunction(); DataCommandResult dataResult; @@ -73,7 +73,7 @@ public class RemoveCommand extends InternalGfshCommand { Set<DistributedMember> memberList = findAnyMembersForRegion(regionPath); if (CollectionUtils.isEmpty(memberList)) { - return new ResultModel().createError(String.format(REGION_NOT_FOUND, regionPath)); + return createUserErrorResult(String.format(REGION_NOT_FOUND, regionPath)); } DataCommandRequest request = new DataCommandRequest(); @@ -89,7 +89,6 @@ public class RemoveCommand extends InternalGfshCommand { } dataResult.setKeyClass(keyClass); - - return dataResult.toResultModel(); + return makePresentationResult(dataResult); } } diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/DataCommandResult.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/DataCommandResult.java index b23d0ea..429c329 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/DataCommandResult.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/DataCommandResult.java @@ -14,29 +14,33 @@ */ package org.apache.geode.management.internal.cli.domain; +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; -import java.util.LinkedHashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; -import java.util.Map; +import java.util.Set; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.json.JSONObject; -import org.apache.geode.cache.query.Struct; -import org.apache.geode.cache.query.internal.StructImpl; -import org.apache.geode.cache.query.internal.Undefined; +import org.apache.geode.DataSerializer; +import org.apache.geode.internal.ClassPathLoader; import org.apache.geode.management.cli.Result; import org.apache.geode.management.internal.cli.GfshParser; import org.apache.geode.management.internal.cli.i18n.CliStrings; -import org.apache.geode.management.internal.cli.result.model.DataResultModel; -import org.apache.geode.management.internal.cli.result.model.ResultModel; -import org.apache.geode.management.internal.cli.result.model.TabularResultModel; -import org.apache.geode.pdx.PdxInstance; +import org.apache.geode.management.internal.cli.json.GfJsonException; +import org.apache.geode.management.internal.cli.json.GfJsonObject; +import org.apache.geode.management.internal.cli.result.CompositeResultData; +import org.apache.geode.management.internal.cli.result.CompositeResultData.SectionResultData; +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.util.JsonUtil; /** @@ -366,7 +370,12 @@ public class DataCommandResult implements Serializable { return locateEntryLocations; } - public ResultModel toResultModel() { + public void setLocateEntryLocations(List<KeyInfo> locateEntryLocations) { + this.locateEntryLocations = locateEntryLocations; + } + + public Result toCommandResult() { + if (StringUtils.isEmpty(keyClass)) { keyClass = "java.lang.String"; } @@ -375,48 +384,62 @@ public class DataCommandResult implements Serializable { valueClass = "java.lang.String"; } - ResultModel result = new ResultModel(); - DataResultModel data = result.addData(); - if (errorString != null) { - data.addData("Message", errorString); - data.addData(RESULT_FLAG, operationCompletedSuccessfully); - return result; + CompositeResultData data = ResultBuilder.createCompositeResultData(); + SectionResultData section = data.addSection(); + section.addData("Message", errorString); + section.addData(RESULT_FLAG, operationCompletedSuccessfully); + return ResultBuilder.buildResult(data); } - data.addData(RESULT_FLAG, operationCompletedSuccessfully); + CompositeResultData data = ResultBuilder.createCompositeResultData(); + SectionResultData section = data.addSection(); + TabularResultData table = section.addTable(); + + section.addData(RESULT_FLAG, operationCompletedSuccessfully); if (infoString != null) { - data.addData("Message", infoString); + section.addData("Message", infoString); } if (isGet()) { - toResultModel_isGet(data); + toCommandResult_isGet(section, table); } else if (isLocateEntry()) { - toResultModel_isLocate(result, data); + toCommandResult_isLocate(section, table); } else if (isPut()) { - toResultModel_isPut(data); + toCommandResult_isPut(section, table); } else if (isRemove()) { - toResultModel_isRemove(data); + toCommandResult_isRemove(section, table); } - - return result; + return ResultBuilder.buildResult(data); } + private void toCommandResult_isGet(SectionResultData section, TabularResultData table) { + section.addData("Key Class", getKeyClass()); + if (!isDeclaredPrimitive(keyClass)) { + addJSONStringToTable(table, inputKey); + } else { + section.addData("Key", inputKey); + } - private void toResultModel_isGet(DataResultModel data) { - data.addData("Key Class", getKeyClass()); - data.addData("Key", inputKey); - data.addData("Value Class", getValueClass()); - data.addData("Value", getResult != null ? getResult.toString() : "null"); + section.addData("Value Class", getValueClass()); + if (!isDeclaredPrimitive(valueClass)) { + addJSONStringToTable(table, getResult); + } else { + section.addData("Value", getResult); + } } - private void toResultModel_isLocate(ResultModel result, DataResultModel data) { + private void toCommandResult_isLocate(SectionResultData section, TabularResultData table) { - data.addData("Key Class", getKeyClass()); - data.addData("Key", inputKey); + section.addData("Key Class", getKeyClass()); + if (!isDeclaredPrimitive(keyClass)) { + addJSONStringToTable(table, inputKey); + } else { + section.addData("Key", inputKey); + } if (locateEntryLocations != null) { - TabularResultModel locationTable = result.addTable(); + TabularResultData locationTable = section.addTable(); int totalLocations = 0; @@ -466,23 +489,38 @@ public class DataCommandResult implements Serializable { } } } - data.addData("Locations Found", totalLocations); + section.addData("Locations Found", totalLocations); } else { - data.addData("Location Info ", "Could not find location information"); + section.addData("Location Info ", "Could not find location information"); } } - private void toResultModel_isPut(DataResultModel data) { - data.addData("Key Class", getKeyClass()); - data.addData("Key", inputKey); - data.addData("Value Class", getValueClass()); - data.addData("Old Value", putResult != null ? putResult.toString() : "null"); + private void toCommandResult_isPut(SectionResultData section, TabularResultData table) { + section.addData("Key Class", getKeyClass()); + + if (!isDeclaredPrimitive(keyClass)) { + addJSONStringToTable(table, inputKey); + } else { + section.addData("Key", inputKey); + } + + section.addData("Value Class", getValueClass()); + if (!isDeclaredPrimitive(valueClass)) { + addJSONStringToTable(table, putResult); + } else { + section.addData("Old Value", putResult); + } + } - private void toResultModel_isRemove(DataResultModel data) { + private void toCommandResult_isRemove(SectionResultData section, TabularResultData table) { if (inputKey != null) {// avoids printing key when remove ALL is called - data.addData("Key Class", getKeyClass()); - data.addData("Key", inputKey); + section.addData("Key Class", getKeyClass()); + if (!isDeclaredPrimitive(keyClass)) { + addJSONStringToTable(table, inputKey); + } else { + section.addData("Key", inputKey); + } } } @@ -492,62 +530,119 @@ public class DataCommandResult implements Serializable { * instead of Result as Command Step is required to add NEXT_STEP information to guide * executionStrategy to route it through final step. */ - public ResultModel toSelectCommandResult() { - ResultModel result = new ResultModel(); - if (!operationCompletedSuccessfully) { - result.setStatus(Result.Status.ERROR); - DataResultModel data = result.addData(); - data.addData(RESULT_FLAG, operationCompletedSuccessfully); - if (errorString != null) { - data.addData("Message", errorString); - } else if (infoString != null) { - data.addData("Message", infoString); - } - return result; + public CompositeResultData toSelectCommandResult() { + if (errorString != null) { + CompositeResultData data = ResultBuilder.createCompositeResultData(); + SectionResultData section = data.addSection(); + section.addData("Message", errorString); + section.addData(RESULT_FLAG, operationCompletedSuccessfully); + return data; } else { - DataResultModel data = result.addData(); - TabularResultModel table = result.addTable(); - data.addData(RESULT_FLAG, operationCompletedSuccessfully); + CompositeResultData data = ResultBuilder.createCompositeResultData(); + SectionResultData section = data.addSection(); + TabularResultData table = section.addTable(); + section.addData(RESULT_FLAG, operationCompletedSuccessfully); if (infoString != null) { - data.addData("Message", infoString); + section.addData("Message", infoString); } if (inputQuery != null) { if (this.limit > 0) { - data.addData("Limit", this.limit); + section.addData("Limit", this.limit); } if (this.selectResult != null) { - data.addData(NUM_ROWS, this.selectResult.size()); + section.addData(NUM_ROWS, this.selectResult.size()); if (this.queryTraceString != null) { - data.addData("Query Trace", this.queryTraceString); + section.addData("Query Trace", this.queryTraceString); } buildTable(table, 0, selectResult.size()); } } - return result; + return data; } } - private void buildTable(TabularResultModel table, int startCount, int endCount) { + private int buildTable(TabularResultData table, int startCount, int endCount) { + // Three steps: + // 1a. Convert each row object to a Json object. + // 1b. Build a list of keys that are used for each object + // 2. Pad MISSING_VALUE into Json objects for those data that are missing any particular key + // 3. Build the table from these Json objects. + + // 1. int lastRowExclusive = Math.min(selectResult.size(), endCount + 1); List<SelectResultRow> paginatedRows = selectResult.subList(startCount, lastRowExclusive); - // First find all the possible columns - not a Set because we want them ordered consistently - List<String> possibleColumns = new ArrayList<>(); + List<GfJsonObject> tableRows = new ArrayList<>(); + List<GfJsonObject> rowsWithRealJsonObjects = new ArrayList<>(); + Set<String> columns = new HashSet<>(); + for (SelectResultRow row : paginatedRows) { - for (String column : row.getColumnValues().keySet()) { - if (!possibleColumns.contains(column)) { - possibleColumns.add(column); + GfJsonObject object = new GfJsonObject(); + try { + if (row.value == null || MISSING_VALUE.equals(row.value)) { + object.put("Value", MISSING_VALUE); + } else if (row.type == ROW_TYPE_PRIMITIVE) { + object.put(RESULT_FLAG, row.value); + } else { + object = buildGfJsonFromRawObject(row.value); + rowsWithRealJsonObjects.add(object); + object.keys().forEachRemaining(columns::add); } + tableRows.add(object); + } catch (GfJsonException e) { + JSONObject errJson = + new JSONObject().put("Value", "Error getting bean properties " + e.getMessage()); + tableRows.add(new GfJsonObject(errJson, false)); } } - for (SelectResultRow row : paginatedRows) { - Map<String, String> columnValues = row.getColumnValues(); - for (String column : possibleColumns) { - table.accumulate(column, - columnValues.getOrDefault(column, DataCommandResult.MISSING_VALUE)); + // 2. + for (GfJsonObject tableRow : rowsWithRealJsonObjects) { + for (String key : columns) { + if (!tableRow.has(key)) { + try { + tableRow.put(key, MISSING_VALUE); + } catch (GfJsonException e) { + logger.warn("Ignored GfJsonException:", e); + } + } + } + } + + // 3. + for (GfJsonObject jsonObject : tableRows) { + addJSONObjectToTable(table, jsonObject); + } + + return paginatedRows.size(); + } + + + private boolean isDeclaredPrimitive(String keyClass2) { + try { + Class klass = ClassPathLoader.getLatest().forName(keyClass2); + return JsonUtil.isPrimitiveOrWrapper(klass); + } catch (ClassNotFoundException e) { + return false; + } + } + + + private Object getDomainValue(Object value) { + if (value instanceof String) { + String str = (String) value; + if (str.contains("{") && str.contains("}")) {// small filter to see if its json string + try { + JSONObject json = new JSONObject(str); + return json.get("type-class"); + } catch (Exception e) { + return str; + } + } else { + return str; } } + return value; } public Object getInputQuery() { @@ -562,7 +657,7 @@ public class DataCommandResult implements Serializable { this.limit = limit; } - public static class KeyInfo implements Serializable { + public static class KeyInfo implements /* Data */ Serializable { private String memberId; private String memberName; @@ -642,6 +737,26 @@ public class DataCommandResult implements Serializable { } return false; } + + // @Override + public void toData(DataOutput out) throws IOException { + DataSerializer.writeString(memberId, out); + DataSerializer.writeString(memberName, out); + DataSerializer.writeString(host, out); + DataSerializer.writePrimitiveInt(pid, out); + DataSerializer.writeArrayList(locations, out); + + + } + + // @Override + public void fromData(DataInput in) throws IOException, ClassNotFoundException { + memberId = DataSerializer.readString(in); + memberName = DataSerializer.readString(in); + host = DataSerializer.readString(in); + pid = DataSerializer.readPrimitiveInt(in); + locations = DataSerializer.readArrayList(in); + } } public static final int ROW_TYPE_STRUCT_RESULT = 100; @@ -651,65 +766,32 @@ public class DataCommandResult implements Serializable { public static class SelectResultRow implements Serializable { private static final long serialVersionUID = 1L; private int type; - private final Map<String, String> columnValues; + private Object value; public SelectResultRow(int type, Object value) { this.type = type; - this.columnValues = createColumnValues(value); + this.value = value; } - public Map<String, String> getColumnValues() { - return columnValues; + public int getType() { + return type; } - private Map<String, String> createColumnValues(Object value) { - Map<String, String> result = new LinkedHashMap<>(); - - if (value == null || MISSING_VALUE.equals(value)) { - result.put("Value", MISSING_VALUE); - } else if (type == ROW_TYPE_PRIMITIVE) { - result.put(RESULT_FLAG, value.toString()); - } else if (value instanceof Undefined) { - result.put("Value", "UNDEFINED"); - } else { - resolveObjectToColumns(result, value); - } - - return result; + public void setType(int type) { + this.type = type; } - private void resolveObjectToColumns(Map<String, String> columnData, Object value) { - if (value instanceof PdxInstance) { - resolvePdxToColumns(columnData, (PdxInstance) value); - } else if (value instanceof Struct) { - resolveStructToColumns(columnData, (StructImpl) value); - } else { - ObjectMapper mapper = new ObjectMapper(); - JsonNode node = mapper.valueToTree(value); - - node.fieldNames().forEachRemaining(field -> { - try { - columnData.put(field, mapper.writeValueAsString(node.get(field))); - } catch (JsonProcessingException e) { - columnData.put(field, e.getMessage()); - } - }); - } + public Object getValue() { + return value; } - private void resolvePdxToColumns(Map<String, String> columnData, PdxInstance pdx) { - for (String field : pdx.getFieldNames()) { - columnData.put(field, pdx.getField(field).toString()); - } + public void setValue(Object value) { + this.value = value; } - private void resolveStructToColumns(Map<String, String> columnData, StructImpl struct) { - for (String field : struct.getFieldNames()) { - columnData.put(field, struct.get(field).toString()); - } - } } + public void aggregate(DataCommandResult result) { /* Right now only called for LocateEntry */ if (!isLocateEntry()) { @@ -747,4 +829,96 @@ public class DataCommandResult implements Serializable { } } + + private void addJSONObjectToTable(TabularResultData table, GfJsonObject object) { + Iterator<String> keys; + + keys = object.keys(); + while (keys.hasNext()) { + String k = keys.next(); + // filter out meta-field type-class used to identify java class of json object + if (!"type-class".equals(k)) { + Object value = object.get(k); + + if (value != null) { + table.accumulate(k, getDomainValue(value)); + } + } + } + } + + private GfJsonObject buildGfJsonFromRawObject(Object object) throws GfJsonException { + GfJsonObject jsonObject; + if (String.class.equals(object.getClass())) { + jsonObject = new GfJsonObject(sanitizeJsonString((String) object)); + } else { + jsonObject = new GfJsonObject(object, true); + } + + return jsonObject; + } + + private String sanitizeJsonString(String s) { + // InputString in JSON Form but with round brackets + String newString = s.replaceAll("'", "\""); + if (newString.charAt(0) == '(') { + int len = newString.length(); + newString = "{" + newString.substring(1, len - 1) + "}"; + } + return newString; + } + + private void addJSONStringToTable(TabularResultData table, Object object) { + if (object == null || MISSING_VALUE.equals(object)) { + table.accumulate("Value", MISSING_VALUE); + } else { + try { + GfJsonObject jsonObject = buildGfJsonFromRawObject(object); + addJSONObjectToTable(table, jsonObject); + } catch (Exception e) { + table.accumulate("Value", "Error getting bean properties " + e.getMessage()); + } + } + } + + + // @Override + public void toData(DataOutput out) throws IOException { + DataSerializer.writeString(command, out); + out.writeUTF(command); + DataSerializer.writeObject(putResult, out); + DataSerializer.writeObject(getResult, out); + DataSerializer.writeObject(locateEntryResult, out); + DataSerializer.writeArrayList((ArrayList<?>) locateEntryLocations, out); + DataSerializer.writeBoolean(hasResultForAggregation, out); + DataSerializer.writeObject(removeResult, out); + DataSerializer.writeObject(inputKey, out); + DataSerializer.writeObject(inputValue, out); + DataSerializer.writeObject(error, out); + DataSerializer.writeString(errorString, out); + DataSerializer.writeString(infoString, out); + DataSerializer.writeString(keyClass, out); + DataSerializer.writeString(valueClass, out); + DataSerializer.writeBoolean(operationCompletedSuccessfully, out); + } + + // @Override + public void fromData(DataInput in) throws IOException, ClassNotFoundException { + command = DataSerializer.readString(in); + putResult = DataSerializer.readObject(in); + getResult = DataSerializer.readObject(in); + locateEntryLocations = DataSerializer.readArrayList(in); + locateEntryResult = DataSerializer.readObject(in); + hasResultForAggregation = DataSerializer.readBoolean(in); + removeResult = DataSerializer.readObject(in); + inputKey = DataSerializer.readObject(in); + inputValue = DataSerializer.readObject(in); + error = DataSerializer.readObject(in); + errorString = DataSerializer.readString(in); + infoString = DataSerializer.readString(in); + keyClass = DataSerializer.readString(in); + valueClass = DataSerializer.readString(in); + operationCompletedSuccessfully = DataSerializer.readBoolean(in); + } + } diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/DataCommandFunction.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/DataCommandFunction.java index a51d29e..989f79b 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/DataCommandFunction.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/DataCommandFunction.java @@ -14,19 +14,17 @@ */ package org.apache.geode.management.internal.cli.functions; -import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.Logger; +import org.json.JSONArray; import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.Region; @@ -44,6 +42,8 @@ import org.apache.geode.cache.query.internal.DefaultQuery; import org.apache.geode.cache.query.internal.IndexTrackingQueryObserver; import org.apache.geode.cache.query.internal.QueryObserver; import org.apache.geode.cache.query.internal.QueryObserverHolder; +import org.apache.geode.cache.query.internal.StructImpl; +import org.apache.geode.cache.query.internal.Undefined; import org.apache.geode.distributed.DistributedMember; import org.apache.geode.internal.ClassPathLoader; import org.apache.geode.internal.NanoTimer; @@ -56,8 +56,9 @@ import org.apache.geode.management.internal.cli.domain.DataCommandRequest; import org.apache.geode.management.internal.cli.domain.DataCommandResult; import org.apache.geode.management.internal.cli.domain.DataCommandResult.SelectResultRow; import org.apache.geode.management.internal.cli.i18n.CliStrings; +import org.apache.geode.management.internal.cli.json.GfJsonException; +import org.apache.geode.management.internal.cli.json.GfJsonObject; import org.apache.geode.management.internal.cli.util.JsonUtil; -import org.apache.geode.pdx.JSONFormatter; import org.apache.geode.pdx.PdxInstance; /** @@ -191,6 +192,7 @@ public class DataCommandFunction implements InternalFunction { @SuppressWarnings("rawtypes") private DataCommandResult select(InternalCache cache, Object principal, String queryString) { + AtomicInteger nestedObjectCount = new AtomicInteger(0); if (StringUtils.isEmpty(queryString)) { return DataCommandResult.createSelectInfoResult(null, null, -1, null, CliStrings.QUERY__MSG__QUERY_EMPTY, false); @@ -217,15 +219,15 @@ public class DataCommandFunction implements InternalFunction { queryObserver.reset2(); } if (results instanceof SelectResults) { - select_SelectResults((SelectResults) results, principal, list, cache); + select_SelectResults((SelectResults) results, principal, list, nestedObjectCount, cache); } else { select_NonSelectResults(results, list); } return DataCommandResult.createSelectResult(queryString, list, queryVerboseMsg, null, null, true); - } catch (FunctionDomainException | QueryInvocationTargetException | NameResolutionException - | TypeMismatchException e) { + } catch (FunctionDomainException | GfJsonException | QueryInvocationTargetException + | NameResolutionException | TypeMismatchException e) { logger.warn(e.getMessage(), e); return DataCommandResult.createSelectResult(queryString, null, queryVerboseMsg, e, e.getMessage(), false); @@ -240,30 +242,97 @@ public class DataCommandFunction implements InternalFunction { if (logger.isDebugEnabled()) { logger.debug("BeanResults : Bean Results class is {}", results.getClass()); } - list.add(createSelectResultRow(results)); + String str = toJson(results); + GfJsonObject jsonBean; + try { + jsonBean = new GfJsonObject(str); + } catch (GfJsonException e) { + logger.info("Exception occurred:", e); + jsonBean = new GfJsonObject(); + try { + jsonBean.put("msg", e.getMessage()); + } catch (GfJsonException e1) { + logger.warn("Ignored GfJsonException:", e1); + } + } + if (logger.isDebugEnabled()) { + logger.debug("BeanResults : Adding bean json string : {}", jsonBean); + } + list.add(new SelectResultRow(DataCommandResult.ROW_TYPE_BEAN, jsonBean.toString())); } private void select_SelectResults(SelectResults selectResults, Object principal, - List<SelectResultRow> list, InternalCache cache) { + List<SelectResultRow> list, AtomicInteger nestedObjectCount, InternalCache cache) + throws GfJsonException { for (Object object : selectResults) { // Post processing object = cache.getSecurityService().postProcess(principal, null, null, object, false); - list.add(createSelectResultRow(object)); + if (object instanceof Struct) { + StructImpl impl = (StructImpl) object; + GfJsonObject jsonStruct = getJSONForStruct(impl, nestedObjectCount); + if (logger.isDebugEnabled()) { + logger.debug("SelectResults : Adding select json string : {}", jsonStruct); + } + list.add( + new SelectResultRow(DataCommandResult.ROW_TYPE_STRUCT_RESULT, jsonStruct.toString())); + } else if (JsonUtil.isPrimitiveOrWrapper(object.getClass())) { + if (logger.isDebugEnabled()) { + logger.debug("SelectResults : Adding select primitive : {}", object); + } + list.add(new SelectResultRow(DataCommandResult.ROW_TYPE_PRIMITIVE, object)); + } else { + if (logger.isDebugEnabled()) { + logger.debug("SelectResults : Bean Results class is {}", object.getClass()); + } + String str = toJson(object); + GfJsonObject jsonBean; + try { + jsonBean = new GfJsonObject(str); + } catch (GfJsonException e) { + logger.error(e.getMessage(), e); + jsonBean = new GfJsonObject(); + try { + jsonBean.put("msg", e.getMessage()); + } catch (GfJsonException e1) { + logger.warn("Ignored GfJsonException:", e1); + } + } + if (logger.isDebugEnabled()) { + logger.debug("SelectResults : Adding bean json string : {}", jsonBean); + } + list.add(new SelectResultRow(DataCommandResult.ROW_TYPE_BEAN, jsonBean.toString())); + } } } - private SelectResultRow createSelectResultRow(Object object) { - int rowType; - if (object instanceof Struct) { - rowType = DataCommandResult.ROW_TYPE_STRUCT_RESULT; - } else if (JsonUtil.isPrimitiveOrWrapper(object.getClass())) { - rowType = DataCommandResult.ROW_TYPE_PRIMITIVE; + private String toJson(Object object) { + if (object instanceof Undefined) { + return "{\"Value\":\"UNDEFINED\"}"; + } else if (object instanceof PdxInstance) { + return pdxToJson((PdxInstance) object); } else { - rowType = DataCommandResult.ROW_TYPE_BEAN; + return JsonUtil.objectToJsonNestedChkCDep(object, NESTED_JSON_LENGTH); } + } - return new SelectResultRow(rowType, object); + private GfJsonObject getJSONForStruct(StructImpl impl, AtomicInteger ai) throws GfJsonException { + String fields[] = impl.getFieldNames(); + Object[] values = impl.getFieldValues(); + GfJsonObject jsonObject = new GfJsonObject(); + for (int i = 0; i < fields.length; i++) { + Object value = values[i]; + if (value != null) { + if (JsonUtil.isPrimitiveOrWrapper(value.getClass())) { + jsonObject.put(fields[i], value); + } else { + jsonObject.put(fields[i], toJson(value)); + } + } else { + jsonObject.put(fields[i], "null"); + } + } + return jsonObject; } @SuppressWarnings({"rawtypes"}) @@ -302,7 +371,7 @@ public class DataCommandFunction implements InternalFunction { if (logger.isDebugEnabled()) { logger.debug("Removed key {} successfully", key); } - Object array[] = getClassAndJson(value); + Object array[] = getJSONForNonPrimitiveObject(value); DataCommandResult result = DataCommandResult.createRemoveResult(key, array[1], null, null, true); if (array[0] != null) { @@ -379,7 +448,7 @@ public class DataCommandFunction implements InternalFunction { if (logger.isDebugEnabled()) { logger.debug("Get for key {} value {}", key, value); } - Object array[] = getClassAndJson(value); + Object array[] = getJSONForNonPrimitiveObject(value); if (value != null) { DataCommandResult result = DataCommandResult.createGetResult(key, array[1], null, null, true); @@ -394,7 +463,7 @@ public class DataCommandFunction implements InternalFunction { if (logger.isDebugEnabled()) { logger.debug("Key is not present in the region {}", regionName); } - return DataCommandResult.createGetInfoResult(key, getClassAndJson(null)[1], null, + return DataCommandResult.createGetInfoResult(key, null, null, CliStrings.GET__MSG__KEY_NOT_FOUND_REGION, false); } } @@ -476,8 +545,8 @@ public class DataCommandFunction implements InternalFunction { PartitionRegionHelper.getPrimaryMemberForKey(region, keyObject); int bucketId = pr.getKeyInfo(keyObject).getBucketId(); boolean isPrimary = member == primaryMember; - keyInfo.addLocation(new Object[] {region.getFullPath(), true, getClassAndJson(value)[1], - isPrimary, "" + bucketId}); + keyInfo.addLocation(new Object[] {region.getFullPath(), true, + getJSONForNonPrimitiveObject(value)[1], isPrimary, "" + bucketId}); } else { if (logger.isDebugEnabled()) { logger.debug("Key is not present in the region {}", regionPath); @@ -492,8 +561,8 @@ public class DataCommandFunction implements InternalFunction { logger.debug("Get for key {} value {} in region {}", key, value, region.getFullPath()); } if (value != null) { - keyInfo.addLocation( - new Object[] {region.getFullPath(), true, getClassAndJson(value)[1], false, null}); + keyInfo.addLocation(new Object[] {region.getFullPath(), true, + getJSONForNonPrimitiveObject(value)[1], false, null}); } else { keyInfo.addLocation(new Object[] {region.getFullPath(), false, null, false, null}); } @@ -562,7 +631,7 @@ public class DataCommandFunction implements InternalFunction { } else { returnValue = region.put(keyObject, valueObject); } - Object array[] = getClassAndJson(returnValue); + Object array[] = getJSONForNonPrimitiveObject(returnValue); DataCommandResult result = DataCommandResult.createPutResult(key, array[1], null, null, true); if (array[0] != null) { result.setValueClass((String) array[0]); @@ -583,45 +652,116 @@ public class DataCommandFunction implements InternalFunction { return string; } - Object resultObject; - try { - ObjectMapper mapper = new ObjectMapper(); - mapper.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES); - resultObject = mapper.readValue(string, klass); - } catch (IOException e) { - throw new IllegalArgumentException( - "Failed to convert input key to " + klassString + " Msg : " + e.getMessage()); + if (JsonUtil.isPrimitiveOrWrapper(klass)) { + try { + if (klass.equals(Byte.class)) { + return Byte.parseByte(string); + } else if (klass.equals(Short.class)) { + return Short.parseShort(string); + } else if (klass.equals(Integer.class)) { + return Integer.parseInt(string); + } else if (klass.equals(Long.class)) { + return Long.parseLong(string); + } else if (klass.equals(Double.class)) { + return Double.parseDouble(string); + } else if (klass.equals(Boolean.class)) { + return Boolean.parseBoolean(string); + } else if (klass.equals(Float.class)) { + return Float.parseFloat(string); + } + return null; + } catch (NumberFormatException e) { + throw new IllegalArgumentException( + "Failed to convert input key to " + klassString + " Msg : " + e.getMessage()); + } } - return resultObject; + return getObjectFromJson(string, klass); } - private Object[] getClassAndJson(Object obj) { + @SuppressWarnings({"rawtypes"}) + public static Object[] getJSONForNonPrimitiveObject(Object obj) { Object[] array = new Object[2]; - if (obj == null) { array[0] = null; - array[1] = null; + array[1] = "<NULL>"; return array; - } - - array[0] = obj.getClass().getCanonicalName(); - - if (obj instanceof PdxInstance) { - array[1] = JSONFormatter.toJSON((PdxInstance) obj); + } else { + array[0] = obj.getClass().getCanonicalName(); + Class klass = obj.getClass(); + if (JsonUtil.isPrimitiveOrWrapper(klass)) { + array[1] = obj; + } else if (obj instanceof PdxInstance) { + String str = pdxToJson((PdxInstance) obj); + array[1] = str; + } else { + GfJsonObject object = new GfJsonObject(obj, true); + Iterator keysIterator = object.keys(); + while (keysIterator.hasNext()) { + String key = (String) keysIterator.next(); + Object value = object.get(key); + if (GfJsonObject.isJSONKind(value)) { + GfJsonObject jsonVal = new GfJsonObject(value); + try { + if (jsonVal.has("type-class")) { + object.put(key, jsonVal.get("type-class")); + } else { + // Its Map Value + object.put(key, "a Map"); + } + } catch (GfJsonException e) { + throw new RuntimeException(e); + } + } else if (value instanceof JSONArray) { + // Its a collection either a set or list + try { + object.put(key, "a Collection"); + } catch (GfJsonException e) { + throw new RuntimeException(e); + } + } + } + String str = object.toString(); + array[1] = str; + } return array; } + } - ObjectMapper mapper = new ObjectMapper(); - try { - array[1] = mapper.writeValueAsString(obj); - } catch (JsonProcessingException e) { - array[1] = e.getMessage(); + private static String pdxToJson(PdxInstance obj) { + if (obj != null) { + try { + GfJsonObject json = new GfJsonObject(); + for (String field : obj.getFieldNames()) { + Object fieldValue = obj.getField(field); + if (fieldValue != null) { + if (JsonUtil.isPrimitiveOrWrapper(fieldValue.getClass())) { + json.put(field, fieldValue); + } else { + json.put(field, fieldValue.getClass()); + } + } + } + return json.toString(); + } catch (GfJsonException e) { + return null; + } } + return null; + } - return array; + public static <V> V getObjectFromJson(String json, Class<V> klass) { + String newString = json.replaceAll("'", "\""); + if (newString.charAt(0) == '(') { + int len = newString.length(); + StringBuilder sb = new StringBuilder(); + sb.append("{").append(newString.substring(1, len - 1)).append("}"); + newString = sb.toString(); + } + return JsonUtil.jsonToObject(newString, klass); } + /** * Returns a sorted list of all region full paths found in the specified cache. * 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 da553fa..5902980 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 @@ -1838,7 +1838,7 @@ public class CliStrings { public static final String QUERY__INTERACTIVE__HELP = "Deprecated: Since Geode 1.4. This option has no effect, but is kept around to maintain backwards compatibility with existing scripts."; public static final String QUERY__MSG__QUERY_EMPTY = "Query is either empty or Null"; - public static final String QUERY__MSG__INVALID_QUERY = "Query is invalid due to error : <{0}>"; + public static final String QUERY__MSG__INVALID_QUERY = "Query is invalid due for error : <{0}>"; public static final String QUERY__MSG__REGIONS_NOT_FOUND = "Cannot find regions <{0}> in any of the members"; public static final String QUERY__MSG__NOT_SUPPORTED_ON_MEMBERS = CliStrings.QUERY 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 94cf9ed..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 @@ -29,7 +29,6 @@ public interface ResultData { String TYPE_ERROR = "error"; String TYPE_INFO = "info"; String TYPE_TABULAR = "table"; - String TYPE_MODEL = "model"; String SECTION_DATA_ACCESSOR = "__sections__"; String TABLE_DATA_ACCESSOR = "__tables__"; 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 27f8f3b..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 @@ -181,7 +181,9 @@ public class GfshExecutionStrategy implements ExecutionStrategy { if (((ResultModel) preExecResult).getStatus() != Status.OK) { return new ModelCommandResult((ResultModel) preExecResult); } - } else { // Must be Result + } + + if (preExecResult instanceof Result) { if (Status.ERROR.equals(((Result) preExecResult).getStatus())) { return (Result) preExecResult; } @@ -259,6 +261,7 @@ public class GfshExecutionStrategy implements ExecutionStrategy { } else if (logWrapper.fineEnabled()) { logWrapper.fine("Post execution Result :: " + postExecResult); } + commandResult = postExecResult; } } diff --git a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt index 7a2e627..dde4c25 100644 --- a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt +++ b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt @@ -492,7 +492,7 @@ org/apache/geode/management/internal/cli/domain/ClassName,true,1,className:java/ org/apache/geode/management/internal/cli/domain/DataCommandRequest,false,command:java/lang/String,key:java/lang/String,keyClass:java/lang/String,loadOnCacheMiss:boolean,principal:java/lang/Object,putIfAbsent:boolean,query:java/lang/String,recursive:boolean,regionName:java/lang/String,removeAllKeys:java/lang/String,value:java/lang/String,valueClass:java/lang/String org/apache/geode/management/internal/cli/domain/DataCommandResult,true,1,command:java/lang/String,error:java/lang/Throwable,errorString:java/lang/String,getResult:java/lang/Object,hasResultForAggregation:boolean,infoString:java/lang/String,inputKey:java/lang/Object,inputQuery:java/lang/Object,inputValue:java/lang/Object,keyClass:java/lang/String,limit:int,locateEntryLocations:java/util/List,locateEntryResult:org/apache/geode/management/internal/cli/domain/DataCommandResult$KeyInfo,operat [...] org/apache/geode/management/internal/cli/domain/DataCommandResult$KeyInfo,false,host:java/lang/String,locations:java/util/ArrayList,memberId:java/lang/String,memberName:java/lang/String,pid:int -org/apache/geode/management/internal/cli/domain/DataCommandResult$SelectResultRow,true,1,columnValues:java/util/Map,type:int +org/apache/geode/management/internal/cli/domain/DataCommandResult$SelectResultRow,true,1,type:int,value:java/lang/Object org/apache/geode/management/internal/cli/domain/DiskStoreDetails,false,allowForceCompaction:java/lang/Boolean,asyncEventQueueDetailsSet:java/util/Set,autoCompact:java/lang/Boolean,cacheServerDetailsSet:java/util/Set,compactionThreshold:java/lang/Integer,diskDirDetailsSet:java/util/Set,diskUsageCriticalPercentage:java/lang/Float,diskUsageWarningPercentage:java/lang/Float,gatewayDetailsSet:java/util/Set,id:java/util/UUID,maxOplogSize:java/lang/Long,memberId:java/lang/String,memberName:java [...] org/apache/geode/management/internal/cli/domain/DiskStoreDetails$AsyncEventQueueDetails,false,id:java/lang/String org/apache/geode/management/internal/cli/domain/DiskStoreDetails$CacheServerDetails,false,bindAddress:java/lang/String,hostName:java/lang/String,port:int diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/GemfireDataCommandsDUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/GemfireDataCommandsDUnitTest.java index 7651ea5..8e6f4c2 100644 --- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/GemfireDataCommandsDUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/GemfireDataCommandsDUnitTest.java @@ -17,19 +17,19 @@ package org.apache.geode.management.internal.cli.commands; import static org.apache.geode.distributed.ConfigurationProperties.NAME; import static org.apache.geode.test.dunit.Assert.assertEquals; +import static org.apache.geode.test.dunit.Assert.assertNotEquals; import static org.apache.geode.test.dunit.Assert.assertNotNull; +import static org.apache.geode.test.dunit.Assert.assertNotSame; import static org.apache.geode.test.dunit.Assert.assertTrue; import static org.apache.geode.test.dunit.Assert.fail; import static org.apache.geode.test.dunit.IgnoredException.addIgnoredException; import static org.apache.geode.test.dunit.LogWriterUtils.getLogWriter; import static org.apache.geode.test.dunit.Wait.waitForCriterion; -import static org.assertj.core.api.Java6Assertions.assertThat; import java.io.Serializable; import java.util.Collections; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Properties; import java.util.Random; import java.util.Set; @@ -40,6 +40,8 @@ import org.junit.experimental.categories.Category; import org.apache.geode.cache.Cache; import org.apache.geode.cache.CacheFactory; +import org.apache.geode.cache.CacheListener; +import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.EntryEvent; import org.apache.geode.cache.PartitionAttributes; import org.apache.geode.cache.PartitionAttributesFactory; @@ -66,10 +68,13 @@ import org.apache.geode.management.internal.cli.HeadlessGfsh; import org.apache.geode.management.internal.cli.domain.DataCommandRequest; import org.apache.geode.management.internal.cli.dto.Value1; import org.apache.geode.management.internal.cli.dto.Value2; +import org.apache.geode.management.internal.cli.json.GfJsonArray; +import org.apache.geode.management.internal.cli.json.GfJsonException; import org.apache.geode.management.internal.cli.result.CommandResult; +import org.apache.geode.management.internal.cli.result.CompositeResultData; +import org.apache.geode.management.internal.cli.result.CompositeResultData.SectionResultData; import org.apache.geode.management.internal.cli.result.ResultData; -import org.apache.geode.management.internal.cli.result.model.DataResultModel; -import org.apache.geode.management.internal.cli.result.model.ResultModel; +import org.apache.geode.management.internal.cli.result.TabularResultData; import org.apache.geode.test.dunit.Host; import org.apache.geode.test.dunit.IgnoredException; import org.apache.geode.test.dunit.SerializableCallable; @@ -710,7 +715,7 @@ public class GemfireDataCommandsDUnitTest extends CliCommandTestBase { vm1.invoke(clearTask); - // Do put from shell check from gemfire do remove from shell get from shell expect false + // Do put from shell check from gemfire do remove from shell get from shell exepct false cmdResult = executeCommand(putCommand); printCommandOutput(cmdResult); validateResult(cmdResult, true); @@ -750,32 +755,151 @@ public class GemfireDataCommandsDUnitTest extends CliCommandTestBase { } - private void validateResult(CommandResult cmdResult, Boolean expected) { - if (ResultData.TYPE_MODEL.equals(cmdResult.getType())) { - ResultModel rd = (ResultModel) cmdResult.getResultData(); - DataResultModel result = rd.getDataSection("0"); - assertThat(result.getContent().get("Result")).isEqualTo(expected.toString()); + private void validateResult(CommandResult cmdResult, boolean expected) { + if (ResultData.TYPE_COMPOSITE.equals(cmdResult.getType())) { + CompositeResultData rd = (CompositeResultData) cmdResult.getResultData(); + SectionResultData section = rd.retrieveSectionByIndex(0); + boolean result = (Boolean) section.retrieveObject("Result"); + assertEquals(expected, result); + } else + fail("Expected CompositeResult Returned Result Type " + cmdResult.getType()); + } + + private void validateLocationsResult(CommandResult cmdResult, int expected) { + if (ResultData.TYPE_COMPOSITE.equals(cmdResult.getType())) { + CompositeResultData rd = (CompositeResultData) cmdResult.getResultData(); + SectionResultData section = rd.retrieveSectionByIndex(0); + int result = (Integer) section.retrieveObject("Locations Found"); + assertEquals(expected, result); } else fail("Expected CompositeResult Returned Result Type " + cmdResult.getType()); } - private void validateSelectResult(CommandResult cmdResult, Boolean expectedFlag, - Integer expectedRows, String[] cols) { - if (ResultData.TYPE_MODEL.equals(cmdResult.getType())) { - ResultModel rd = (ResultModel) cmdResult.getResultData(); - Map<String, String> data = rd.getDataSection("0").getContent(); - assertThat(data.get("Result")).isEqualTo(expectedFlag.toString()); + private void validateJSONGetResult(CommandResult cmdResult, String[] expectedCols) { + CompositeResultData rd = (CompositeResultData) cmdResult.getResultData(); + SectionResultData section = rd.retrieveSectionByIndex(0); + TabularResultData table = section.retrieveTableByIndex(0); + GfJsonArray array = table.getHeaders(); + assertEquals(expectedCols.length, array.size()); + try { + for (String col : expectedCols) { + boolean found = false; + getLogWriter().info("Validating column " + col); + for (int i = 0; i < array.size(); i++) { + String header = (String) array.get(i); + if (col.equals(header)) + found = true; + } + assertEquals(true, found); + } + } catch (GfJsonException e) { + fail("Error accessing table data", e); + } + } + + private void validateJSONGetResultValues(CommandResult cmdResult, String[] expectedCols) { + CompositeResultData rd = (CompositeResultData) cmdResult.getResultData(); + SectionResultData section = rd.retrieveSectionByIndex(0); + TabularResultData table = section.retrieveTableByIndex(0); + GfJsonArray array = table.getHeaders(); + assertEquals(expectedCols.length, array.size()); + try { + for (String col : expectedCols) { + boolean found = false; + getLogWriter().info("Validating column " + col); + for (int i = 0; i < array.size(); i++) { + String header = (String) array.get(i); + if (col.equals(header)) + found = true; + } + assertEquals(true, found); + + List<String> values = table.retrieveAllValues(col); + for (String value : values) { + assertNotSame("null", value); + } + + } + } catch (GfJsonException e) { + fail("Error accessing table data", e); + } + } + + private void validateSelectResult(CommandResult cmdResult, boolean expectedFlag, int expectedRows, + String[] cols) { + if (ResultData.TYPE_COMPOSITE.equals(cmdResult.getType())) { + CompositeResultData rd = (CompositeResultData) cmdResult.getResultData(); + SectionResultData section = rd.retrieveSectionByIndex(0); + boolean result = (Boolean) section.retrieveObject("Result"); + assertEquals(expectedFlag, result); if (expectedFlag && expectedRows != -1) { - assertThat(data.get("Rows")).isEqualTo(expectedRows.toString()); - if (expectedRows > 0 && cols != null) { - Map<String, List<String>> table = rd.getTableSection("1").getContent(); - assertThat(table.keySet()).contains(cols); + int rowsReturned = (Integer) section.retrieveObject("Rows"); + assertEquals(expectedRows, rowsReturned); + if (rowsReturned > 0 && cols != null) { + try { + TabularResultData table = section.retrieveTableByIndex(0); + GfJsonArray array = table.getHeaders(); + assertEquals(cols.length, array.size()); + for (String col : cols) { + boolean found = false; + getLogWriter().info("Validating column " + col); + for (int i = 0; i < array.size(); i++) { + String header = (String) array.get(i); + if (col.equals(header)) + found = true; + } + assertEquals(true, found); + } + } catch (GfJsonException e) { + fail("Error accessing table data", e); + } } } } else fail("Expected CompositeResult Returned Result Type " + cmdResult.getType()); } + private Region<?, ?> createParReg(String regionName, Cache cache) { + RegionFactory regionFactory = cache.createRegionFactory(); + regionFactory.setDataPolicy(DataPolicy.PARTITION); + return regionFactory.create(regionName); + } + + private Region<?, ?> createReplicatedRegion(String regionName, Cache cache) { + RegionFactory regionFactory = cache.createRegionFactory(); + regionFactory.setDataPolicy(DataPolicy.REPLICATE); + return regionFactory.create(regionName); + } + + private SerializableRunnable addCacheListenerInvocations(final String regionName) { + return new SerializableRunnable() { + public void run() { + Region region = getCache().getRegion(regionName); + region.getAttributesMutator().addCacheListener(new CountingCacheListener()); + } + }; + } + + private SerializableRunnable verifyCacheListenerInvocations(final String regionName, + boolean callbacksShouldHaveBeenInvoked) { + return new SerializableRunnable() { + public void run() { + Region region = getCache().getRegion(regionName); + CacheListener<?, ?>[] listeners = region.getAttributes().getCacheListeners(); + for (CacheListener<?, ?> listener : listeners) { + if (listener instanceof CountingCacheListener) { + CountingCacheListener ccl = (CountingCacheListener) listener; + if (callbacksShouldHaveBeenInvoked) { + assertNotEquals(0, ccl.getEvents()); + } else { + assertEquals(0, ccl.getEvents()); + } + } + } + } + }; + } + void setupWith2Regions() { final VM vm1 = Host.getHost(0).getVM(1); final VM vm2 = Host.getHost(0).getVM(2); diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/GetCommandIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/GetCommandIntegrationTest.java index c21622d..dddb598 100644 --- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/GetCommandIntegrationTest.java +++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/GetCommandIntegrationTest.java @@ -20,7 +20,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import java.io.Serializable; -import java.util.Formatter; import java.util.HashMap; import java.util.Map; @@ -30,19 +29,13 @@ import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.rules.RuleChain; +import org.apache.geode.cache.Cache; import org.apache.geode.cache.CacheLoader; import org.apache.geode.cache.CacheLoaderException; import org.apache.geode.cache.LoaderHelper; import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionFactory; import org.apache.geode.cache.RegionShortcut; -import org.apache.geode.internal.cache.InternalCache; -import org.apache.geode.management.cli.Result; -import org.apache.geode.management.internal.cli.result.CommandResult; -import org.apache.geode.pdx.PdxInstance; -import org.apache.geode.pdx.PdxInstanceFactory; -import org.apache.geode.pdx.internal.PdxInstanceFactoryImpl; -import org.apache.geode.pdx.internal.PdxInstanceImpl; import org.apache.geode.test.junit.categories.GfshTest; import org.apache.geode.test.junit.categories.IntegrationTest; import org.apache.geode.test.junit.rules.GfshCommandRule; @@ -52,16 +45,6 @@ import org.apache.geode.test.junit.rules.ServerStarterRule; @Category({IntegrationTest.class, GfshTest.class}) public class GetCommandIntegrationTest { - private static final Map<String, User> userDataStore = new HashMap<String, User>(5); - - static { - userDataStore.put("jackhandy", new User("jackhandy")); - userDataStore.put("janedoe", new User("janedoe")); - userDataStore.put("jondoe", new User("jondoe")); - userDataStore.put("piedoe", new User("piedoe")); - userDataStore.put("supertool", new User("supertool")); - } - private static ServerStarterRule server = new ServerStarterRule().withJMXManager().withAutoStart(); @@ -73,34 +56,23 @@ public class GetCommandIntegrationTest { @BeforeClass public static void beforeClass() throws Exception { - InternalCache cache = server.getCache(); + Cache cache = server.getCache(); + RegionFactory<String, User> regionFactory = cache.createRegionFactory(RegionShortcut.REPLICATE); + + regionFactory.setCacheLoader(new UserDataStoreCacheLoader()); + regionFactory.setInitialCapacity(51); + regionFactory.setKeyConstraint(String.class); + regionFactory.setLoadFactor(0.75f); + regionFactory.setStatisticsEnabled(false); + regionFactory.setValueConstraint(User.class); - // Region containing POJOs - RegionFactory<String, User> userRegionFactory = - cache.createRegionFactory(RegionShortcut.REPLICATE); - userRegionFactory.setCacheLoader(new UserDataStoreCacheLoader()); - Region<String, User> users = userRegionFactory.create("Users"); + Region<String, User> users = regionFactory.create("Users"); + assertThat(users.getName()).isEqualTo("Users"); + assertThat(users.getFullPath()).isEqualTo("/Users"); users.put("jonbloom", new User("jonbloom")); assertFalse(users.isEmpty()); assertEquals(1, users.size()); - - // Region containing PdxInstances - RegionFactory<String, PdxInstance> userPdxRegionFactory = - cache.createRegionFactory(RegionShortcut.REPLICATE); - userPdxRegionFactory.setCacheLoader(new UserPdxDataStoreCacheLoader(cache)); - Region<String, PdxInstance> pdxRegion = userPdxRegionFactory.create("UsersPdx"); - pdxRegion.put("jonbloom", makePdxInstance(new User("jonbloom"), cache)); - - // Region containing primitives - RegionFactory<String, String> userStringRegionFactory = - cache.createRegionFactory(RegionShortcut.REPLICATE); - userStringRegionFactory.setCacheLoader(new UserStringDataStoreCacheLoader()); - Region<String, String> usersString = userStringRegionFactory.create("UsersString"); - - usersString.put("jonbloom", "6a6f6e626c6f6f6d"); - assertFalse(usersString.isEmpty()); - assertEquals(1, usersString.size()); } @Test @@ -114,100 +86,20 @@ public class GetCommandIntegrationTest { } @Test - public void getOnCacheMissForRegularRegion() throws Exception { - CommandResult result = gfsh.executeCommand("get --region=Users --key=jonbloom"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - Map<String, String> data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("true"); - - result = gfsh.executeCommand("get --region=Users --key=jondoe --load-on-cache-miss=false"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("false"); - assertThat(data.get("Message")).isEqualTo("Key is not present in the region"); - - result = gfsh.executeCommand("get --region=Users --key=jondoe"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("true"); - assertThat(data.get("Value Class")).isEqualTo(User.class.getCanonicalName()); - - // get something that does not exist - result = gfsh.executeCommand("get --region=Users --key=missingUser --load-on-cache-miss"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("false"); - assertThat(data.get("Value")).isEqualTo("null"); - } - - @Test - public void getOnCacheMissForPdxRegion() { - CommandResult result = gfsh.executeCommand("get --region=UsersPdx --key=jonbloom"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - Map<String, String> data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("true"); - - result = gfsh.executeCommand("get --region=UsersPdx --key=jondoe --load-on-cache-miss=false"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("false"); - assertThat(data.get("Message")).isEqualTo("Key is not present in the region"); - - result = gfsh.executeCommand("get --region=UsersPdx --key=jondoe"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("true"); - assertThat(data.get("Value Class")).isEqualTo(PdxInstanceImpl.class.getCanonicalName()); - - // get something that does not exist - result = gfsh.executeCommand("get --region=UsersPdx --key=missingUser --load-on-cache-miss"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("false"); - assertThat(data.get("Value")).isEqualTo("null"); - } - - @Test - public void getOnCacheMissForStringRegion() throws Exception { - CommandResult result = gfsh.executeCommand("get --region=UsersString --key=jonbloom"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - Map<String, String> data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("true"); - assertThat(data.get("Value")).isEqualTo("\"6a6f6e626c6f6f6d\""); - - result = - gfsh.executeCommand("get --region=UsersString --key=jondoe --load-on-cache-miss=false"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("false"); - assertThat(data.get("Message")).isEqualTo("Key is not present in the region"); - assertThat(data.get("Value")).isEqualTo("null"); - - result = gfsh.executeCommand("get --region=UsersString --key=jondoe"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); + public void getOnCacheMiss() throws Exception { + gfsh.executeAndAssertThat("get --region=Users --key=jonbloom").statusIsSuccess(); + assertThat(gfsh.getGfshOutput()).contains("Result : true"); + gfsh.executeAndAssertThat("get --region=Users --key=jondoe --load-on-cache-miss=false") + .statusIsSuccess(); + assertThat(gfsh.getGfshOutput()).contains("Result : false"); - data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("true"); - assertThat(data.get("Value Class")).isEqualTo(String.class.getName()); - assertThat(data.get("Value")).isEqualTo("\"6a6f6e646f65\""); + gfsh.executeAndAssertThat("get --region=Users --key=jondoe").statusIsSuccess(); + assertThat(gfsh.getGfshOutput()).contains("Result : true"); // get something that does not exist - result = gfsh.executeCommand("get --region=UsersString --key=missingUser --load-on-cache-miss"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("false"); - assertThat(data.get("Value")).isEqualTo("null"); + gfsh.executeAndAssertThat("get --region=Users --key=missingUser --load-on-cache-miss") + .statusIsSuccess(); + assertThat(gfsh.getGfshOutput()).contains("Result : false"); } private static class User implements Serializable { @@ -222,17 +114,6 @@ public class GetCommandIntegrationTest { return username; } - public String getHashcode() { - StringBuilder sb = new StringBuilder(username.getBytes().length * 2); - - Formatter formatter = new Formatter(sb); - for (byte b : username.getBytes()) { - formatter.format("%02x", b); - } - - return sb.toString(); - } - @Override public boolean equals(final Object obj) { if (obj == this) { @@ -250,60 +131,29 @@ public class GetCommandIntegrationTest { } private static class UserDataStoreCacheLoader implements CacheLoader<String, User>, Serializable { - @Override - public User load(final LoaderHelper<String, User> helper) throws CacheLoaderException { - return userDataStore.get(helper.getKey()); - } - - @Override - public void close() {} - } - private static class UserPdxDataStoreCacheLoader - implements CacheLoader<String, PdxInstance>, Serializable { + private static final Map<String, User> userDataStore = new HashMap<String, User>(5); - private InternalCache cache; - - UserPdxDataStoreCacheLoader(InternalCache cache) { - this.cache = cache; + static { + userDataStore.put("jackhandy", createUser("jackhandy")); + userDataStore.put("janedoe", createUser("janedoe")); + userDataStore.put("jondoe", createUser("jondoe")); + userDataStore.put("piedoe", createUser("piedoe")); + userDataStore.put("supertool", createUser("supertool")); } - @Override - public PdxInstance load(final LoaderHelper<String, PdxInstance> helper) - throws CacheLoaderException { - User user = userDataStore.get(helper.getKey()); - if (user == null) { - return null; - } - - return makePdxInstance(user, cache); + protected static User createUser(final String username) { + return new User(username); } @Override - public void close() {} - } - - private static class UserStringDataStoreCacheLoader - implements CacheLoader<String, String>, Serializable { - - @Override - public String load(final LoaderHelper<String, String> helper) throws CacheLoaderException { - User user = userDataStore.get(helper.getKey()); - if (user == null) { - return null; - } - - return user.getHashcode(); + public User load(final LoaderHelper<String, User> helper) throws CacheLoaderException { + return userDataStore.get(helper.getKey()); } @Override - public void close() {} - } - - private static PdxInstance makePdxInstance(User user, InternalCache cache) { - PdxInstanceFactory pf = PdxInstanceFactoryImpl.newCreator("User", false, cache); - pf.writeString("username", user.getUsername()); - pf.writeString("hashcode", user.getHashcode()); - return pf.create(); + public void close() { + userDataStore.clear(); + } } } diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/LocateEntryDUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/LocateEntryDUnitTest.java index 4ffcb05..875421e 100644 --- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/LocateEntryDUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/LocateEntryDUnitTest.java @@ -15,9 +15,6 @@ package org.apache.geode.management.internal.cli.commands; -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.Map; import java.util.Properties; import org.junit.BeforeClass; @@ -26,10 +23,8 @@ import org.junit.Test; import org.junit.experimental.categories.Category; import org.apache.geode.distributed.ConfigurationProperties; -import org.apache.geode.management.cli.Result; import org.apache.geode.management.internal.cli.dto.Key; import org.apache.geode.management.internal.cli.dto.Value; -import org.apache.geode.management.internal.cli.result.CommandResult; import org.apache.geode.test.dunit.rules.ClusterStartupRule; import org.apache.geode.test.dunit.rules.MemberVM; import org.apache.geode.test.junit.categories.DistributedTest; @@ -80,30 +75,20 @@ public class LocateEntryDUnitTest { @Test public void locateEntryForPartitionedRegion() throws Exception { - CommandResult result = gfsh.executeCommand("locate entry --region=regionA --key=key"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - Map<String, String> data = result.getMapFromSection("0"); - assertThat(data.get("Locations Found")).isEqualTo("1"); + gfsh.executeAndAssertThat("locate entry --region=regionA --key=key").statusIsSuccess() + .containsKeyValuePair("Locations Found", "1"); } @Test public void locateEntryForReplicateRegion() throws Exception { - CommandResult result = gfsh.executeCommand("locate entry --region=regionB --key=key"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - Map<String, String> data = result.getMapFromSection("0"); - assertThat(data.get("Locations Found")).isEqualTo("2"); + gfsh.executeAndAssertThat("locate entry --region=regionB --key=key").statusIsSuccess() + .containsKeyValuePair("Locations Found", "2"); } @Test public void recursiveLocate() throws Exception { - CommandResult result = - gfsh.executeCommand("locate entry --region=regionB --key=key --recursive=true"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - Map<String, String> data = result.getMapFromSection("0"); - assertThat(data.get("Locations Found")).isEqualTo("4"); + gfsh.executeAndAssertThat("locate entry --region=regionB --key=key --recursive=true") + .statusIsSuccess().containsKeyValuePair("Locations Found", "4"); } @Test @@ -112,12 +97,8 @@ public class LocateEntryDUnitTest { "put --region=regionA --key=('key':'1') --value=('value':'1') " + "--key-class=" + Key.class.getCanonicalName() + " --value-class=" + Value.class.getCanonicalName()) .statusIsSuccess(); - CommandResult result = - gfsh.executeCommand("locate entry --region=regionA --key=('key':'1') " + "--key-class=" - + Key.class.getCanonicalName() + " --value-class=" + Value.class.getCanonicalName()); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - Map<String, String> data = result.getMapFromSection("0"); - assertThat(data.get("Locations Found")).isEqualTo("1"); + gfsh.executeAndAssertThat("locate entry --region=regionA --key=('key':'1') " + "--key-class=" + + Key.class.getCanonicalName()).statusIsSuccess() + .containsKeyValuePair("Locations Found", "1"); } } diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/PutCommandIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/PutCommandIntegrationTest.java index c618f4f..b3a3230 100644 --- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/PutCommandIntegrationTest.java +++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/PutCommandIntegrationTest.java @@ -17,8 +17,6 @@ package org.apache.geode.management.internal.cli.commands; import static org.assertj.core.api.Assertions.assertThat; -import java.util.Map; - import org.junit.After; import org.junit.ClassRule; import org.junit.Test; @@ -26,14 +24,12 @@ import org.junit.experimental.categories.Category; import org.junit.rules.RuleChain; import org.apache.geode.cache.RegionShortcut; -import org.apache.geode.management.cli.Result; import org.apache.geode.management.internal.cli.dto.Car; import org.apache.geode.management.internal.cli.dto.Key; import org.apache.geode.management.internal.cli.dto.Key1; import org.apache.geode.management.internal.cli.dto.ObjectWithCharAttr; import org.apache.geode.management.internal.cli.dto.Value; import org.apache.geode.management.internal.cli.dto.Value2; -import org.apache.geode.management.internal.cli.result.CommandResult; import org.apache.geode.test.junit.categories.GfshTest; import org.apache.geode.test.junit.categories.IntegrationTest; import org.apache.geode.test.junit.rules.GfshCommandRule; @@ -99,7 +95,7 @@ public class PutCommandIntegrationTest { @Test // Bug : 51587 : GFSH command failing when ; is present in either key or value in put operation - public void putWithSemicolon() throws Exception { + public void putWithSemicoln() throws Exception { gfsh.executeAndAssertThat("put --region=/testRegion --key=key1;key1 --value=value1;value1") .statusIsSuccess().containsKeyValuePair("Result", "true"); assertThat(server.getCache().getRegion("testRegion").get("key1;key1")) @@ -112,11 +108,8 @@ public class PutCommandIntegrationTest { gfsh.executeAndAssertThat("help put").statusIsSuccess() .containsOutput("(Deprecated: Use --if-not-exists)."); - CommandResult result = - gfsh.executeCommand("put --region=/testRegion --key=key1 --value=value1"); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - Map<String, String> data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("true"); + gfsh.executeAndAssertThat("put --region=/testRegion --key=key1 --value=value1") + .statusIsSuccess().containsKeyValuePair("Result", "true"); // if unspecified then override gfsh.executeAndAssertThat("put --region=/testRegion --key=key1 --value=value2") @@ -137,30 +130,10 @@ public class PutCommandIntegrationTest { @Test public void putWithSimpleJson() throws Exception { - CommandResult result = gfsh.executeCommand( - "put --region=testRegion --key=('key':'1') --value=('value':'1') " + "--key-class=" - + Key.class.getCanonicalName() + " --value-class=" + Value.class.getCanonicalName()); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - Map<String, String> data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("true"); - } - - @Test - public void putWithCorrectJsonSyntax() throws Exception { - CommandResult result = gfsh.executeCommand( - "put --region=testRegion --key={\"key\":\"1\"} --value={\"value\":\"1\"} " + "--key-class=" - + Key.class.getCanonicalName() + " --value-class=" + Value.class.getCanonicalName()); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - Map<String, String> data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("true"); - } - - @Test - public void putWithInvalidJson() throws Exception { gfsh.executeAndAssertThat( - "put --region=testRegion --key=('key':'1') --value=(value:2) " + "--key-class=" + "put --region=testRegion --key=('key':'1') --value=('value':'1') " + "--key-class=" + Key.class.getCanonicalName() + " --value-class=" + Value.class.getCanonicalName()) - .statusIsError().containsOutput("Failed to convert input key"); + .statusIsSuccess().containsKeyValuePair("Result", "true"); } @Test @@ -175,11 +148,7 @@ public class PutCommandIntegrationTest { String command = "put --region=testRegion --key=" + keyJson + " --value=" + stateJson + " --key-class=" + Key1.class.getCanonicalName() + " --value-class=" + Value2.class.getCanonicalName(); - CommandResult result = gfsh.executeCommand(command); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - Map<String, String> data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("true"); + gfsh.executeAndAssertThat(command).statusIsSuccess(); // put the car json String list = "['red','white','blue']"; @@ -190,19 +159,11 @@ public class PutCommandIntegrationTest { valueJson = valueJson.replaceAll("\\?map", map); command = "put --region=testRegion --key=" + keyJson + " --value=" + valueJson + " --key-class=" + Key1.class.getCanonicalName() + " --value-class=" + Car.class.getCanonicalName(); - result = gfsh.executeCommand(command); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("true"); + gfsh.executeAndAssertThat(command).statusIsSuccess(); // put with json with single character field command = "put --region=testRegion --key-class=" + ObjectWithCharAttr.class.getCanonicalName() + " --value=456 --key=('name':'hesdfdsfy2','t':456,'c':'d')"; - result = gfsh.executeCommand(command); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - - data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("true"); + gfsh.executeAndAssertThat(command).statusIsSuccess(); } } diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/QueryCommandIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/QueryCommandIntegrationTest.java index dae707b..a95ce31 100644 --- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/QueryCommandIntegrationTest.java +++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/QueryCommandIntegrationTest.java @@ -21,7 +21,6 @@ import java.io.Serializable; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.List; -import java.util.Map; import com.google.common.io.Files; import org.apache.commons.io.FileUtils; @@ -36,8 +35,6 @@ import org.junit.rules.TemporaryFolder; import org.apache.geode.cache.Cache; import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionShortcut; -import org.apache.geode.management.cli.Result; -import org.apache.geode.management.internal.cli.result.CommandResult; import org.apache.geode.management.internal.cli.shell.Gfsh; import org.apache.geode.test.junit.categories.GfshTest; import org.apache.geode.test.junit.categories.IntegrationTest; @@ -147,18 +144,17 @@ public class QueryCommandIntegrationTest { File outputFile = temporaryFolder.newFile("queryOutput.txt"); FileUtils.deleteQuietly(outputFile); - CommandResult result = gfsh.executeCommand( - "query --query='select * from /simpleRegion' --file=" + outputFile.getAbsolutePath()); - assertThat(result.getStatus()).isEqualTo(Result.Status.OK); - // .statusIsSuccess().containsOutput(outputFile.getAbsolutePath()); + gfsh.executeAndAssertThat( + "query --query='select * from /simpleRegion' --file=" + outputFile.getAbsolutePath()) + .statusIsSuccess().containsOutput(outputFile.getAbsolutePath()); assertThat(outputFile).exists(); List<String> lines = Files.readLines(outputFile, StandardCharsets.UTF_8); - assertThat(lines.get(4)).isEqualTo("Result"); - assertThat(lines.get(5)).isEqualTo("--------"); - lines.subList(6, lines.size()).forEach(line -> assertThat(line).matches("value\\d+")); + assertThat(lines.get(0)).isEqualTo("Result"); + assertThat(lines.get(1)).isEqualTo("--------"); + lines.subList(2, lines.size()).forEach(line -> assertThat(line).matches("value\\d+")); } @Test @@ -174,8 +170,8 @@ public class QueryCommandIntegrationTest { assertThat(outputFile).exists(); List<String> lines = Files.readLines(outputFile, StandardCharsets.UTF_8); - assertThat(lines.get(4)).containsPattern("name\\s+\\|\\s+address"); - lines.subList(6, lines.size()) + assertThat(lines.get(0)).containsPattern("name\\s+\\|\\s+address"); + lines.subList(2, lines.size()) .forEach(line -> assertThat(line).matches("name\\d+\\s+\\|\\s+address\\d+")); } @@ -194,18 +190,6 @@ public class QueryCommandIntegrationTest { } @Test - public void queryWithGfshEnvVariables() { - gfsh.executeAndAssertThat("set variable --name=DATA_REGION --value=/complexRegion") - .statusIsSuccess(); - gfsh.executeAndAssertThat("set variable --name=QUERY_LIMIT --value=10").statusIsSuccess(); - CommandResult result = gfsh.executeCommand( - "query --query='select c.name, c.address from ${DATA_REGION} c limit ${QUERY_LIMIT}'"); - Map<String, String> data = result.getMapFromSection("0"); - - assertThat(data.get("Rows")).isEqualTo("10"); - } - - @Test public void queryWithInvalidRegionNameGivesDescriptiveErrorMessage() throws Exception { gfsh.executeAndAssertThat("query --query='select * from /nonExistentRegion'") .containsKeyValuePair("Result", "false") @@ -213,43 +197,18 @@ public class QueryCommandIntegrationTest { } @Test - public void invalidQueryGivesDescriptiveErrorMessage() { - CommandResult result = gfsh.executeCommand("query --query='this is not a valid query'"); - - Map<String, String> data = result.getMapFromSection("0"); - assertThat(data.get("Result")).isEqualTo("false"); - assertThat(data.get("Message")) - .startsWith("Query is invalid due to error : <Syntax error in query:"); + public void invalidQueryGivesDescriptiveErrorMessage() throws Exception { + gfsh.executeAndAssertThat("query --query='this is not a valid query'") + .containsKeyValuePair("Result", "false") + .containsOutput("Query is invalid due for error : <Syntax error in query:"); } @Test - public void queryGivesDescriptiveErrorMessageIfNoQueryIsSpecified() { + public void queryGivesDescriptiveErrorMessageIfNoQueryIsSpecified() throws Exception { gfsh.executeAndAssertThat("query").containsOutput( "You should specify option (--query, --file, --interactive) for this command"); } - @Test - public void queryReturnsUndefinedQueryResult() { - CommandResult result = - gfsh.executeCommand("query --query='select c.unknown from /complexRegion c limit 10'"); - - Map<String, List<String>> table = result.getMapFromTableContent("1"); - assertThat(table.get("Value").size()).isEqualTo(10); - assertThat(table.get("Value").get(0)).isEqualTo("UNDEFINED"); - } - - @Test - public void queryReturnsNonSelectResult() { - CommandResult result = gfsh.executeCommand( - "query --query=\"(select c.address from /complexRegion c where c.name = 'name1' limit 1).size\""); - - Map<String, String> data = result.getMapFromSection("0"); - assertThat(data.get("Rows")).isEqualTo("1"); - - Map<String, List<String>> table = result.getMapFromTableContent("1"); - assertThat(table.get("Result")).contains("1"); - } - private String[] splitOnLineBreaks(String multilineString) { return multilineString.split("[\\r\\n]+"); } diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/RemoveCommandDUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/RemoveCommandDUnitTest.java index adb3646..85ccaf3 100644 --- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/RemoveCommandDUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/RemoveCommandDUnitTest.java @@ -112,8 +112,12 @@ public class RemoveCommandDUnitTest { public void removeKeyFromPartitionedRegion() { String command = "remove --key=key1 --region=" + PARTITIONED_REGION_NAME; - gfsh.executeAndAssertThat(command).statusIsSuccess().containsKeyValuePair("Result", "true") - .containsKeyValuePair("Key Class", "java.lang.String").containsKeyValuePair("Key", "key1"); + gfsh.executeAndAssertThat(command).statusIsSuccess(); + + String output = gfsh.getGfshOutput(); + assertThat(output).containsPattern("Result\\s+:\\s+true"); + assertThat(output).containsPattern("Key Class\\s+:\\s+java.lang.String"); + assertThat(output).containsPattern("Key\\s+:\\s+key1"); server1.invoke(() -> verifyKeyIsRemoved(PARTITIONED_REGION_NAME, "key1")); server2.invoke(() -> verifyKeyIsRemoved(PARTITIONED_REGION_NAME, "key1")); diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/DataCommandFunctionWithPDXJUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/DataCommandFunctionWithPDXJUnitTest.java index 66e962e..4b6a38c 100644 --- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/DataCommandFunctionWithPDXJUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/DataCommandFunctionWithPDXJUnitTest.java @@ -17,9 +17,6 @@ package org.apache.geode.management.internal.cli.functions; import static org.apache.geode.management.internal.cli.domain.DataCommandResult.MISSING_VALUE; import static org.assertj.core.api.Assertions.assertThat; -import java.util.List; -import java.util.Map; - import org.assertj.core.api.SoftAssertions; import org.junit.Before; import org.junit.Rule; @@ -31,8 +28,11 @@ import org.apache.geode.cache.RegionShortcut; import org.apache.geode.internal.cache.InternalCache; import org.apache.geode.management.internal.cli.domain.DataCommandRequest; import org.apache.geode.management.internal.cli.domain.DataCommandResult; -import org.apache.geode.management.internal.cli.result.model.ResultModel; -import org.apache.geode.management.internal.cli.result.model.TabularResultModel; +import org.apache.geode.management.internal.cli.json.GfJsonArray; +import org.apache.geode.management.internal.cli.json.GfJsonException; +import org.apache.geode.management.internal.cli.json.GfJsonObject; +import org.apache.geode.management.internal.cli.result.CompositeResultData; +import org.apache.geode.management.internal.cli.result.TabularResultData; import org.apache.geode.pdx.PdxReader; import org.apache.geode.pdx.PdxSerializable; import org.apache.geode.pdx.PdxWriter; @@ -72,91 +72,94 @@ public class DataCommandFunctionWithPDXJUnitTest { // GEODE-2662: building a table where early values are missing keys causes the data to shift // upward during reporting. @Test - public void testTableIsRectangular() { - TabularResultModel rawTable = getTableFromQuery("select * from /" + PARTITIONED_REGION); + public void testTableIsRectangular() throws GfJsonException { + TabularResultData rawTable = getTableFromQuery("select * from /" + PARTITIONED_REGION); // Verify any table built - Map<String, List<String>> content = rawTable.getContent(); - assertThat(content).isNotEmpty(); - + assertThat(rawTable.getGfJsonObject()).isNotNull(); + assertThat(rawTable.getGfJsonObject().getJSONObject("content")).isNotNull(); + GfJsonObject tableJson = rawTable.getGfJsonObject().getJSONObject("content"); // Verify table is rectangular SoftAssertions softly = new SoftAssertions(); for (String k : new String[] {"id", "phone", "firstName", "lastName"}) { - softly.assertThat(content.get(k).size()).isEqualTo(4); + softly.assertThat(tableJson.getJSONArray(k).size()).isEqualTo(4); } softly.assertAll(); } @Test - public void testVerifyDataDoesNotShift() { - TabularResultModel rawTable = + public void testVerifyDataDoesNotShift() throws Exception { + TabularResultData rawTable = getTableFromQuery("select * from /" + PARTITIONED_REGION + " order by id"); // Verify any table built - Map<String, List<String>> content = rawTable.getContent(); - assertThat(content).isNotEmpty(); - + assertThat(rawTable.getGfJsonObject()).isNotNull(); + assertThat(rawTable.getGfJsonObject().getJSONObject("content")).isNotNull(); + GfJsonObject tableJson = rawTable.getGfJsonObject().getJSONObject("content"); // Table only contains correct keys - assertThat(content.get("missingKey")).isNull(); + assertThat(tableJson.getJSONArray("missingKey")).isNull(); // Table contains correct data - assertThatRowIsBuiltCorrectly(content, 0, alice); - assertThatRowIsBuiltCorrectly(content, 1, bob); - assertThatRowIsBuiltCorrectly(content, 2, charlie); - assertThatRowIsBuiltCorrectly(content, 3, dan); + assertThatRowIsBuiltCorrectly(tableJson, 0, alice); + assertThatRowIsBuiltCorrectly(tableJson, 1, bob); + assertThatRowIsBuiltCorrectly(tableJson, 2, charlie); + assertThatRowIsBuiltCorrectly(tableJson, 3, dan); } @Test - public void testFilteredQueryWithPhone() { - TabularResultModel rawTable = getTableFromQuery( + public void testFilteredQueryWithPhone() throws Exception { + TabularResultData rawTable = getTableFromQuery( "select * from /" + PARTITIONED_REGION + " c where IS_DEFINED ( c.phone ) order by id"); - Map<String, List<String>> content = rawTable.getContent(); - assertThat(content).isNotEmpty(); - + assertThat(rawTable.getGfJsonObject()).isNotNull(); + assertThat(rawTable.getGfJsonObject().getJSONObject("content")).isNotNull(); + GfJsonObject tableJson = rawTable.getGfJsonObject().getJSONObject("content"); for (String k : new String[] {"id", "phone", "firstName", "lastName"}) { - assertThat(content.get(k).size()).isEqualTo(2); + assertThat(tableJson.getJSONArray(k).size()).isEqualTo(2); } - assertThatRowIsBuiltCorrectly(content, 0, charlie); - assertThatRowIsBuiltCorrectly(content, 1, dan); + assertThatRowIsBuiltCorrectly(tableJson, 0, charlie); + assertThatRowIsBuiltCorrectly(tableJson, 1, dan); } + @Test - public void testFilteredQueryWithoutPhone() { - TabularResultModel rawTable = getTableFromQuery( + public void testFilteredQueryWithoutPhone() throws Exception { + TabularResultData rawTable = getTableFromQuery( "select * from /" + PARTITIONED_REGION + " c where IS_UNDEFINED ( c.phone ) order by id"); - Map<String, List<String>> content = rawTable.getContent(); - assertThat(content).isNotNull(); + assertThat(rawTable.getGfJsonObject()).isNotNull(); + assertThat(rawTable.getGfJsonObject().getJSONObject("content")).isNotNull(); + GfJsonObject tableJson = rawTable.getGfJsonObject().getJSONObject("content"); for (String k : new String[] {"id", "firstName", "lastName"}) { - assertThat(content.get(k).size()).isEqualTo(2); + assertThat(tableJson.getJSONArray(k).size()).isEqualTo(2); } - assertThatRowIsBuiltCorrectly(content, 0, alice); - assertThatRowIsBuiltCorrectly(content, 1, bob); + assertThatRowIsBuiltCorrectly(tableJson, 0, alice); + assertThatRowIsBuiltCorrectly(tableJson, 1, bob); } - private TabularResultModel getTableFromQuery(String query) { + private TabularResultData getTableFromQuery(String query) { DataCommandRequest request = new DataCommandRequest(); request.setQuery(query); DataCommandResult result = new DataCommandFunction().select(request, cache); - ResultModel m = result.toSelectCommandResult(); - return m.getTableSection("1"); + CompositeResultData r = result.toSelectCommandResult(); + return r.retrieveSectionByIndex(0).retrieveTableByIndex(0); } - private void assertThatRowIsBuiltCorrectly(Map<String, List<String>> table, int rowNum, - Customer customer) { + + private void assertThatRowIsBuiltCorrectly(GfJsonObject table, int rowNum, Customer customer) + throws Exception { SoftAssertions softly = new SoftAssertions(); - String id = table.get("id").get(rowNum); - String firstName = table.get("firstName").get(rowNum); - String lastName = table.get("lastName").get(rowNum); + String id = (String) table.getJSONArray("id").get(rowNum); + String firstName = (String) table.getJSONArray("firstName").get(rowNum); + String lastName = (String) table.getJSONArray("lastName").get(rowNum); softly.assertThat(id).describedAs("Customer ID").isEqualTo(customer.id); softly.assertThat(firstName).describedAs("First name").isEqualTo(customer.firstName); softly.assertThat(lastName).describedAs("Last name").isEqualTo(customer.lastName); - List<String> phoneArray = table.get("phone"); + GfJsonArray phoneArray = table.getJSONArray("phone"); if (phoneArray == null) { softly.assertThat(customer).describedAs("No phone data") .isNotInstanceOf(CustomerWithPhone.class); } else { - String phone = phoneArray.get(rowNum); + String phone = (String) phoneArray.get(rowNum); if (customer instanceof CustomerWithPhone) { softly.assertThat(phone).describedAs("Phone") diff --git a/geode-core/src/test/java/org/apache/geode/pdx/SimpleClass.java b/geode-core/src/test/java/org/apache/geode/pdx/SimpleClass.java index 9feed9b..1b65059 100644 --- a/geode-core/src/test/java/org/apache/geode/pdx/SimpleClass.java +++ b/geode-core/src/test/java/org/apache/geode/pdx/SimpleClass.java @@ -38,18 +38,6 @@ public class SimpleClass implements PdxSerializable { this.myEnum = enumVal; } - public int getMyInt() { - return myInt; - } - - public byte getMyByte() { - return myByte; - } - - public SimpleEnum getMyEnum() { - return myEnum; - } - public void toData(PdxWriter out) { out.writeInt("myInt", this.myInt); out.writeByte("myByte", this.myByte); -- To stop receiving notification emails like this one, please contact jensde...@apache.org.