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 f1c6b56 GEODE-5011: Convert 'Data' commands to ResultModel (#1945) f1c6b56 is described below commit f1c6b560442f2f23aa9240b3550d9d664e094c7c Author: Jens Deppe <jde...@pivotal.io> AuthorDate: Thu May 10 22:07:33 2018 -0700 GEODE-5011: Convert 'Data' commands to ResultModel (#1945) --- .../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, 632 insertions(+), 815 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 7a6bfbc..b4da63d 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,19 +21,21 @@ 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 Result makePresentationResult(DataCommandResult dataResult) { - if (dataResult != null) { - return dataResult.toCommandResult(); + static String makeBrokenJsonCompliant(String json) { + if (json == null) { + return null; + } + + if (json.startsWith("(") && json.endsWith(")")) { + return "{" + json.substring(1, json.length() - 1) + "}"; } else { - return ResultBuilder.createGemFireErrorResult("Error executing data command"); + return json; } } 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 cf34715..085655c 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,7 +16,6 @@ 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; @@ -31,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 GetCommand extends InternalGfshCommand { @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_DATA, CliStrings.TOPIC_GEODE_REGION}) @CliCommand(value = {CliStrings.GET}, help = CliStrings.GET__HELP) - public Result get( + public ResultModel get( @CliOption(key = {CliStrings.GET__KEY}, mandatory = true, help = CliStrings.GET__KEY__HELP) String key, @CliOption(key = {CliStrings.GET__REGIONNAME}, mandatory = true, @@ -60,6 +59,8 @@ 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(); @@ -92,6 +93,6 @@ public class GetCommand extends InternalGfshCommand { dataResult.setValueClass(valueClass); } - return makePresentationResult(dataResult); + return dataResult.toResultModel(); } } 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 07dd4d1..d70914f 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,7 +16,6 @@ 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; @@ -27,18 +26,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 Result locateEntry( + public ResultModel 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, @@ -56,6 +55,8 @@ public class LocateEntryCommand extends InternalGfshCommand { DataCommandResult dataResult; + key = DataCommandsUtils.makeBrokenJsonCompliant(key); + DataCommandFunction locateEntry = new DataCommandFunction(); Set<DistributedMember> memberList = findMembersForRegion(regionPath); if (CollectionUtils.isNotEmpty(memberList)) { @@ -76,6 +77,6 @@ public class LocateEntryCommand extends InternalGfshCommand { dataResult.setValueClass(valueClass); } - return makePresentationResult(dataResult); + return dataResult.toResultModel(); } } 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 feb0056..4b13840 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,7 +16,6 @@ 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 +29,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 Result put( + public ResultModel put( @CliOption(key = {CliStrings.PUT__KEY}, mandatory = true, help = CliStrings.PUT__KEY__HELP) String key, @CliOption(key = {CliStrings.PUT__VALUE}, mandatory = true, @@ -63,6 +62,10 @@ 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(); @@ -91,6 +94,6 @@ public class PutCommand extends InternalGfshCommand { if (valueClass != null) { dataResult.setValueClass(valueClass); } - return makePresentationResult(dataResult); + return dataResult.toResultModel(); } } 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 9d92c45..b8d8f49 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,15 +38,13 @@ 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.CompositeResultData; -import org.apache.geode.management.internal.cli.result.ResultBuilder; +import org.apache.geode.management.internal.cli.result.model.ResultModel; import org.apache.geode.security.ResourcePermission.Operation; import org.apache.geode.security.ResourcePermission.Resource; @@ -55,7 +53,7 @@ public class QueryCommand extends InternalGfshCommand { @CliCommand(value = "query", help = CliStrings.QUERY__HELP) @CliMetaData(interceptor = "org.apache.geode.management.internal.cli.commands.QueryInterceptor") - public Result query( + public ResultModel 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.", @@ -63,8 +61,7 @@ public class QueryCommand extends InternalGfshCommand { @CliOption(key = CliStrings.QUERY__INTERACTIVE, unspecifiedDefaultValue = "false", help = CliStrings.QUERY__INTERACTIVE__HELP) final boolean interactive) { DataCommandResult dataResult = select(query); - CompositeResultData rd = dataResult.toSelectCommandResult(); - return ResultBuilder.buildResult(rd); + return dataResult.toSelectCommandResult(); } 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 e9f8ce2..8b5940e 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,34 +19,32 @@ 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.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; +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; public class QueryInterceptor extends AbstractCliAroundInterceptor { public static final String FILE_ALREADY_EXISTS_MESSAGE = "The specified output file already exists."; @Override - public Result preExecution(GfshParseResult parseResult) { + public ResultModel preExecution(GfshParseResult parseResult) { File outputFile = getOutputFile(parseResult); if (outputFile != null && outputFile.exists()) { - return ResultBuilder.createUserErrorResult(FILE_ALREADY_EXISTS_MESSAGE); + return ResultModel.createError(FILE_ALREADY_EXISTS_MESSAGE); } - return ResultBuilder.createInfoResult(""); + return new ResultModel(); } @Override @@ -58,36 +56,36 @@ public class QueryInterceptor extends AbstractCliAroundInterceptor { return result; } - CompositeResultData resultData = (CompositeResultData) result.getResultData(); - CompositeResultData.SectionResultData sectionResultData = resultData.retrieveSectionByIndex(0); + ResultModel model = ((ModelCommandResult) result).getResultData(); + Map<String, String> sectionResultData = model.getDataSection("0").getContent(); - String limit = sectionResultData.retrieveString("Limit"); - String resultString = sectionResultData.retrieveString("Result"); - String rows = sectionResultData.retrieveString("Rows"); + String limit = sectionResultData.get("Limit"); + String resultString = sectionResultData.get("Result"); + String rows = sectionResultData.get("Rows"); if ("false".equalsIgnoreCase(resultString)) { return result; } - TabularResultData tabularResultData = sectionResultData.retrieveTableByIndex(0); - CommandResult resultTable = new LegacyCommandResult(tabularResultData); try { - writeResultTableToFile(outputFile, resultTable); + writeResultTableToFile(outputFile, result); // return a result w/ message explaining limit } catch (IOException e) { throw new RuntimeException(e); } - InfoResultData infoResultData = ResultBuilder.createInfoResultData(); - infoResultData.addLine("Result : " + resultString); + ResultModel newModel = new ResultModel(); + DataResultModel data = newModel.addData(); + + data.addData("Result", resultString); if (StringUtils.isNotBlank(limit)) { - infoResultData.addLine("Limit : " + limit); + data.addData("Limit", limit); } - infoResultData.addLine("Rows : " + rows); - infoResultData.addLine(SystemUtils.LINE_SEPARATOR); - infoResultData.addLine("Query results output to " + outputFile.getAbsolutePath()); + data.addData("Rows", rows); + + newModel.addInfo().addLine("Query results output to " + outputFile.getAbsolutePath()); - return new LegacyCommandResult(infoResultData); + return new ModelCommandResult(newModel); } 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 a6612d8..d3c640f 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,8 +16,6 @@ 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; @@ -31,11 +29,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; @@ -44,7 +42,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 Result remove( + public ResultModel remove( @CliOption(key = {CliStrings.REMOVE__KEY}, help = CliStrings.REMOVE__KEY__HELP, specifiedDefaultValue = "") String key, @CliOption(key = {CliStrings.REMOVE__REGION}, mandatory = true, @@ -57,7 +55,7 @@ public class RemoveCommand extends InternalGfshCommand { Cache cache = getCache(); if (!removeAllKeys && (key == null)) { - return createUserErrorResult(CliStrings.REMOVE__MSG__KEY_EMPTY); + return new ResultModel().createError(CliStrings.REMOVE__MSG__KEY_EMPTY); } if (removeAllKeys) { @@ -66,6 +64,8 @@ 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 createUserErrorResult(String.format(REGION_NOT_FOUND, regionPath)); + return new ResultModel().createError(String.format(REGION_NOT_FOUND, regionPath)); } DataCommandRequest request = new DataCommandRequest(); @@ -89,6 +89,7 @@ public class RemoveCommand extends InternalGfshCommand { } dataResult.setKeyClass(keyClass); - return makePresentationResult(dataResult); + + return dataResult.toResultModel(); } } 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 429c329..b23d0ea 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,33 +14,29 @@ */ 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.HashSet; -import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; -import java.util.Set; +import java.util.Map; +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.DataSerializer; -import org.apache.geode.internal.ClassPathLoader; +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.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.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; +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; /** @@ -370,12 +366,7 @@ public class DataCommandResult implements Serializable { return locateEntryLocations; } - public void setLocateEntryLocations(List<KeyInfo> locateEntryLocations) { - this.locateEntryLocations = locateEntryLocations; - } - - public Result toCommandResult() { - + public ResultModel toResultModel() { if (StringUtils.isEmpty(keyClass)) { keyClass = "java.lang.String"; } @@ -384,62 +375,48 @@ public class DataCommandResult implements Serializable { valueClass = "java.lang.String"; } + ResultModel result = new ResultModel(); + DataResultModel data = result.addData(); + if (errorString != null) { - CompositeResultData data = ResultBuilder.createCompositeResultData(); - SectionResultData section = data.addSection(); - section.addData("Message", errorString); - section.addData(RESULT_FLAG, operationCompletedSuccessfully); - return ResultBuilder.buildResult(data); + data.addData("Message", errorString); + data.addData(RESULT_FLAG, operationCompletedSuccessfully); + return result; } - CompositeResultData data = ResultBuilder.createCompositeResultData(); - SectionResultData section = data.addSection(); - TabularResultData table = section.addTable(); - - section.addData(RESULT_FLAG, operationCompletedSuccessfully); + data.addData(RESULT_FLAG, operationCompletedSuccessfully); if (infoString != null) { - section.addData("Message", infoString); + data.addData("Message", infoString); } if (isGet()) { - toCommandResult_isGet(section, table); + toResultModel_isGet(data); } else if (isLocateEntry()) { - toCommandResult_isLocate(section, table); + toResultModel_isLocate(result, data); } else if (isPut()) { - toCommandResult_isPut(section, table); + toResultModel_isPut(data); } else if (isRemove()) { - toCommandResult_isRemove(section, table); + toResultModel_isRemove(data); } - return ResultBuilder.buildResult(data); + + return result; } - private void toCommandResult_isGet(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, getResult); - } else { - section.addData("Value", getResult); - } + 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"); } - private void toCommandResult_isLocate(SectionResultData section, TabularResultData table) { + private void toResultModel_isLocate(ResultModel result, DataResultModel data) { - section.addData("Key Class", getKeyClass()); - if (!isDeclaredPrimitive(keyClass)) { - addJSONStringToTable(table, inputKey); - } else { - section.addData("Key", inputKey); - } + data.addData("Key Class", getKeyClass()); + data.addData("Key", inputKey); if (locateEntryLocations != null) { - TabularResultData locationTable = section.addTable(); + TabularResultModel locationTable = result.addTable(); int totalLocations = 0; @@ -489,38 +466,23 @@ public class DataCommandResult implements Serializable { } } } - section.addData("Locations Found", totalLocations); + data.addData("Locations Found", totalLocations); } else { - section.addData("Location Info ", "Could not find location information"); + data.addData("Location Info ", "Could not find location information"); } } - 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_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_isRemove(SectionResultData section, TabularResultData table) { + private void toResultModel_isRemove(DataResultModel data) { if (inputKey != null) {// avoids printing key when remove ALL is called - section.addData("Key Class", getKeyClass()); - if (!isDeclaredPrimitive(keyClass)) { - addJSONStringToTable(table, inputKey); - } else { - section.addData("Key", inputKey); - } + data.addData("Key Class", getKeyClass()); + data.addData("Key", inputKey); } } @@ -530,119 +492,62 @@ 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 CompositeResultData toSelectCommandResult() { - if (errorString != null) { - CompositeResultData data = ResultBuilder.createCompositeResultData(); - SectionResultData section = data.addSection(); - section.addData("Message", errorString); - section.addData(RESULT_FLAG, operationCompletedSuccessfully); - return data; + 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; } else { - CompositeResultData data = ResultBuilder.createCompositeResultData(); - SectionResultData section = data.addSection(); - TabularResultData table = section.addTable(); - section.addData(RESULT_FLAG, operationCompletedSuccessfully); + DataResultModel data = result.addData(); + TabularResultModel table = result.addTable(); + data.addData(RESULT_FLAG, operationCompletedSuccessfully); if (infoString != null) { - section.addData("Message", infoString); + data.addData("Message", infoString); } if (inputQuery != null) { if (this.limit > 0) { - section.addData("Limit", this.limit); + data.addData("Limit", this.limit); } if (this.selectResult != null) { - section.addData(NUM_ROWS, this.selectResult.size()); + data.addData(NUM_ROWS, this.selectResult.size()); if (this.queryTraceString != null) { - section.addData("Query Trace", this.queryTraceString); + data.addData("Query Trace", this.queryTraceString); } buildTable(table, 0, selectResult.size()); } } - return data; + return result; } } - 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. + private void buildTable(TabularResultModel table, int startCount, int endCount) { int lastRowExclusive = Math.min(selectResult.size(), endCount + 1); List<SelectResultRow> paginatedRows = selectResult.subList(startCount, lastRowExclusive); - List<GfJsonObject> tableRows = new ArrayList<>(); - List<GfJsonObject> rowsWithRealJsonObjects = new ArrayList<>(); - Set<String> columns = new HashSet<>(); - + // First find all the possible columns - not a Set because we want them ordered consistently + List<String> possibleColumns = new ArrayList<>(); for (SelectResultRow row : paginatedRows) { - 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); + for (String column : row.getColumnValues().keySet()) { + if (!possibleColumns.contains(column)) { + possibleColumns.add(column); } - tableRows.add(object); - } catch (GfJsonException e) { - JSONObject errJson = - new JSONObject().put("Value", "Error getting bean properties " + e.getMessage()); - tableRows.add(new GfJsonObject(errJson, false)); } } - // 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; + for (SelectResultRow row : paginatedRows) { + Map<String, String> columnValues = row.getColumnValues(); + for (String column : possibleColumns) { + table.accumulate(column, + columnValues.getOrDefault(column, DataCommandResult.MISSING_VALUE)); } } - return value; } public Object getInputQuery() { @@ -657,7 +562,7 @@ public class DataCommandResult implements Serializable { this.limit = limit; } - public static class KeyInfo implements /* Data */ Serializable { + public static class KeyInfo implements Serializable { private String memberId; private String memberName; @@ -737,26 +642,6 @@ 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; @@ -766,32 +651,65 @@ public class DataCommandResult implements Serializable { public static class SelectResultRow implements Serializable { private static final long serialVersionUID = 1L; private int type; - private Object value; + private final Map<String, String> columnValues; public SelectResultRow(int type, Object value) { this.type = type; - this.value = value; + this.columnValues = createColumnValues(value); } - public int getType() { - return type; + public Map<String, String> getColumnValues() { + return columnValues; } - public void setType(int type) { - this.type = 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 Object getValue() { - return value; + 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 void setValue(Object value) { - this.value = value; + private void resolvePdxToColumns(Map<String, String> columnData, PdxInstance pdx) { + for (String field : pdx.getFieldNames()) { + columnData.put(field, pdx.getField(field).toString()); + } } + 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()) { @@ -829,96 +747,4 @@ 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 989f79b..a51d29e 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,17 +14,19 @@ */ 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; @@ -42,8 +44,6 @@ 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,9 +56,8 @@ 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; /** @@ -192,7 +191,6 @@ 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); @@ -219,15 +217,15 @@ public class DataCommandFunction implements InternalFunction { queryObserver.reset2(); } if (results instanceof SelectResults) { - select_SelectResults((SelectResults) results, principal, list, nestedObjectCount, cache); + select_SelectResults((SelectResults) results, principal, list, cache); } else { select_NonSelectResults(results, list); } return DataCommandResult.createSelectResult(queryString, list, queryVerboseMsg, null, null, true); - } catch (FunctionDomainException | GfJsonException | QueryInvocationTargetException - | NameResolutionException | TypeMismatchException e) { + } catch (FunctionDomainException | QueryInvocationTargetException | NameResolutionException + | TypeMismatchException e) { logger.warn(e.getMessage(), e); return DataCommandResult.createSelectResult(queryString, null, queryVerboseMsg, e, e.getMessage(), false); @@ -242,97 +240,30 @@ public class DataCommandFunction implements InternalFunction { if (logger.isDebugEnabled()) { logger.debug("BeanResults : Bean Results class is {}", results.getClass()); } - 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())); + list.add(createSelectResultRow(results)); } private void select_SelectResults(SelectResults selectResults, Object principal, - List<SelectResultRow> list, AtomicInteger nestedObjectCount, InternalCache cache) - throws GfJsonException { + List<SelectResultRow> list, InternalCache cache) { for (Object object : selectResults) { // Post processing object = cache.getSecurityService().postProcess(principal, null, null, object, false); - 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())); - } + list.add(createSelectResultRow(object)); } } - private String toJson(Object object) { - if (object instanceof Undefined) { - return "{\"Value\":\"UNDEFINED\"}"; - } else if (object instanceof PdxInstance) { - return pdxToJson((PdxInstance) object); + 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; } else { - return JsonUtil.objectToJsonNestedChkCDep(object, NESTED_JSON_LENGTH); + rowType = DataCommandResult.ROW_TYPE_BEAN; } - } - 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; + return new SelectResultRow(rowType, object); } @SuppressWarnings({"rawtypes"}) @@ -371,7 +302,7 @@ public class DataCommandFunction implements InternalFunction { if (logger.isDebugEnabled()) { logger.debug("Removed key {} successfully", key); } - Object array[] = getJSONForNonPrimitiveObject(value); + Object array[] = getClassAndJson(value); DataCommandResult result = DataCommandResult.createRemoveResult(key, array[1], null, null, true); if (array[0] != null) { @@ -448,7 +379,7 @@ public class DataCommandFunction implements InternalFunction { if (logger.isDebugEnabled()) { logger.debug("Get for key {} value {}", key, value); } - Object array[] = getJSONForNonPrimitiveObject(value); + Object array[] = getClassAndJson(value); if (value != null) { DataCommandResult result = DataCommandResult.createGetResult(key, array[1], null, null, true); @@ -463,7 +394,7 @@ public class DataCommandFunction implements InternalFunction { if (logger.isDebugEnabled()) { logger.debug("Key is not present in the region {}", regionName); } - return DataCommandResult.createGetInfoResult(key, null, null, + return DataCommandResult.createGetInfoResult(key, getClassAndJson(null)[1], null, CliStrings.GET__MSG__KEY_NOT_FOUND_REGION, false); } } @@ -545,8 +476,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, - getJSONForNonPrimitiveObject(value)[1], isPrimary, "" + bucketId}); + keyInfo.addLocation(new Object[] {region.getFullPath(), true, getClassAndJson(value)[1], + isPrimary, "" + bucketId}); } else { if (logger.isDebugEnabled()) { logger.debug("Key is not present in the region {}", regionPath); @@ -561,8 +492,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, - getJSONForNonPrimitiveObject(value)[1], false, null}); + keyInfo.addLocation( + new Object[] {region.getFullPath(), true, getClassAndJson(value)[1], false, null}); } else { keyInfo.addLocation(new Object[] {region.getFullPath(), false, null, false, null}); } @@ -631,7 +562,7 @@ public class DataCommandFunction implements InternalFunction { } else { returnValue = region.put(keyObject, valueObject); } - Object array[] = getJSONForNonPrimitiveObject(returnValue); + Object array[] = getClassAndJson(returnValue); DataCommandResult result = DataCommandResult.createPutResult(key, array[1], null, null, true); if (array[0] != null) { result.setValueClass((String) array[0]); @@ -652,115 +583,44 @@ public class DataCommandFunction implements InternalFunction { return string; } - 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()); - } + 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()); } - return getObjectFromJson(string, klass); + return resultObject; } - @SuppressWarnings({"rawtypes"}) - public static Object[] getJSONForNonPrimitiveObject(Object obj) { + private Object[] getClassAndJson(Object obj) { Object[] array = new Object[2]; + if (obj == null) { array[0] = null; - array[1] = "<NULL>"; - return array; - } 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; - } + array[1] = null; return array; } - } - 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; - } + array[0] = obj.getClass().getCanonicalName(); + + if (obj instanceof PdxInstance) { + array[1] = JSONFormatter.toJSON((PdxInstance) obj); + return array; } - return null; - } - 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(); + ObjectMapper mapper = new ObjectMapper(); + try { + array[1] = mapper.writeValueAsString(obj); + } catch (JsonProcessingException e) { + array[1] = e.getMessage(); } - return JsonUtil.jsonToObject(newString, klass); - } + return array; + } /** * 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 5902980..da553fa 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 for error : <{0}>"; + public static final String QUERY__MSG__INVALID_QUERY = "Query is invalid due to 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 6b2656a..94cf9ed 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,6 +29,7 @@ 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 7b7dedc..27f8f3b 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,9 +181,7 @@ public class GfshExecutionStrategy implements ExecutionStrategy { if (((ResultModel) preExecResult).getStatus() != Status.OK) { return new ModelCommandResult((ResultModel) preExecResult); } - } - - if (preExecResult instanceof Result) { + } else { // Must be Result if (Status.ERROR.equals(((Result) preExecResult).getStatus())) { return (Result) preExecResult; } @@ -261,7 +259,6 @@ 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 dde4c25..7a2e627 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,type:int,value:java/lang/Object +org/apache/geode/management/internal/cli/domain/DataCommandResult$SelectResultRow,true,1,columnValues:java/util/Map,type:int 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 8e6f4c2..7651ea5 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,8 +40,6 @@ 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; @@ -68,13 +66,10 @@ 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.TabularResultData; +import org.apache.geode.management.internal.cli.result.model.DataResultModel; +import org.apache.geode.management.internal.cli.result.model.ResultModel; import org.apache.geode.test.dunit.Host; import org.apache.geode.test.dunit.IgnoredException; import org.apache.geode.test.dunit.SerializableCallable; @@ -715,7 +710,7 @@ public class GemfireDataCommandsDUnitTest extends CliCommandTestBase { vm1.invoke(clearTask); - // Do put from shell check from gemfire do remove from shell get from shell exepct false + // Do put from shell check from gemfire do remove from shell get from shell expect false cmdResult = executeCommand(putCommand); printCommandOutput(cmdResult); validateResult(cmdResult, true); @@ -755,151 +750,32 @@ public class GemfireDataCommandsDUnitTest extends CliCommandTestBase { } - 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); + 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()); } else fail("Expected CompositeResult Returned Result Type " + cmdResult.getType()); } - 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); + 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()); if (expectedFlag && expectedRows != -1) { - 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); - } + 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); } } } 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 dddb598..c21622d 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,6 +20,7 @@ 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; @@ -29,13 +30,19 @@ 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; @@ -45,6 +52,16 @@ 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(); @@ -56,23 +73,34 @@ public class GetCommandIntegrationTest { @BeforeClass public static void beforeClass() throws Exception { - 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); + InternalCache cache = server.getCache(); - Region<String, User> users = regionFactory.create("Users"); - assertThat(users.getName()).isEqualTo("Users"); - assertThat(users.getFullPath()).isEqualTo("/Users"); + // Region containing POJOs + RegionFactory<String, User> userRegionFactory = + cache.createRegionFactory(RegionShortcut.REPLICATE); + userRegionFactory.setCacheLoader(new UserDataStoreCacheLoader()); + Region<String, User> users = userRegionFactory.create("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 @@ -86,20 +114,100 @@ public class GetCommandIntegrationTest { } @Test - 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"); + 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); - gfsh.executeAndAssertThat("get --region=Users --key=jondoe").statusIsSuccess(); - assertThat(gfsh.getGfshOutput()).contains("Result : true"); + 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); + + 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\""); // get something that does not exist - gfsh.executeAndAssertThat("get --region=Users --key=missingUser --load-on-cache-miss") - .statusIsSuccess(); - assertThat(gfsh.getGfshOutput()).contains("Result : false"); + 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"); } private static class User implements Serializable { @@ -114,6 +222,17 @@ 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) { @@ -131,29 +250,60 @@ 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()); + } - private static final Map<String, User> userDataStore = new HashMap<String, User>(5); + @Override + public void close() {} + } - 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")); - } + private static class UserPdxDataStoreCacheLoader + implements CacheLoader<String, PdxInstance>, Serializable { - protected static User createUser(final String username) { - return new User(username); + private InternalCache cache; + + UserPdxDataStoreCacheLoader(InternalCache cache) { + this.cache = cache; } @Override - public User load(final LoaderHelper<String, User> helper) throws CacheLoaderException { - return userDataStore.get(helper.getKey()); + 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); } @Override - public void close() { - userDataStore.clear(); + 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(); } + + @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(); } } 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 875421e..4ffcb05 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,6 +15,9 @@ 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; @@ -23,8 +26,10 @@ 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; @@ -75,20 +80,30 @@ public class LocateEntryDUnitTest { @Test public void locateEntryForPartitionedRegion() throws Exception { - gfsh.executeAndAssertThat("locate entry --region=regionA --key=key").statusIsSuccess() - .containsKeyValuePair("Locations Found", "1"); + 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"); } @Test public void locateEntryForReplicateRegion() throws Exception { - gfsh.executeAndAssertThat("locate entry --region=regionB --key=key").statusIsSuccess() - .containsKeyValuePair("Locations Found", "2"); + 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"); } @Test public void recursiveLocate() throws Exception { - gfsh.executeAndAssertThat("locate entry --region=regionB --key=key --recursive=true") - .statusIsSuccess().containsKeyValuePair("Locations Found", "4"); + 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"); } @Test @@ -97,8 +112,12 @@ public class LocateEntryDUnitTest { "put --region=regionA --key=('key':'1') --value=('value':'1') " + "--key-class=" + Key.class.getCanonicalName() + " --value-class=" + Value.class.getCanonicalName()) .statusIsSuccess(); - gfsh.executeAndAssertThat("locate entry --region=regionA --key=('key':'1') " + "--key-class=" - + Key.class.getCanonicalName()).statusIsSuccess() - .containsKeyValuePair("Locations Found", "1"); + 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"); } } 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 b3a3230..c618f4f 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,6 +17,8 @@ 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; @@ -24,12 +26,14 @@ 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; @@ -95,7 +99,7 @@ public class PutCommandIntegrationTest { @Test // Bug : 51587 : GFSH command failing when ; is present in either key or value in put operation - public void putWithSemicoln() throws Exception { + public void putWithSemicolon() 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")) @@ -108,8 +112,11 @@ public class PutCommandIntegrationTest { gfsh.executeAndAssertThat("help put").statusIsSuccess() .containsOutput("(Deprecated: Use --if-not-exists)."); - gfsh.executeAndAssertThat("put --region=/testRegion --key=key1 --value=value1") - .statusIsSuccess().containsKeyValuePair("Result", "true"); + 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"); // if unspecified then override gfsh.executeAndAssertThat("put --region=/testRegion --key=key1 --value=value2") @@ -130,10 +137,30 @@ public class PutCommandIntegrationTest { @Test public void putWithSimpleJson() throws Exception { - gfsh.executeAndAssertThat( + 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=" + Key.class.getCanonicalName() + " --value-class=" + Value.class.getCanonicalName()) - .statusIsSuccess().containsKeyValuePair("Result", "true"); + .statusIsError().containsOutput("Failed to convert input key"); } @Test @@ -148,7 +175,11 @@ public class PutCommandIntegrationTest { String command = "put --region=testRegion --key=" + keyJson + " --value=" + stateJson + " --key-class=" + Key1.class.getCanonicalName() + " --value-class=" + Value2.class.getCanonicalName(); - gfsh.executeAndAssertThat(command).statusIsSuccess(); + 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"); // put the car json String list = "['red','white','blue']"; @@ -159,11 +190,19 @@ 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(); - gfsh.executeAndAssertThat(command).statusIsSuccess(); + result = gfsh.executeCommand(command); + assertThat(result.getStatus()).isEqualTo(Result.Status.OK); + + data = result.getMapFromSection("0"); + assertThat(data.get("Result")).isEqualTo("true"); // 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')"; - gfsh.executeAndAssertThat(command).statusIsSuccess(); + result = gfsh.executeCommand(command); + assertThat(result.getStatus()).isEqualTo(Result.Status.OK); + + data = result.getMapFromSection("0"); + assertThat(data.get("Result")).isEqualTo("true"); } } 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 a95ce31..dae707b 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,6 +21,7 @@ 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; @@ -35,6 +36,8 @@ 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; @@ -144,17 +147,18 @@ public class QueryCommandIntegrationTest { File outputFile = temporaryFolder.newFile("queryOutput.txt"); FileUtils.deleteQuietly(outputFile); - gfsh.executeAndAssertThat( - "query --query='select * from /simpleRegion' --file=" + outputFile.getAbsolutePath()) - .statusIsSuccess().containsOutput(outputFile.getAbsolutePath()); + CommandResult result = gfsh.executeCommand( + "query --query='select * from /simpleRegion' --file=" + outputFile.getAbsolutePath()); + assertThat(result.getStatus()).isEqualTo(Result.Status.OK); + // .statusIsSuccess().containsOutput(outputFile.getAbsolutePath()); assertThat(outputFile).exists(); List<String> lines = Files.readLines(outputFile, StandardCharsets.UTF_8); - assertThat(lines.get(0)).isEqualTo("Result"); - assertThat(lines.get(1)).isEqualTo("--------"); - lines.subList(2, lines.size()).forEach(line -> assertThat(line).matches("value\\d+")); + assertThat(lines.get(4)).isEqualTo("Result"); + assertThat(lines.get(5)).isEqualTo("--------"); + lines.subList(6, lines.size()).forEach(line -> assertThat(line).matches("value\\d+")); } @Test @@ -170,8 +174,8 @@ public class QueryCommandIntegrationTest { assertThat(outputFile).exists(); List<String> lines = Files.readLines(outputFile, StandardCharsets.UTF_8); - assertThat(lines.get(0)).containsPattern("name\\s+\\|\\s+address"); - lines.subList(2, lines.size()) + assertThat(lines.get(4)).containsPattern("name\\s+\\|\\s+address"); + lines.subList(6, lines.size()) .forEach(line -> assertThat(line).matches("name\\d+\\s+\\|\\s+address\\d+")); } @@ -190,6 +194,18 @@ 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") @@ -197,18 +213,43 @@ public class QueryCommandIntegrationTest { } @Test - 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:"); + 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:"); } @Test - public void queryGivesDescriptiveErrorMessageIfNoQueryIsSpecified() throws Exception { + public void queryGivesDescriptiveErrorMessageIfNoQueryIsSpecified() { 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 85ccaf3..adb3646 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,12 +112,8 @@ public class RemoveCommandDUnitTest { public void removeKeyFromPartitionedRegion() { String command = "remove --key=key1 --region=" + PARTITIONED_REGION_NAME; - 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"); + gfsh.executeAndAssertThat(command).statusIsSuccess().containsKeyValuePair("Result", "true") + .containsKeyValuePair("Key Class", "java.lang.String").containsKeyValuePair("Key", "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 4b6a38c..66e962e 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,6 +17,9 @@ 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; @@ -28,11 +31,8 @@ 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.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.management.internal.cli.result.model.ResultModel; +import org.apache.geode.management.internal.cli.result.model.TabularResultModel; import org.apache.geode.pdx.PdxReader; import org.apache.geode.pdx.PdxSerializable; import org.apache.geode.pdx.PdxWriter; @@ -72,94 +72,91 @@ 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() throws GfJsonException { - TabularResultData rawTable = getTableFromQuery("select * from /" + PARTITIONED_REGION); + public void testTableIsRectangular() { + TabularResultModel rawTable = getTableFromQuery("select * from /" + PARTITIONED_REGION); // Verify any table built - assertThat(rawTable.getGfJsonObject()).isNotNull(); - assertThat(rawTable.getGfJsonObject().getJSONObject("content")).isNotNull(); - GfJsonObject tableJson = rawTable.getGfJsonObject().getJSONObject("content"); + Map<String, List<String>> content = rawTable.getContent(); + assertThat(content).isNotEmpty(); + // Verify table is rectangular SoftAssertions softly = new SoftAssertions(); for (String k : new String[] {"id", "phone", "firstName", "lastName"}) { - softly.assertThat(tableJson.getJSONArray(k).size()).isEqualTo(4); + softly.assertThat(content.get(k).size()).isEqualTo(4); } softly.assertAll(); } @Test - public void testVerifyDataDoesNotShift() throws Exception { - TabularResultData rawTable = + public void testVerifyDataDoesNotShift() { + TabularResultModel rawTable = getTableFromQuery("select * from /" + PARTITIONED_REGION + " order by id"); // Verify any table built - assertThat(rawTable.getGfJsonObject()).isNotNull(); - assertThat(rawTable.getGfJsonObject().getJSONObject("content")).isNotNull(); - GfJsonObject tableJson = rawTable.getGfJsonObject().getJSONObject("content"); + Map<String, List<String>> content = rawTable.getContent(); + assertThat(content).isNotEmpty(); + // Table only contains correct keys - assertThat(tableJson.getJSONArray("missingKey")).isNull(); + assertThat(content.get("missingKey")).isNull(); // Table contains correct data - assertThatRowIsBuiltCorrectly(tableJson, 0, alice); - assertThatRowIsBuiltCorrectly(tableJson, 1, bob); - assertThatRowIsBuiltCorrectly(tableJson, 2, charlie); - assertThatRowIsBuiltCorrectly(tableJson, 3, dan); + assertThatRowIsBuiltCorrectly(content, 0, alice); + assertThatRowIsBuiltCorrectly(content, 1, bob); + assertThatRowIsBuiltCorrectly(content, 2, charlie); + assertThatRowIsBuiltCorrectly(content, 3, dan); } @Test - public void testFilteredQueryWithPhone() throws Exception { - TabularResultData rawTable = getTableFromQuery( + public void testFilteredQueryWithPhone() { + TabularResultModel rawTable = getTableFromQuery( "select * from /" + PARTITIONED_REGION + " c where IS_DEFINED ( c.phone ) order by id"); - assertThat(rawTable.getGfJsonObject()).isNotNull(); - assertThat(rawTable.getGfJsonObject().getJSONObject("content")).isNotNull(); - GfJsonObject tableJson = rawTable.getGfJsonObject().getJSONObject("content"); + Map<String, List<String>> content = rawTable.getContent(); + assertThat(content).isNotEmpty(); + for (String k : new String[] {"id", "phone", "firstName", "lastName"}) { - assertThat(tableJson.getJSONArray(k).size()).isEqualTo(2); + assertThat(content.get(k).size()).isEqualTo(2); } - assertThatRowIsBuiltCorrectly(tableJson, 0, charlie); - assertThatRowIsBuiltCorrectly(tableJson, 1, dan); + assertThatRowIsBuiltCorrectly(content, 0, charlie); + assertThatRowIsBuiltCorrectly(content, 1, dan); } - @Test - public void testFilteredQueryWithoutPhone() throws Exception { - TabularResultData rawTable = getTableFromQuery( + public void testFilteredQueryWithoutPhone() { + TabularResultModel rawTable = getTableFromQuery( "select * from /" + PARTITIONED_REGION + " c where IS_UNDEFINED ( c.phone ) order by id"); - assertThat(rawTable.getGfJsonObject()).isNotNull(); - assertThat(rawTable.getGfJsonObject().getJSONObject("content")).isNotNull(); - GfJsonObject tableJson = rawTable.getGfJsonObject().getJSONObject("content"); + Map<String, List<String>> content = rawTable.getContent(); + assertThat(content).isNotNull(); for (String k : new String[] {"id", "firstName", "lastName"}) { - assertThat(tableJson.getJSONArray(k).size()).isEqualTo(2); + assertThat(content.get(k).size()).isEqualTo(2); } - assertThatRowIsBuiltCorrectly(tableJson, 0, alice); - assertThatRowIsBuiltCorrectly(tableJson, 1, bob); + assertThatRowIsBuiltCorrectly(content, 0, alice); + assertThatRowIsBuiltCorrectly(content, 1, bob); } - private TabularResultData getTableFromQuery(String query) { + private TabularResultModel getTableFromQuery(String query) { DataCommandRequest request = new DataCommandRequest(); request.setQuery(query); DataCommandResult result = new DataCommandFunction().select(request, cache); - CompositeResultData r = result.toSelectCommandResult(); - return r.retrieveSectionByIndex(0).retrieveTableByIndex(0); + ResultModel m = result.toSelectCommandResult(); + return m.getTableSection("1"); } - - private void assertThatRowIsBuiltCorrectly(GfJsonObject table, int rowNum, Customer customer) - throws Exception { + private void assertThatRowIsBuiltCorrectly(Map<String, List<String>> table, int rowNum, + Customer customer) { SoftAssertions softly = new SoftAssertions(); - String id = (String) table.getJSONArray("id").get(rowNum); - String firstName = (String) table.getJSONArray("firstName").get(rowNum); - String lastName = (String) table.getJSONArray("lastName").get(rowNum); + String id = table.get("id").get(rowNum); + String firstName = table.get("firstName").get(rowNum); + String lastName = table.get("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); - GfJsonArray phoneArray = table.getJSONArray("phone"); + List<String> phoneArray = table.get("phone"); if (phoneArray == null) { softly.assertThat(customer).describedAs("No phone data") .isNotInstanceOf(CustomerWithPhone.class); } else { - String phone = (String) phoneArray.get(rowNum); + String phone = 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 1b65059..9feed9b 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,6 +38,18 @@ 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.