You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by je...@apache.org on 2016/02/25 21:27:26 UTC
[38/50] [abbrv] incubator-geode git commit: Merge branch 'develop'
into feature/GEODE-17
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5c01d5f4/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/DurableClientCommands.java
----------------------------------------------------------------------
diff --cc geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/DurableClientCommands.java
index 0000000,b844e85..e6de2ec
mode 000000,100644..100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/DurableClientCommands.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/DurableClientCommands.java
@@@ -1,0 -1,430 +1,437 @@@
+ /*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package com.gemstone.gemfire.management.internal.cli.commands;
+
+
+ import java.util.ArrayList;
+ import java.util.HashMap;
+ import java.util.HashSet;
+ import java.util.LinkedList;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.TreeMap;
+ import java.util.TreeSet;
+
+ import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
+ import org.springframework.shell.core.annotation.CliCommand;
+ import org.springframework.shell.core.annotation.CliOption;
+
+ import com.gemstone.gemfire.cache.Cache;
+ import com.gemstone.gemfire.cache.CacheFactory;
+ import com.gemstone.gemfire.cache.execute.ResultCollector;
+ import com.gemstone.gemfire.distributed.DistributedMember;
+ import com.gemstone.gemfire.internal.lang.StringUtils;
+ import com.gemstone.gemfire.management.cli.Result;
+ import com.gemstone.gemfire.management.internal.cli.CliUtil;
+ import com.gemstone.gemfire.management.cli.CliMetaData;
+ import com.gemstone.gemfire.management.cli.ConverterHint;
+ import com.gemstone.gemfire.management.internal.cli.domain.DurableCqNamesResult;
+ import com.gemstone.gemfire.management.internal.cli.domain.IndexDetails.IndexStatisticsDetails;
+ import com.gemstone.gemfire.management.internal.cli.domain.MemberResult;
+ import com.gemstone.gemfire.management.internal.cli.domain.SubscriptionQueueSizeResult;
+ import com.gemstone.gemfire.management.internal.cli.functions.CloseDurableClientFunction;
+ import com.gemstone.gemfire.management.internal.cli.functions.CloseDurableCqFunction;
+ import com.gemstone.gemfire.management.internal.cli.functions.GetSubscriptionQueueSizeFunction;
+ import com.gemstone.gemfire.management.internal.cli.functions.ListDurableCqNamesFunction;
+ import com.gemstone.gemfire.management.internal.cli.i18n.CliStrings;
+ import com.gemstone.gemfire.management.internal.cli.result.CommandResultException;
+ import com.gemstone.gemfire.management.internal.cli.result.CompositeResultData;
+ import com.gemstone.gemfire.management.internal.cli.result.ErrorResultData;
+ import com.gemstone.gemfire.management.internal.cli.result.InfoResultData;
+ import com.gemstone.gemfire.management.internal.cli.result.ResultBuilder;
+ import com.gemstone.gemfire.management.internal.cli.result.ResultData;
+ import com.gemstone.gemfire.management.internal.cli.result.TabularResultData;
++import com.gemstone.gemfire.management.internal.security.Resource;
++import com.gemstone.gemfire.management.internal.security.ResourceConstants;
++import com.gemstone.gemfire.management.internal.security.ResourceOperation;
+
+ /**
+ * The DurableClientCommands class encapsulates all GemFire shell (Gfsh) commands related to
+ * durable clients and cqs defined in GemFire.
+ * </p>
+ * @author jhuynh
+ * @author bansods
+ */
+ @SuppressWarnings("unused")
+ public class DurableClientCommands extends AbstractCommandsSupport {
+
+ private static final ListDurableCqNamesFunction listDurableCqNamesFunction = new ListDurableCqNamesFunction();
+ private static final CloseDurableClientFunction closeDurableClientFunction = new CloseDurableClientFunction();
+ private static final CloseDurableCqFunction closeDurableCqFunction = new CloseDurableCqFunction();
+ private static final GetSubscriptionQueueSizeFunction countDurableCqEvents = new GetSubscriptionQueueSizeFunction();
+
+ @CliCommand(value = CliStrings.LIST_DURABLE_CQS, help = CliStrings.LIST_DURABLE_CQS__HELP)
+ @CliMetaData(shellOnly = false)
++ @ResourceOperation(resource = Resource.DISTRIBUTED_SYSTEM, operation= ResourceConstants.LIST_DS)
+ public Result listDurableClientCqs(
+ @CliOption (key = CliStrings.LIST_DURABLE_CQS__DURABLECLIENTID,
+ mandatory=true,
+ help = CliStrings.LIST_DURABLE_CQS__DURABLECLIENTID__HELP
+ ) final String durableClientId,
+
+ @CliOption (key = CliStrings.LIST_DURABLE_CQS__MEMBER,
+ help = CliStrings.LIST_DURABLE_CQS__MEMBER__HELP,
+ optionContext=ConverterHint.MEMBERIDNAME
+ ) final String memberNameOrId,
+
+ @CliOption (key = CliStrings.LIST_DURABLE_CQS__GROUP,
+ help = CliStrings.LIST_DURABLE_CQS__GROUP__HELP,
+ optionContext=ConverterHint.MEMBERGROUP
+ ) final String group) {
+ Result result = null;
+ try {
+
+ boolean noResults = true;
+ Set<DistributedMember> targetMembers;
+ try {
+ targetMembers = CliUtil.findAllMatchingMembers(group, memberNameOrId);
+ } catch (CommandResultException e) {
+ return e.getResult();
+ }
+ final ResultCollector<?,?> rc = CliUtil.executeFunction(new ListDurableCqNamesFunction(), durableClientId, targetMembers);
+ final List<DurableCqNamesResult> results = (List<DurableCqNamesResult>) rc.getResult();
+ Map<String, List<String>> memberCqNamesMap = new TreeMap<String, List<String>>();
+ Map<String, List<String>> errorMessageNodes = new HashMap<String, List<String>>();
+ Map<String, List<String>> exceptionMessageNodes = new HashMap<String, List<String>>();
+
+ for (DurableCqNamesResult memberResult : results) {
+ if (memberResult != null) {
+ if (memberResult.isSuccessful()) {
+ memberCqNamesMap.put(memberResult.getMemberNameOrId(), memberResult.getCqNamesList());
+ } else {
+ if (memberResult.isOpPossible()) {
+ groupByMessage(memberResult.getExceptionMessage(), memberResult.getMemberNameOrId(), exceptionMessageNodes);
+ } else {
+ groupByMessage(memberResult.getErrorMessage(), memberResult.getMemberNameOrId(), errorMessageNodes);
+ }
+ }
+ }
+ }
+
+ if (!memberCqNamesMap.isEmpty()) {
+ TabularResultData table = ResultBuilder.createTabularResultData();
+ Set<String> members = memberCqNamesMap.keySet();
+
+ for (String member : members) {
+ boolean isFirst = true;
+ List<String> cqNames = memberCqNamesMap.get(member);
+ for (String cqName : cqNames) {
+ if (isFirst) {
+ isFirst = false;
+ table.accumulate(CliStrings.LIST_DURABLE_CQS__MEMBER, member);
+ } else {
+ table.accumulate(CliStrings.LIST_DURABLE_CQS__MEMBER, "");
+ }
+ table.accumulate(CliStrings.LIST_DURABLE_CQS__NAME, cqName);
+ }
+ }
+ result = ResultBuilder.buildResult(table);
+ } else {
+ String errorHeader = CliStrings.format(CliStrings.LIST_DURABLE_CQS__FAILURE__HEADER, durableClientId);
+ result = ResultBuilder.buildResult(buildFailureData(null, exceptionMessageNodes, errorMessageNodes, errorHeader));
+ }
+ } catch (Exception e) {
+ result = ResultBuilder.createGemFireErrorResult(e.getMessage());
+ }
+
+ return result;
+ }
+
+ @CliCommand(value = CliStrings.COUNT_DURABLE_CQ_EVENTS, help = CliStrings.COUNT_DURABLE_CQ_EVENTS__HELP)
+ @CliMetaData(shellOnly = false)
++ @ResourceOperation(resource = Resource.DISTRIBUTED_SYSTEM, operation= ResourceConstants.LIST_DS)
+ public Result countDurableCqEvents(
+ @CliOption (key = CliStrings.COUNT_DURABLE_CQ_EVENTS__DURABLE__CLIENT__ID,
+ mandatory=true,
+ help = CliStrings.COUNT_DURABLE_CQ_EVENTS__DURABLE__CLIENT__ID__HELP
+ ) final String durableClientId,
+ @CliOption (key = CliStrings.COUNT_DURABLE_CQ_EVENTS__DURABLE__CQ__NAME,
+ mandatory = false,
+ help = CliStrings.COUNT_DURABLE_CQ_EVENTS__DURABLE__CQ__NAME__HELP
+ ) final String cqName,
+ @CliOption (key = CliStrings.COUNT_DURABLE_CQ_EVENTS__MEMBER,
+ mandatory=false,
+ help = CliStrings.COUNT_DURABLE_CQ_EVENTS__MEMBER__HELP,
+ optionContext = ConverterHint.MEMBERIDNAME
+ ) final String memberNameOrId,
+ @CliOption (key = CliStrings.COUNT_DURABLE_CQ_EVENTS__GROUP,
+ mandatory=false,
+ help = CliStrings.COUNT_DURABLE_CQ_EVENTS__GROUP__HELP,
+ optionContext = ConverterHint.MEMBERGROUP
+ ) final String group) {
+
+ Result result = null;
+ try {
+ Set<DistributedMember> targetMembers;
+ try {
+ targetMembers = CliUtil.findAllMatchingMembers(group, memberNameOrId);
+ } catch (CommandResultException e) {
+ return e.getResult();
+ }
+ String [] params = new String[2];
+ params[0] = durableClientId;
+ params[1] = cqName;
+ final ResultCollector<?,?> rc = CliUtil.executeFunction(new GetSubscriptionQueueSizeFunction(), params, targetMembers);
+ final List<SubscriptionQueueSizeResult> funcResults = (List<SubscriptionQueueSizeResult>) rc.getResult();
+
+ String queueSizeColumnName;
+
+ if (cqName != null && !cqName.isEmpty()) {
+ queueSizeColumnName = CliStrings.format(CliStrings.COUNT_DURABLE_CQ_EVENTS__SUBSCRIPTION__QUEUE__SIZE__CLIENT, cqName);
+ } else {
+ queueSizeColumnName = CliStrings.format(CliStrings.COUNT_DURABLE_CQ_EVENTS__SUBSCRIPTION__QUEUE__SIZE__CLIENT, durableClientId);
+ }
+ result = buildTableResultForQueueSize(funcResults, queueSizeColumnName);
+ } catch (Exception e) {
+ result = ResultBuilder.createGemFireErrorResult(e.getMessage());
+ }
+
+ return result;
+ }
+
+ @CliCommand(value = CliStrings.CLOSE_DURABLE_CLIENTS, help = CliStrings.CLOSE_DURABLE_CLIENTS__HELP)
+ @CliMetaData(shellOnly = false)
++ @ResourceOperation(resource = Resource.DISTRIBUTED_SYSTEM, operation= ResourceConstants.CLOSE_DURABLE_CLIENT)
+ public Result closeDurableClient(
+ @CliOption (key = CliStrings.CLOSE_DURABLE_CLIENTS__CLIENT__ID,
+ mandatory=true,
+ help = CliStrings.CLOSE_DURABLE_CLIENTS__CLIENT__ID__HELP
+ ) final String durableClientId,
+ @CliOption (key = CliStrings.CLOSE_DURABLE_CLIENTS__MEMBER,
+ mandatory=false,
+ help = CliStrings.CLOSE_DURABLE_CLIENTS__MEMBER__HELP,
+ optionContext = ConverterHint.MEMBERIDNAME
+ ) final String memberNameOrId,
+ @CliOption (key = CliStrings.CLOSE_DURABLE_CLIENTS__GROUP,
+ mandatory=false,
+ help = CliStrings.COUNT_DURABLE_CQ_EVENTS__GROUP__HELP,
+ optionContext = ConverterHint.MEMBERGROUP
+ ) final String group) {
+
+ Result result = null;
+ try {
+ Set<DistributedMember> targetMembers;
+ try {
+ targetMembers = CliUtil.findAllMatchingMembers(group, memberNameOrId);
+ } catch (CommandResultException e) {
+ return e.getResult();
+ }
+ final ResultCollector<?,?> rc = CliUtil.executeFunction(new CloseDurableClientFunction(), durableClientId, targetMembers);
+ final List<MemberResult> results = (List<MemberResult>) rc.getResult();
+ String failureHeader = CliStrings.format(CliStrings.CLOSE_DURABLE_CLIENTS__FAILURE__HEADER, durableClientId);
+ String successHeader = CliStrings.format(CliStrings.CLOSE_DURABLE_CLIENTS__SUCCESS, durableClientId);
+ result = buildResult(results, successHeader, failureHeader);
+ } catch (Exception e) {
+ result = ResultBuilder.createGemFireErrorResult(e.getMessage());
+ }
+ return result;
+ }
+
+
+ @CliCommand(value = CliStrings.CLOSE_DURABLE_CQS, help = CliStrings.CLOSE_DURABLE_CQS__HELP)
+ @CliMetaData(shellOnly = false)
++ @ResourceOperation(resource = Resource.DISTRIBUTED_SYSTEM, operation= ResourceConstants.CLOSE_DURABLE_CQ)
+ public Result closeDurableCqs(
+ @CliOption (key = CliStrings.CLOSE_DURABLE_CQS__DURABLE__CLIENT__ID,
+ mandatory=true,
+ help = CliStrings.CLOSE_DURABLE_CQS__DURABLE__CLIENT__ID__HELP
+ ) final String durableClientId,
+
+ @CliOption(key = CliStrings.CLOSE_DURABLE_CQS__NAME,
+ mandatory = true,
+ help = CliStrings.CLOSE_DURABLE_CQS__NAME__HELP)
+ final String cqName,
+
+ @CliOption (key = CliStrings.CLOSE_DURABLE_CQS__MEMBER,
+ mandatory=false,
+ help = CliStrings.CLOSE_DURABLE_CQS__MEMBER__HELP,
+ optionContext = ConverterHint.MEMBERIDNAME
+ ) final String memberNameOrId,
+
+ @CliOption (key = CliStrings.CLOSE_DURABLE_CQS__GROUP,
+ mandatory=false,
+ help = CliStrings.CLOSE_DURABLE_CQS__GROUP__HELP,
+ optionContext = ConverterHint.MEMBERGROUP
+ ) final String group) {
+ Result result = null;
+ try{
+ Set<DistributedMember> targetMembers;
+ try {
+ targetMembers = CliUtil.findAllMatchingMembers(group, memberNameOrId);
+ } catch (CommandResultException e) {
+ return e.getResult();
+ }
+
+ String [] params = new String[2];
+ params[0] = durableClientId;
+ params[1] = cqName;
+
+ final ResultCollector<?,?> rc = CliUtil.executeFunction(new CloseDurableCqFunction(), params, targetMembers);
+ final List<MemberResult> results = (List<MemberResult>) rc.getResult();
+ String failureHeader = CliStrings.format(CliStrings.CLOSE_DURABLE_CQS__FAILURE__HEADER, cqName, durableClientId);
+ String successHeader = CliStrings.format(CliStrings.CLOSE_DURABLE_CQS__SUCCESS, cqName, durableClientId);
+ result = buildResult(results, successHeader, failureHeader);
+ } catch (Exception e) {
+ result = ResultBuilder.createGemFireErrorResult(e.getMessage());
+ }
+ return result;
+ }
+
+
+ private Result buildResult (List<MemberResult> results, String successHeader, String failureHeader) {
+ Result result = null;
+ boolean failure = true;
+ boolean partialFailure = false;
+ Map<String, List<String>> errorMap = new HashMap<String, List<String>>();
+ Map<String, List<String>> successMap = new HashMap<String, List<String>>();
+ Map<String, List<String>> exceptionMap = new HashMap<String, List<String>>();
+
+ /***
+ * Aggregate the results from the members
+ */
+ for (MemberResult memberResult : results) {
+
+ if (memberResult.isSuccessful()) {
+ failure = false;
+ groupByMessage(memberResult.getSuccessMessage(), memberResult.getMemberNameOrId(), successMap);
+ } else {
+
+ if (memberResult.isOpPossible()) {
+ partialFailure = true;
+ groupByMessage(memberResult.getExceptionMessage(), memberResult.getMemberNameOrId(), exceptionMap);
+
+ }else {
+ groupByMessage(memberResult.getErrorMessage(), memberResult.getMemberNameOrId(), errorMap);
+ }
+ }
+ }
+
+ if (!failure && !partialFailure) {
+ result = ResultBuilder.buildResult(buildSuccessData(successMap));
+ } else {
+ result = ResultBuilder.buildResult(buildFailureData(successMap, exceptionMap, errorMap, failureHeader));
+ }
+ return result ;
+ }
+
+ private Result buildTableResultForQueueSize (List<SubscriptionQueueSizeResult> results, String queueSizeColumnName) {
+ Result result = null;
+ boolean failure = true;
+
+ Map<String, List<String>> failureMap = new HashMap<String, List<String>>();
+ Map<String, Long> memberQueueSizeTable = new TreeMap<String, Long>();
+
+ /***
+ * Aggregate the results from the members
+ */
+ for (SubscriptionQueueSizeResult memberResult : results) {
+
+ if (memberResult.isSuccessful()) {
+ failure = false;
+ memberResult.getSubscriptionQueueSize();
+ memberQueueSizeTable.put(memberResult.getMemberNameOrId(), memberResult.getSubscriptionQueueSize());
+ } else {
+ groupByMessage(memberResult.getErrorMessage(), memberResult.getMemberNameOrId(), failureMap);
+ }
+ }
+
+ if (!failure) {
+ TabularResultData table = ResultBuilder.createTabularResultData();
+
+ Set<String> members = memberQueueSizeTable.keySet();
+
+ for (String member : members) {
+ long queueSize = memberQueueSizeTable.get(member);
+ table.accumulate(CliStrings.COUNT_DURABLE_CQ_EVENTS__MEMBER, member);
+ table.accumulate(queueSizeColumnName, queueSize);
+ }
+ result = ResultBuilder.buildResult(table);
+
+ } else{
+ ErrorResultData erd = ResultBuilder.createErrorResultData();
+ buildErrorResult(erd, failureMap);
+ result = ResultBuilder.buildResult(erd);
+ }
+ return result ;
+ }
+
+ private void groupByMessage (String message, String memberNameOrId, Map<String, List<String>> map){
+ List<String> members = map.get(message);
+
+ if (members == null) {
+ members = new LinkedList<String>();
+ }
+ members.add(memberNameOrId);
+ map.put(message, members);
+ }
+
+
+ private InfoResultData buildSuccessData(Map<String, List<String>> successMap) {
+ InfoResultData ird = ResultBuilder.createInfoResultData();
+ Set<String> successMessages = successMap.keySet();
+
+ for (String successMessage : successMessages) {
+ ird.addLine(CliStrings.format(CliStrings.ACTION_SUCCCEEDED_ON_MEMBER, successMessage));
+
+ List<String> successfullMembers = successMap.get(successMessage);
+ int num = 0;
+ for (String member : successfullMembers) {
+ ird.addLine("" + ++num + "." + member);
+ }
+ ird.addLine("\n");
+ }
+ return ird;
+ }
+
+ private ErrorResultData buildFailureData(Map<String, List<String>> successMap, Map<String, List<String>> exceptionMap, Map<String, List<String>> errorMap, String errorHeader) {
+ ErrorResultData erd = ResultBuilder.createErrorResultData();
+ buildErrorResult(erd, successMap);
+ erd.addLine("\n");
+ erd.addLine(errorHeader);
+ buildErrorResult(erd, exceptionMap);
+ buildErrorResult(erd, errorMap);
+ return erd;
+ }
+
+ private void buildErrorResult(ErrorResultData erd, Map<String, List<String>> resultMap) {
+ if (resultMap != null && !resultMap.isEmpty()) {
+ Set<String> messages = resultMap.keySet();
+
+ for (String message : messages) {
+ erd.addLine("\n");
+ erd.addLine(message);
+ erd.addLine(CliStrings.OCCURRED_ON_MEMBERS);
+ List<String> members = resultMap.get(message);
+ int num = 0;
+ for (String member : members) {
+ ++num;
+ erd.addLine(""+num + "." + member);
+ }
+ }
+ }
+ }
+ @CliAvailabilityIndicator({ CliStrings.LIST_DURABLE_CQS, CliStrings.CLOSE_DURABLE_CLIENTS, CliStrings.CLOSE_DURABLE_CQS, CliStrings.COUNT_DURABLE_CQ_EVENTS })
+ public boolean durableCommandsAvailable() {
+ boolean isAvailable = true;
+ if (CliUtil.isGfshVM()) {
+ isAvailable = getGfsh() != null && getGfsh().isConnectedAndReady();
+ }
+ return isAvailable;
+ }
+ }
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5c01d5f4/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/ExportImportSharedConfigurationCommands.java
----------------------------------------------------------------------
diff --cc geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/ExportImportSharedConfigurationCommands.java
index 0000000,2e8447a..60eea3e
mode 000000,100644..100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/ExportImportSharedConfigurationCommands.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/ExportImportSharedConfigurationCommands.java
@@@ -1,0 -1,292 +1,297 @@@
+ /*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package com.gemstone.gemfire.management.internal.cli.commands;
+
+ import java.io.File;
+ import java.io.FileNotFoundException;
+ import java.io.IOException;
+ import java.util.HashSet;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+
+ import com.gemstone.gemfire.cache.execute.ResultCollector;
+ import com.gemstone.gemfire.distributed.DistributedMember;
+ import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+ import com.gemstone.gemfire.internal.lang.StringUtils;
+ import com.gemstone.gemfire.management.cli.CliMetaData;
+ import com.gemstone.gemfire.management.cli.Result;
+ import com.gemstone.gemfire.management.internal.cli.AbstractCliAroundInterceptor;
+ import com.gemstone.gemfire.management.internal.cli.CliUtil;
+ import com.gemstone.gemfire.management.internal.cli.GfshParseResult;
+ import com.gemstone.gemfire.management.internal.cli.functions.CliFunctionResult;
+ import com.gemstone.gemfire.management.internal.cli.functions.ExportSharedConfigurationFunction;
+ import com.gemstone.gemfire.management.internal.cli.functions.ImportSharedConfigurationArtifactsFunction;
+ import com.gemstone.gemfire.management.internal.cli.functions.LoadSharedConfigurationFunction;
+ import com.gemstone.gemfire.management.internal.cli.i18n.CliStrings;
+ import com.gemstone.gemfire.management.internal.cli.remote.CommandExecutionContext;
+ import com.gemstone.gemfire.management.internal.cli.result.FileResult;
+ import com.gemstone.gemfire.management.internal.cli.result.InfoResultData;
+ import com.gemstone.gemfire.management.internal.cli.result.ResultBuilder;
+ import com.gemstone.gemfire.management.internal.cli.result.TabularResultData;
++import com.gemstone.gemfire.management.internal.security.Resource;
++import com.gemstone.gemfire.management.internal.security.ResourceConstants;
++import com.gemstone.gemfire.management.internal.security.ResourceOperation;
+
+ import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
+ import org.springframework.shell.core.annotation.CliCommand;
+ import org.springframework.shell.core.annotation.CliOption;
+
+ /****
+ * Commands for the shared configuration
+ * @author bansods
+ *
+ */
+ @SuppressWarnings("unused")
+ public class ExportImportSharedConfigurationCommands extends AbstractCommandsSupport {
+
+ private final ExportSharedConfigurationFunction exportSharedConfigurationFunction = new ExportSharedConfigurationFunction();
+ private final ImportSharedConfigurationArtifactsFunction importSharedConfigurationFunction = new ImportSharedConfigurationArtifactsFunction();
+ private final LoadSharedConfigurationFunction loadSharedConfiguration = new LoadSharedConfigurationFunction();
+
+ @CliCommand(value = { CliStrings.EXPORT_SHARED_CONFIG }, help = CliStrings.EXPORT_SHARED_CONFIG__HELP)
+ @CliMetaData(interceptor = "com.gemstone.gemfire.management.internal.cli.commands.ExportImportSharedConfigurationCommands$ExportInterceptor", readsSharedConfiguration=true, relatedTopic = {CliStrings.TOPIC_GEMFIRE_CONFIG})
++ @ResourceOperation(resource = Resource.DISTRIBUTED_SYSTEM, operation= ResourceConstants.EXPORT_CONFIG)
+ public Result exportSharedConfig(
+ @CliOption(key = { CliStrings.EXPORT_SHARED_CONFIG__FILE},
+ mandatory = true,
+ help = CliStrings.EXPORT_SHARED_CONFIG__FILE__HELP)
+ String zipFileName,
+
+ @CliOption(key = { CliStrings.EXPORT_SHARED_CONFIG__DIR},
+ help = CliStrings.EXPORT_SHARED_CONFIG__DIR__HELP)
+ String dir
+ ) {
+ Result result;
+
+ InfoResultData infoData = ResultBuilder.createInfoResultData();
+ TabularResultData errorTable = ResultBuilder.createTabularResultData();
+ GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
+ Set<DistributedMember> locators = new HashSet<DistributedMember>(cache.getDistributionManager().getAllHostedLocatorsWithSharedConfiguration().keySet());
+ byte [] byteData;
+ boolean success = false;
+
+ if (!locators.isEmpty()) {
+ for (DistributedMember locator : locators) {
+ ResultCollector<?, ?> rc = CliUtil.executeFunction(exportSharedConfigurationFunction, null, locator);
+ @SuppressWarnings("unchecked")
+ List<CliFunctionResult> results = (List<CliFunctionResult>) rc.getResult();
+ CliFunctionResult functionResult = results.get(0);
+
+ if (functionResult.isSuccessful()) {
+ byteData = functionResult.getByteData();
+ infoData.addAsFile(zipFileName, byteData, InfoResultData.FILE_TYPE_BINARY, CliStrings.EXPORT_SHARED_CONFIG__DOWNLOAD__MSG, false);
+ success = true;
+ break;
+ } else {
+ errorTable.accumulate(CliStrings.LOCATOR_HEADER, functionResult.getMemberIdOrName());
+ errorTable.accumulate(CliStrings.ERROR__MSG__HEADER, functionResult.getMessage());
+ }
+ }
+ if (success) {
+ result = ResultBuilder.buildResult(infoData);
+ } else {
+ errorTable.setStatus(Result.Status.ERROR);
+ result = ResultBuilder.buildResult(errorTable);
+ }
+ } else {
+ result = ResultBuilder.createGemFireErrorResult(CliStrings.SHARED_CONFIGURATION_NO_LOCATORS_WITH_SHARED_CONFIGURATION);
+ }
+ return result;
+ }
+
+ @CliCommand(value = { CliStrings.IMPORT_SHARED_CONFIG }, help = CliStrings.IMPORT_SHARED_CONFIG__HELP)
+ @CliMetaData(interceptor = "com.gemstone.gemfire.management.internal.cli.commands.ExportImportSharedConfigurationCommands$ImportInterceptor", writesToSharedConfiguration=true, relatedTopic = {CliStrings.TOPIC_GEMFIRE_CONFIG})
++ @ResourceOperation(resource = Resource.DISTRIBUTED_SYSTEM, operation= ResourceConstants.IMPORT_CONFIG)
+ @SuppressWarnings("unchecked")
+ public Result importSharedConfig(
+ @CliOption(key = { CliStrings.IMPORT_SHARED_CONFIG__ZIP},
+ mandatory = true,
+ help = CliStrings.IMPORT_SHARED_CONFIG__ZIP__HELP)
+ String zip) {
+
+ GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
+
+ if (!CliUtil.getAllNormalMembers(cache).isEmpty()) {
+ return ResultBuilder.createGemFireErrorResult(CliStrings.IMPORT_SHARED_CONFIG__CANNOT__IMPORT__MSG);
+ }
+
+ Set<DistributedMember> locators = new HashSet<DistributedMember>(cache.getDistributionManager().getAllHostedLocatorsWithSharedConfiguration().keySet());
+
+ if (locators.isEmpty()) {
+ return ResultBuilder.createGemFireErrorResult(CliStrings.NO_LOCATORS_WITH_SHARED_CONFIG);
+ }
+
+ Result result;
+ byte[][] shellBytesData = CommandExecutionContext.getBytesFromShell();
+ String[] names = CliUtil.bytesToNames(shellBytesData);
+ byte[][] bytes = CliUtil.bytesToData(shellBytesData);
+
+ String zipFileName = names[0];
+ byte[] zipBytes = bytes[0];
+
+ Object [] args = new Object[] {zipFileName, zipBytes};
+
+ InfoResultData infoData = ResultBuilder.createInfoResultData();
+ TabularResultData errorTable = ResultBuilder.createTabularResultData();
+
+ boolean success = false;
+ boolean copySuccess = false;
+
+ ResultCollector<?, ?> rc = CliUtil.executeFunction(importSharedConfigurationFunction, args, locators);
+ List<CliFunctionResult> functionResults = CliFunctionResult.cleanResults((List<CliFunctionResult>) rc.getResult());
+
+ for (CliFunctionResult functionResult : functionResults) {
+ if (!functionResult.isSuccessful()) {
+ errorTable.accumulate(CliStrings.LOCATOR_HEADER, functionResult.getMemberIdOrName());
+ errorTable.accumulate(CliStrings.ERROR__MSG__HEADER, functionResult.getMessage());
+ } else {
+ copySuccess = true;
+ }
+ }
+
+ if (!copySuccess ) {
+ errorTable.setStatus(Result.Status.ERROR);
+ return ResultBuilder.buildResult(errorTable);
+ }
+
+ errorTable = ResultBuilder.createTabularResultData();
+
+ for (DistributedMember locator : locators) {
+ rc = CliUtil.executeFunction(loadSharedConfiguration, args, locator);
+ functionResults = (List<CliFunctionResult>) rc.getResult();
+ CliFunctionResult functionResult = functionResults.get(0);
+ if (functionResult.isSuccessful()) {
+ success = true;
+ infoData.addLine(functionResult.getMessage());
+ break;
+ } else {
+ errorTable.accumulate(CliStrings.LOCATOR_HEADER, functionResult.getMemberIdOrName());
+ errorTable.accumulate(CliStrings.ERROR__MSG__HEADER, functionResult.getMessage());
+ }
+ }
+
+ if (success) {
+ result = ResultBuilder.buildResult(infoData);
+ } else {
+ errorTable.setStatus(Result.Status.ERROR);
+ result = ResultBuilder.buildResult(errorTable);
+ }
+ return result;
+ }
+
+
+ @CliAvailabilityIndicator({CliStrings.EXPORT_SHARED_CONFIG, CliStrings.IMPORT_SHARED_CONFIG})
+ public boolean sharedConfigCommandsAvailable() {
+ boolean isAvailable = true; // always available on server
+ if (CliUtil.isGfshVM()) { // in gfsh check if connected
+ isAvailable = getGfsh() != null && getGfsh().isConnectedAndReady();
+ }
+ return isAvailable;
+ }
+
+ /**
+ * Interceptor used by gfsh to intercept execution of export shared config command at "shell".
+ */
+ public static class ExportInterceptor extends AbstractCliAroundInterceptor {
+ private String saveDirString;
+
+ @Override
+ public Result preExecution(GfshParseResult parseResult) {
+ Map<String, String> paramValueMap = parseResult.getParamValueStrings();
+ String zip = paramValueMap.get(CliStrings.EXPORT_SHARED_CONFIG__FILE);
+
+ if (!zip.endsWith(".zip")) {
+ return ResultBuilder.createUserErrorResult(CliStrings.format(CliStrings.INVALID_FILE_EXTENTION, ".zip"));
+ }
+ return ResultBuilder.createInfoResult("OK");
+ }
+
+ @Override
+ public Result postExecution(GfshParseResult parseResult, Result commandResult) {
+ if (commandResult.hasIncomingFiles()) {
+ try {
+ Map<String, String> paramValueMap = parseResult.getParamValueStrings();
+ String dir = paramValueMap.get(CliStrings.EXPORT_SHARED_CONFIG__DIR);
+ dir = (dir == null) ? null : dir.trim();
+
+ File saveDirFile = new File(".");
+
+ if (dir != null && !dir.isEmpty()) {
+ saveDirFile = new File(dir);
+ if (saveDirFile.exists()) {
+ if (!saveDirFile.isDirectory())
+ return ResultBuilder.createGemFireErrorResult(CliStrings.format(CliStrings.EXPORT_SHARED_CONFIG__MSG__NOT_A_DIRECTORY, dir));
+ } else if (!saveDirFile.mkdirs()) {
+ return ResultBuilder.createGemFireErrorResult(CliStrings.format(CliStrings.EXPORT_SHARED_CONFIG__MSG__CANNOT_CREATE_DIR, dir));
+ }
+ }
+ try {
+ if (!saveDirFile.canWrite()) {
+ return ResultBuilder.createGemFireErrorResult(CliStrings.format(CliStrings.EXPORT_SHARED_CONFIG__MSG__NOT_WRITEABLE, saveDirFile
+ .getCanonicalPath()));
+ }
+ } catch (IOException ioex) {
+ }
+ saveDirString = saveDirFile.getAbsolutePath();
+ commandResult.saveIncomingFiles(saveDirString);
+ return commandResult;
+ } catch (IOException ioex) {
+ return ResultBuilder.createShellClientErrorResult(CliStrings.EXPORT_SHARED_CONFIG__UNABLE__TO__EXPORT__CONFIG);
+ }
+ }
+ return null;
+ }
+ }
+
+
+ public static class ImportInterceptor extends AbstractCliAroundInterceptor {
+
+ public Result preExecution(GfshParseResult parseResult) {
+ Map<String, String> paramValueMap = parseResult.getParamValueStrings();
+
+ String zip = paramValueMap.get(CliStrings.IMPORT_SHARED_CONFIG__ZIP);
+
+ zip = StringUtils.trim(zip);
+
+ if (zip == null) {
+ return ResultBuilder.createUserErrorResult(CliStrings.format(CliStrings.IMPORT_SHARED_CONFIG__PROVIDE__ZIP, CliStrings.IMPORT_SHARED_CONFIG__ZIP));
+ }
+ if (!zip.endsWith(CliStrings.ZIP_FILE_EXTENSION)) {
+ return ResultBuilder.createUserErrorResult(CliStrings.format(CliStrings.INVALID_FILE_EXTENTION, CliStrings.ZIP_FILE_EXTENSION));
+ }
+
+ FileResult fileResult;
+
+ try {
+ fileResult = new FileResult(new String[] { zip });
+ } catch (FileNotFoundException fnfex) {
+ return ResultBuilder.createUserErrorResult("'" + zip + "' not found.");
+ } catch (IOException ioex) {
+ return ResultBuilder.createGemFireErrorResult(ioex.getClass().getName() + ": "
+ + ioex.getMessage());
+ }
+
+ return fileResult;
+ }
+ @Override
+ public Result postExecution(GfshParseResult parseResult, Result commandResult) {
+ return null;
+ }
+ }
+
+ }
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5c01d5f4/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/FunctionCommands.java
----------------------------------------------------------------------
diff --cc geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/FunctionCommands.java
index 0000000,7930e1e..7e9a128
mode 000000,100644..100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/FunctionCommands.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/FunctionCommands.java
@@@ -1,0 -1,642 +1,648 @@@
+ /*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package com.gemstone.gemfire.management.internal.cli.commands;
+ import java.util.ArrayList;
+ import java.util.Arrays;
+ import java.util.HashSet;
+ import java.util.Iterator;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Map.Entry;
+ import java.util.Set;
+
+ import org.springframework.shell.core.CommandMarker;
+ import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
+ import org.springframework.shell.core.annotation.CliCommand;
+ import org.springframework.shell.core.annotation.CliOption;
+
+ import com.gemstone.gemfire.SystemFailure;
+ import com.gemstone.gemfire.cache.Cache;
+ import com.gemstone.gemfire.cache.CacheFactory;
+ import com.gemstone.gemfire.cache.Region;
+ import com.gemstone.gemfire.cache.execute.Execution;
+ import com.gemstone.gemfire.cache.execute.Function;
+ import com.gemstone.gemfire.cache.execute.FunctionException;
+ import com.gemstone.gemfire.cache.execute.FunctionService;
+ import com.gemstone.gemfire.cache.execute.ResultCollector;
+ import com.gemstone.gemfire.distributed.DistributedMember;
+ import com.gemstone.gemfire.internal.ClassPathLoader;
+ import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+ import com.gemstone.gemfire.management.DistributedRegionMXBean;
+ import com.gemstone.gemfire.management.ManagementService;
+ import com.gemstone.gemfire.management.cli.CliMetaData;
+ import com.gemstone.gemfire.management.cli.ConverterHint;
+ import com.gemstone.gemfire.management.cli.Result;
+ import com.gemstone.gemfire.management.cli.Result.Status;
+ import com.gemstone.gemfire.management.internal.MBeanJMXAdapter;
+ import com.gemstone.gemfire.management.internal.cli.AbstractCliAroundInterceptor;
+ import com.gemstone.gemfire.management.internal.cli.CliUtil;
+ import com.gemstone.gemfire.management.internal.cli.GfshParseResult;
+ import com.gemstone.gemfire.management.internal.cli.LogWrapper;
+ import com.gemstone.gemfire.management.internal.cli.functions.CliFunctionResult;
+ import com.gemstone.gemfire.management.internal.cli.functions.ListFunctionFunction;
+ import com.gemstone.gemfire.management.internal.cli.functions.UnregisterFunction;
+ import com.gemstone.gemfire.management.internal.cli.functions.UserFunctionExecution;
+ import com.gemstone.gemfire.management.internal.cli.i18n.CliStrings;
+ import com.gemstone.gemfire.management.internal.cli.result.CommandResultException;
+ import com.gemstone.gemfire.management.internal.cli.result.CompositeResultData;
+ import com.gemstone.gemfire.management.internal.cli.result.ErrorResultData;
+ import com.gemstone.gemfire.management.internal.cli.result.ResultBuilder;
+ import com.gemstone.gemfire.management.internal.cli.result.TabularResultData;
+ import com.gemstone.gemfire.management.internal.cli.shell.Gfsh;
++import com.gemstone.gemfire.management.internal.security.Resource;
++import com.gemstone.gemfire.management.internal.security.ResourceConstants;
++import com.gemstone.gemfire.management.internal.security.ResourceOperation;
+
+ /**
+ * @author David Hoots
+ *
+ * @since 7.0
+ */
+ @SuppressWarnings("unused")
+ public class FunctionCommands implements CommandMarker {
+ private final ListFunctionFunction listFunctionFunction = new ListFunctionFunction();
+
+ private Gfsh getGfsh() {
+ return Gfsh.getCurrentInstance();
+ }
+
+ @CliCommand(value = CliStrings.EXECUTE_FUNCTION, help = CliStrings.EXECUTE_FUNCTION__HELP)
+ @CliMetaData(relatedTopic = { CliStrings.TOPIC_GEMFIRE_FUNCTION })
++ @ResourceOperation(resource = Resource.DISTRIBUTED_SYSTEM, operation= ResourceConstants.EXECUTE_FUNCTION)
+ public Result executeFunction(
+ //TODO: Add optioncontext for functionID
+ @CliOption(key = CliStrings.EXECUTE_FUNCTION__ID,
+ mandatory = true, help = CliStrings.EXECUTE_FUNCTION__ID__HELP) String functionId,
+ @CliOption(key = CliStrings.EXECUTE_FUNCTION__ONGROUPS,
+ unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+ optionContext = ConverterHint.MEMBERGROUP,
+ help = CliStrings.EXECUTE_FUNCTION__ONGROUPS__HELP) String[] onGroups,
+ @CliOption(key = CliStrings.EXECUTE_FUNCTION__ONMEMBER,
+ unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+ optionContext = ConverterHint.MEMBERIDNAME,
+ help = CliStrings.EXECUTE_FUNCTION__ONMEMBER__HELP) String onMember,
+ @CliOption(key = CliStrings.EXECUTE_FUNCTION__ONREGION,
+ unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+ optionContext = ConverterHint.REGIONPATH,
+ help = CliStrings.EXECUTE_FUNCTION__ONREGION__HELP) String onRegion,
+ @CliOption(key = CliStrings.EXECUTE_FUNCTION__ARGUMENTS,
+ unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+ help = CliStrings.EXECUTE_FUNCTION__ARGUMENTS__HELP) String[] arguments,
+ @CliOption(key = CliStrings.EXECUTE_FUNCTION__RESULTCOLLECTOR,
+ unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+ help = CliStrings.EXECUTE_FUNCTION__RESULTCOLLECTOR__HELP) String resultCollector,
+ @CliOption(key = CliStrings.EXECUTE_FUNCTION__FILTER,
+ unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+ help = CliStrings.EXECUTE_FUNCTION__FILTER__HELP) String filterString) {
+
+ Result result = null;
+ CompositeResultData executeFunctionResultTable = ResultBuilder
+ .createCompositeResultData();
+ TabularResultData resultTable = executeFunctionResultTable.addSection().addTable(
+ "Table1");
+ String headerText = "Execution summary";
+ resultTable.setHeader(headerText);
+ ResultCollector resultCollectorInstance = null;
+ Function function;
+ Set<String> filters = new HashSet<String>();
+ Execution execution = null;
+ if (functionId != null){
+ functionId = functionId.trim();
+ }
+ if (onRegion != null){
+ onRegion = onRegion.trim();
+ }
+ if (onMember != null){
+ onMember = onMember.trim();
+ }
+ if (filterString != null){
+ filterString = filterString.trim();
+ }
+
+ try {
+ // validate otherwise return right away. no need to process anything
+ if (functionId == null || functionId.length() == 0) {
+ ErrorResultData errorResultData = ResultBuilder.createErrorResultData()
+ .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT).addLine(
+ CliStrings.EXECUTE_FUNCTION__MSG__MISSING_FUNCTIONID);
+ result = ResultBuilder.buildResult(errorResultData);
+ return result;
+ }
+
+ if (onRegion != null && onMember != null && onGroups != null) {
+ ErrorResultData errorResultData = ResultBuilder.createErrorResultData()
+ .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT).addLine(
+ CliStrings.EXECUTE_FUNCTION__MSG__OPTIONS);
+ result = ResultBuilder.buildResult(errorResultData);
+ return result;
+ } else if (onRegion != null && onMember != null) {
+ ErrorResultData errorResultData = ResultBuilder.createErrorResultData()
+ .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT).addLine(
+ CliStrings.EXECUTE_FUNCTION__MSG__OPTIONS);
+ result = ResultBuilder.buildResult(errorResultData);
+ return result;
+ } else if (onMember != null && onGroups != null) {
+ ErrorResultData errorResultData = ResultBuilder.createErrorResultData()
+ .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT).addLine(
+ CliStrings.EXECUTE_FUNCTION__MSG__OPTIONS);
+ result = ResultBuilder.buildResult(errorResultData);
+ return result;
+ } else if (onRegion != null && onGroups != null) {
+ ErrorResultData errorResultData = ResultBuilder.createErrorResultData()
+ .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT).addLine(
+ CliStrings.EXECUTE_FUNCTION__MSG__OPTIONS);
+ result = ResultBuilder.buildResult(errorResultData);
+ return result;
+ } else if (onRegion != null && onMember != null && onGroups != null) {
+ ErrorResultData errorResultData = ResultBuilder.createErrorResultData()
+ .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT).addLine(
+ CliStrings.EXECUTE_FUNCTION__MSG__OPTIONS);
+ result = ResultBuilder.buildResult(errorResultData);
+ return result;
+ }else if ( (onRegion == null || onRegion.length() == 0) && (filterString != null ) ){
+ ErrorResultData errorResultData = ResultBuilder.createErrorResultData()
+ .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT).addLine(
+ CliStrings.EXECUTE_FUNCTION__MSG__MEMBER_SHOULD_NOT_HAVE_FILTER_FOR_EXECUTION);
+ result = ResultBuilder.buildResult(errorResultData);
+ return result;
+ }
+
+ Cache cache = CacheFactory.getAnyInstance();
+
+
+ if (resultCollector != null) {
+ resultCollectorInstance = (ResultCollector) ClassPathLoader.getLatest().forName(resultCollector).newInstance();
+ }
+
+ if (filterString != null && filterString.length() > 0) {
+ filters.add(filterString);
+ }
+
+ if (onRegion == null && onMember == null && onGroups == null) {
+ // run function on all the members excluding locators bug#46113
+ //if user wish to execute on locator then he can choose --member or --group option
+ Set<DistributedMember> dsMembers = CliUtil.getAllNormalMembers(cache);
+ if (dsMembers.size() > 0) {
+ function = new UserFunctionExecution();
+ LogWrapper.getInstance().info(
+ CliStrings.format(
+ CliStrings.EXECUTE_FUNCTION__MSG__EXECUTING_0_ON_ENTIRE_DS,
+ functionId));
+ for (DistributedMember member : dsMembers) {
+ executeAndGetResults(functionId, filterString, resultCollector,
+ arguments, cache, member, resultTable, onRegion);
+ }
+ return ResultBuilder.buildResult(resultTable);
+ } else {
+ return ResultBuilder
+ .createUserErrorResult(CliStrings.EXECUTE_FUNCTION__MSG__DS_HAS_NO_MEMBERS);
+ }
+ } else if (onRegion != null && onRegion.length() > 0) {
+ if (cache.getRegion(onRegion) == null) {
+ // find a member where region is present
+ DistributedRegionMXBean bean = ManagementService
+ .getManagementService(GemFireCacheImpl.getInstance())
+ .getDistributedRegionMXBean(onRegion);
+ if (bean == null) {
+ bean = ManagementService.getManagementService(
+ GemFireCacheImpl.getInstance()).getDistributedRegionMXBean(Region.SEPARATOR + onRegion);
+
+ if (bean == null) {
+ return ResultBuilder.createGemFireErrorResult(CliStrings.format(
+ CliStrings.EXECUTE_FUNCTION__MSG__MXBEAN_0_FOR_NOT_FOUND,
+ onRegion));
+ }
+ }
+
+ DistributedMember member = null;
+ String[] membersName = bean.getMembers();
+ Set<DistributedMember> dsMembers = CliUtil.getAllMembers(cache);
+ Iterator it = dsMembers.iterator();
+ boolean matchFound = false;
+
+ if (membersName.length > 0) {
+ while (it.hasNext() && matchFound == false) {
+ DistributedMember dsmember = (DistributedMember) it.next();
+ for (String memberName : membersName) {
+ if (MBeanJMXAdapter.getMemberNameOrId(dsmember).equals(
+ memberName)) {
+ member = dsmember;
+ matchFound = true;
+ break;
+ }
+ }
+ }
+ }
+ if (matchFound == true) {
+ executeAndGetResults(functionId, filterString, resultCollector,
+ arguments, cache, member, resultTable, onRegion);
+ return ResultBuilder.buildResult(resultTable);
+ } else {
+ return ResultBuilder.createGemFireErrorResult(CliStrings.format(
+ CliStrings.EXECUTE_FUNCTION__MSG__NO_ASSOCIATED_MEMBER_REGION,
+ " " + onRegion));
+ }
+ } else {
+ execution = FunctionService.onRegion(cache.getRegion(onRegion));
+ if (execution != null) {
+ if (resultCollectorInstance != null) {
+ execution = execution.withCollector(resultCollectorInstance);
+ }
+ if (filters != null && filters.size() > 0) {
+ execution = execution.withFilter(filters);
+ }
+ if (arguments != null && arguments.length > 0) {
+ execution = execution.withArgs(arguments);
+ }
+
+ try {
+ List<Object> results = (List<Object>) execution.execute(
+ functionId).getResult();
+ if (results.size() > 0) {
+ StringBuilder strResult = new StringBuilder();
+ for (Object obj : results) {
+ strResult.append(obj);
+ }
+ toTabularResultData(resultTable, cache.getDistributedSystem()
+ .getDistributedMember().getId(), strResult.toString());
+ }
+ return ResultBuilder.buildResult(resultTable);
+ } catch (FunctionException e) {
+ return ResultBuilder
+ .createGemFireErrorResult(CliStrings
+ .format(
+ CliStrings.EXECUTE_FUNCTION__MSG__ERROR_IN_EXECUTING_0_ON_REGION_1_DETAILS_2,
+ functionId, onRegion, e.getMessage()));
+ }
+ } else {
+ return ResultBuilder
+ .createGemFireErrorResult(CliStrings
+ .format(
+ CliStrings.EXECUTE_FUNCTION__MSG__ERROR_IN_EXECUTING_0_ON_REGION_1_DETAILS_2,
+ functionId,
+ onRegion,
+ CliStrings.EXECUTE_FUNCTION__MSG__ERROR_IN_RETRIEVING_EXECUTOR));
+ }
+ }
+ } else if (onGroups != null) {
+ // execute on group members
+ Set<DistributedMember> dsMembers = new HashSet<DistributedMember>();
+ for(String grp : onGroups){
+ dsMembers.addAll(cache.getDistributedSystem().getGroupMembers(grp));
+ }
+
+ StringBuilder successMessage = new StringBuilder();
+ if (dsMembers.size() > 0) {
+ for (DistributedMember member : dsMembers) {
+ executeAndGetResults(functionId, filterString, resultCollector,
+ arguments, cache, member, resultTable, onRegion);
+ }
+ return ResultBuilder.buildResult(resultTable);
+ } else {
+ StringBuilder grps = new StringBuilder();
+ for(String grp : onGroups){
+ grps.append(grp);
+ grps.append(", ");
+ }
+ return ResultBuilder.createUserErrorResult(CliStrings.format(
+ CliStrings.EXECUTE_FUNCTION__MSG__GROUPS_0_HAS_NO_MEMBERS, grps.toString().substring(0,grps.toString().length() -1)));
+ }
+ } else if (onMember != null && onMember.length() > 0) {
+ DistributedMember member = CliUtil
+ .getDistributedMemberByNameOrId(onMember); // fix for bug 45658
+ if (member != null) {
+ executeAndGetResults(functionId, filterString, resultCollector,
+ arguments, cache, member, resultTable, onRegion);
+ } else {
+ toTabularResultData(resultTable, onMember, CliStrings
+ .format(CliStrings.EXECUTE_FUNCTION__MSG__NO_ASSOCIATED_MEMBER
+ + " " + onMember));
+ }
+ return ResultBuilder.buildResult(resultTable);
+ }
+ } catch (InstantiationException e) {
+ ErrorResultData errorResultData = ResultBuilder.createErrorResultData()
+ .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT)
+ .addLine(e.getMessage());
+ result = ResultBuilder.buildResult(errorResultData);
+ return result;
+ } catch (IllegalAccessException e) {
+ ErrorResultData errorResultData = ResultBuilder.createErrorResultData()
+ .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT)
+ .addLine(e.getMessage());
+ result = ResultBuilder.buildResult(errorResultData);
+ return result;
+ } catch (IllegalArgumentException e) {
+ ErrorResultData errorResultData = ResultBuilder.createErrorResultData()
+ .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT)
+ .addLine(e.getMessage());
+ result = ResultBuilder.buildResult(errorResultData);
+ return result;
+ } catch (SecurityException e) {
+ ErrorResultData errorResultData = ResultBuilder.createErrorResultData()
+ .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT)
+ .addLine(e.getMessage());
+ result = ResultBuilder.buildResult(errorResultData);
+ return result;
+ } catch (Exception e) {
+ ErrorResultData errorResultData = ResultBuilder.createErrorResultData()
+ .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT)
+ .addLine(e.getMessage());
+ result = ResultBuilder.buildResult(errorResultData);
+ return result;
+ }
+
+ return result;
+ }
+
+ DistributedMember getMember(Cache cache, String memberNameOrId) {
+ DistributedMember member = null;
+ Set<DistributedMember> dsMembers = CliUtil.getAllMembers(cache) ;
+ Iterator<DistributedMember> it = dsMembers.iterator();
+ while (it.hasNext()) {
+ DistributedMember tempMember = (DistributedMember) it.next();
+ if (memberNameOrId.equals(tempMember.getId())
+ || memberNameOrId.equals(tempMember.getName())) {
+ return tempMember;
+ }
+ }
+ return member;
+ }
+
+ void executeAndGetResults(String functionId, String filterString,
+ String resultCollector, String[] arguments, Cache cache,
+ DistributedMember member, TabularResultData resultTable, String onRegion) {
+ StringBuilder resultMessege = new StringBuilder();
+ try {
+ Function function = new UserFunctionExecution();
+ Object[] args = new Object[5];
+ args[0] = functionId;
+ if(filterString != null){
+ args[1] = filterString;
+ }
+ if (resultCollector != null) {
+ args[2] = resultCollector;
+ }
+ if (arguments != null && arguments.length > 0) {
+ args[3] = new String();
+ for (String str : arguments) {
+ // send via CSV separated value format
+ if(str != null){
+ args[3] = args[3] + str + ",";
+ }
+ }
+ }
+ args[4] = onRegion;
+
+ Execution execution = FunctionService.onMember(member).withArgs(args);
+ if (execution != null) {
+ List<Object> results = (List<Object>) execution.execute(function)
+ .getResult();
+ if (results != null) {
+ for (Object resultObj : results) {
+ if (resultObj != null) {
+ if (resultObj instanceof String) {
+ resultMessege.append(((String) resultObj));
+ } else if (resultObj instanceof Exception) {
+ resultMessege.append(((Exception)resultObj).getMessage());
+ } else {
+ resultMessege.append(resultObj);
+ }
+ }
+ }
+ }
+ toTabularResultData(resultTable, member.getId(), resultMessege
+ .toString());
+ }else{
+ toTabularResultData(resultTable, member.getId(), CliStrings.EXECUTE_FUNCTION__MSG__ERROR_IN_RETRIEVING_EXECUTOR);
+ }
+ } catch (FunctionException e) {
+ resultMessege.append(CliStrings.format(
+ CliStrings.EXECUTE_FUNCTION__MSG__COULD_NOT_EXECUTE_FUNCTION_0_ON_MEMBER_1_ERROR_2, functionId,
+ member.getId(), e.getMessage()));
+ toTabularResultData(resultTable, member.getId(), resultMessege
+ .toString());
+ } catch (Exception e) {
+ resultMessege.append(CliStrings.format(
+ CliStrings.EXECUTE_FUNCTION__MSG__COULD_NOT_EXECUTE_FUNCTION_0_ON_MEMBER_1_ERROR_2, functionId,
+ member.getId(), e.getMessage()));
+ toTabularResultData(resultTable, member.getId(), resultMessege
+ .toString());
+ }
+ }
+
+ protected void toTabularResultData(TabularResultData table,
+ String memberId, String memberResult) {
+ String newLine = System.getProperty("line.separator");
+ table.accumulate("Member ID/Name", memberId);
+ table.accumulate("Function Execution Result", memberResult);
+ }
+
+ @CliCommand(value = CliStrings.DESTROY_FUNCTION, help = CliStrings.DESTROY_FUNCTION__HELP)
+ @CliMetaData(relatedTopic = { CliStrings.TOPIC_GEMFIRE_FUNCTION } ,
- interceptor = "com.gemstone.gemfire.management.internal.cli.commands.FunctionCommands$Interceptor")
++ interceptor = "com.gemstone.gemfire.management.internal.cli.commands.FunctionCommands$Interceptor")
++ @ResourceOperation(resource = Resource.DISTRIBUTED_SYSTEM, operation= ResourceConstants.DESTROY_FUNCTION)
+ //TODO: Add optioncontext for functionId
+ public Result destroyFunction(
+ @CliOption(key = CliStrings.DESTROY_FUNCTION__ID,
+ mandatory = true, help = CliStrings.DESTROY_FUNCTION__HELP) String functionId,
+ @CliOption(key = CliStrings.DESTROY_FUNCTION__ONGROUPS,
+ unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+ optionContext = ConverterHint.MEMBERGROUP,
+ help = CliStrings.DESTROY_FUNCTION__ONGROUPS__HELP) String[] groups,
+ @CliOption(key = CliStrings.DESTROY_FUNCTION__ONMEMBER,
+ unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE,
+ optionContext = ConverterHint.MEMBERIDNAME,
+ help = CliStrings.DESTROY_FUNCTION__ONMEMBER__HELP) String memberId) {
+ Result result = null;
+ try {
+ Cache cache = CacheFactory.getAnyInstance();
+ Set<DistributedMember> dsMembers = new HashSet<DistributedMember>();
+ if(groups != null && memberId != null){
+ return ResultBuilder.createUserErrorResult(CliStrings.DESTROY_FUNCTION__MSG__PROVIDE_OPTION);
+ }else if (groups != null && groups.length > 0 ) {
+ //execute on group members
+ for(String grp : groups){
+ dsMembers.addAll(cache.getDistributedSystem().getGroupMembers(grp));
+ }
+ @SuppressWarnings("unchecked")
+ Result results = executeFunction(cache, dsMembers, functionId);
+ return results;
+ }else if (memberId != null){
+ //execute on member
+ dsMembers.add(getMember(cache , memberId));
+ @SuppressWarnings("unchecked")
+ Result results = executeFunction(cache, dsMembers, functionId);
+ return results;
+ }
+ else{
+ //no option provided.
+ @SuppressWarnings("unchecked")
+ Result results = executeFunction(cache, cache.getMembers(), functionId);
+ return results;
+ }
+ } catch (Exception e) {
+ ErrorResultData errorResultData = ResultBuilder.createErrorResultData()
+ .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT).addLine(
+ e.getMessage());
+ result = ResultBuilder.buildResult(errorResultData);
+ return result;
+ }
+
+ }
+ /**
+ * Interceptor used by gfsh to intercept execution of destroy.
+ */
+ public static class Interceptor extends AbstractCliAroundInterceptor {
+ @Override
+ public Result preExecution(GfshParseResult parseResult) {
+ Map<String, String> paramValueMap = parseResult.getParamValueStrings();
+ Set< Entry<String, String> > setEnvMap = paramValueMap.entrySet();
+ String onGroup = paramValueMap.get(CliStrings.DESTROY_FUNCTION__ONGROUPS);
+ String onMember = paramValueMap.get(CliStrings.DESTROY_FUNCTION__ONMEMBER);
+
+ if ((onGroup == null && onMember == null ) ){
+ Response response = readYesNo("Do you really want to destroy "+paramValueMap.get(CliStrings.DESTROY_FUNCTION__ID)+ " on entire DS?", Response.NO);
+ if (response == Response.NO) {
+ return ResultBuilder.createShellClientAbortOperationResult("Aborted destroy of " +paramValueMap.get(CliStrings.DESTROY_FUNCTION__ID) );
+ }else{
+ return ResultBuilder.createInfoResult("Destroying " +paramValueMap.get(CliStrings.DESTROY_FUNCTION__ID) );
+ }
+ }else{
+ return ResultBuilder.createInfoResult("Destroying " +paramValueMap.get(CliStrings.DESTROY_FUNCTION__ID) );
+ }
+ }
+
+ @Override
+ public Result postExecution(GfshParseResult parseResult, Result commandResult) {
+ return commandResult;
+ }
+ }
+
+ Result executeFunction(Cache cache, Set<DistributedMember> DsMembers, String functionId){
+ //unregister on a set of of members
+ Function unregisterFunction = new UnregisterFunction();
+ FunctionService.registerFunction(unregisterFunction);
+ List resultList = null;
+
+ if(DsMembers.isEmpty()){
+ return ResultBuilder.createInfoResult("No members for execution");
+ }
+ Object[] obj = new Object[1];
+ obj[0] = functionId;
+
+ Execution execution = FunctionService.onMembers(DsMembers).withArgs(obj);
+
+ if (execution == null) {
+ cache.getLogger().error("executeUnregister execution is null") ;
+ ErrorResultData errorResultData = ResultBuilder.createErrorResultData()
+ .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT).addLine(
+ CliStrings.DESTROY_FUNCTION__MSG__CANNOT_EXECUTE);
+ return (ResultBuilder.buildResult(errorResultData));
+ }
+ try {
+ resultList = (ArrayList) execution.execute(unregisterFunction)
+ .getResult();
+ } catch (FunctionException ex) {
+ ErrorResultData errorResultData = ResultBuilder.createErrorResultData()
+ .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT).addLine(
+ ex.getMessage());
+ return (ResultBuilder.buildResult(errorResultData));
+ }
+ String resultStr = ((String) resultList.get(0));
+ if (resultStr.equals("Succeeded in unregistering")){
+ StringBuilder members = new StringBuilder();
+ for(DistributedMember member : DsMembers){
+ members.append(member.getId());
+ members.append(",");
+ }
+ return ResultBuilder.createInfoResult("Destroyed " + functionId
+ + " Successfully on " + members.toString().substring(0,members.toString().length() -1));
+ }else{
+ return ResultBuilder.createInfoResult("Failed in unregistering");
+ }
+ }
+
+ @CliCommand(value = CliStrings.LIST_FUNCTION, help = CliStrings.LIST_FUNCTION__HELP)
+ @CliMetaData(relatedTopic = { CliStrings.TOPIC_GEMFIRE_FUNCTION })
++ @ResourceOperation(resource = Resource.DISTRIBUTED_SYSTEM, operation= ResourceConstants.LIST_DS)
+ public Result listFunction(
+ @CliOption(key = CliStrings.LIST_FUNCTION__MATCHES,
+ help = CliStrings.LIST_FUNCTION__MATCHES__HELP)String matches,
+ @CliOption(key = CliStrings.LIST_FUNCTION__GROUP,
+ optionContext = ConverterHint.MEMBERGROUP,
+ help = CliStrings.LIST_FUNCTION__GROUP__HELP)
+ @CliMetaData (valueSeparator = ",") String groups,
+ @CliOption(key = CliStrings.LIST_FUNCTION__MEMBER,
+ optionContext = ConverterHint.MEMBERIDNAME,
+ help = CliStrings.LIST_FUNCTION__MEMBER__HELP)
+ @CliMetaData (valueSeparator = ",") String members) {
+ TabularResultData tabularData = ResultBuilder.createTabularResultData();
+ boolean accumulatedData = false;
+
+ Cache cache = CacheFactory.getAnyInstance();
+
+ Set<DistributedMember> targetMembers;
+ try {
+ targetMembers = CliUtil.findAllMatchingMembers(groups, members);
+ } catch (CommandResultException crex) {
+ return crex.getResult();
+ }
+
+ try {
+ ResultCollector<?, ?> rc = CliUtil.executeFunction(this.listFunctionFunction, new Object[] { matches }, targetMembers);
+ List<CliFunctionResult> results = CliFunctionResult.cleanResults((List<?>) rc.getResult());
+
+ for (CliFunctionResult result : results) {
+ if (result.getThrowable() != null) {
+ tabularData.accumulate("Member", result.getMemberIdOrName());
+ tabularData.accumulate("Function", "<ERROR: " + result.getThrowable().getMessage() + ">");
+ accumulatedData = true;
+ tabularData.setStatus(Status.ERROR);
+ } else if (result.isSuccessful()) {
+ String[] strings = (String[]) result.getSerializables();
+ Arrays.sort(strings);
+ for (int i = 0; i < strings.length; i++) {
+ tabularData.accumulate("Member", result.getMemberIdOrName());
+ tabularData.accumulate("Function", strings[i]);
+ accumulatedData = true;
+ }
+ }
+ }
+
+ if (!accumulatedData) {
+ return ResultBuilder.createInfoResult(CliStrings.LIST_FUNCTION__NO_FUNCTIONS_FOUND_ERROR_MESSAGE);
+ }
+ return ResultBuilder.buildResult(tabularData);
+ } catch (VirtualMachineError e) {
+ SystemFailure.initiateFailure(e);
+ throw e;
+ } catch (Throwable th) {
+ SystemFailure.checkFailure();
+ return ResultBuilder.createGemFireErrorResult("Exception while attempting to list functions: " + th.getMessage());
+ }
+ }
+
+ @CliAvailabilityIndicator({CliStrings.EXECUTE_FUNCTION, CliStrings.DESTROY_FUNCTION, CliStrings.LIST_FUNCTION})
+ public boolean functionCommandsAvailable() {
+ boolean isAvailable = true; //always available on server
+ if (CliUtil.isGfshVM()) { //in gfsh check if connected
+ isAvailable = getGfsh() != null && getGfsh().isConnectedAndReady();
+ }
+ return isAvailable;
+ }
+ }
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5c01d5f4/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/GfshHelpCommands.java
----------------------------------------------------------------------
diff --cc geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/GfshHelpCommands.java
index 0000000,24fd117..d946ffb
mode 000000,100644..100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/GfshHelpCommands.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/management/internal/cli/commands/GfshHelpCommands.java
@@@ -1,0 -1,106 +1,111 @@@
+ /*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package com.gemstone.gemfire.management.internal.cli.commands;
+
+ import java.util.Map;
+ import java.util.Map.Entry;
+ import java.util.Set;
+
+ import org.springframework.shell.core.CommandMarker;
+ import org.springframework.shell.core.annotation.CliCommand;
+
+ import com.gemstone.gemfire.management.cli.CliMetaData;
+ import com.gemstone.gemfire.management.cli.ConverterHint;
+ import com.gemstone.gemfire.management.cli.Result;
+ import com.gemstone.gemfire.management.internal.cli.CommandManager;
+ import com.gemstone.gemfire.management.internal.cli.GfshParser;
+ import com.gemstone.gemfire.management.internal.cli.annotation.CliArgument;
+ import com.gemstone.gemfire.management.internal.cli.help.CliTopic;
+ import com.gemstone.gemfire.management.internal.cli.i18n.CliStrings;
+ import com.gemstone.gemfire.management.internal.cli.result.CompositeResultData;
+ import com.gemstone.gemfire.management.internal.cli.result.CompositeResultData.SectionResultData;
+ import com.gemstone.gemfire.management.internal.cli.result.ResultBuilder;
+ import com.gemstone.gemfire.management.internal.cli.shell.Gfsh;
++import com.gemstone.gemfire.management.internal.security.Resource;
++import com.gemstone.gemfire.management.internal.security.ResourceConstants;
++import com.gemstone.gemfire.management.internal.security.ResourceOperation;
+
+ /**
+ *
+ * @author Nikhil Jadhav
+ * @author Abhishek Chaudhari
+ *
+ * @since 7.0
+ */
+ public class GfshHelpCommands implements CommandMarker{
+
+ private Gfsh getGfsh() {
+ return Gfsh.getCurrentInstance();
+ }
+
+ @CliCommand(value = CliStrings.HELP, help = CliStrings.HELP__HELP)
+ @CliMetaData(shellOnly=true, relatedTopic = {CliStrings.TOPIC_GEMFIRE_HELP})
++ @ResourceOperation(resource = Resource.DISTRIBUTED_SYSTEM, operation= ResourceConstants.LIST_DS)
+ public Result obtainHelp(
+ @CliArgument(name = CliStrings.HELP__COMMAND,
+ argumentContext = CliStrings.PARAM_CONTEXT_HELP,
+ help = CliStrings.HELP__COMMAND__HELP)
+ String commandString) {
+ return ResultBuilder.createInfoResult(getGfsh().obtainHelp(commandString, null));
+ }
+
+
+
+ @CliCommand(value = CliStrings.HINT, help = CliStrings.HINT__HELP)
+ @CliMetaData(shellOnly=true, relatedTopic = {CliStrings.TOPIC_GEMFIRE_HELP})
++ @ResourceOperation(resource = Resource.DISTRIBUTED_SYSTEM, operation= ResourceConstants.LIST_DS)
+ public Result hint(
+ @CliArgument(name = CliStrings.HINT__TOPICNAME,
+ argumentContext = ConverterHint.HINTTOPIC,
+ help = CliStrings.HINT__TOPICNAME)
+ String topicName) {
+ Result result = null;
+ CommandManager commandManager = CommandManager.getExisting();
+ if (commandManager == null) {
+ result= ResultBuilder.createShellClientErrorResult(CliStrings.HINT__MSG__SHELL_NOT_INITIALIZED);
+ } else {
+ StringBuilder builder = new StringBuilder();
+ if (topicName == null) {
+ builder.append(CliStrings.HINT__MSG__TOPICS_AVAILABLE).append(GfshParser.LINE_SEPARATOR);
+ Set<String> topicNameSet = commandManager.getTopicNames();
+ for (String topic : topicNameSet) {
+ builder.append(topic).append(GfshParser.LINE_SEPARATOR);
+ }
+ result = ResultBuilder.createInfoResult(builder.toString());
+ } else {
+ CliTopic topic = commandManager.getTopic(topicName);
+ if (topic == null) {
+ result = ResultBuilder.createInfoResult(CliStrings.format(CliStrings.HINT__MSG__UNKNOWN_TOPIC, topicName));
+ } else {
+ CompositeResultData compositeResultData = ResultBuilder.createCompositeResultData();
+ SectionResultData commandHelpSection = compositeResultData.addSection("Commands And Help");
+ compositeResultData.setHeader(topic.getOneLinerDescription());
+ Map<String, String> commandsNameHelp = topic.getCommandsNameHelp();
+ Set<Entry<String, String>> entries = commandsNameHelp.entrySet();
+
+ for (Entry<String, String> entry : entries) {
+ commandHelpSection.addData(entry.getKey(), entry.getValue());
+ }
+
+ result = ResultBuilder.buildResult(compositeResultData);
+ }
+ }
+ }
+
+ return result;
+ }
+ }