/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.management.internal.cli.commands; import 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.apache.geode.SystemFailure; import org.apache.geode.cache.Cache; import org.apache.geode.cache.CacheFactory; import org.apache.geode.cache.Region; import org.apache.geode.cache.execute.Execution; import org.apache.geode.cache.execute.Function; import org.apache.geode.cache.execute.FunctionException; import org.apache.geode.cache.execute.FunctionService; import org.apache.geode.cache.execute.ResultCollector; import org.apache.geode.distributed.DistributedMember; import org.apache.geode.internal.ClassPathLoader; import org.apache.geode.internal.cache.GemFireCacheImpl; import org.apache.geode.management.DistributedRegionMXBean; import org.apache.geode.management.ManagementService; 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.cli.Result.Status; import org.apache.geode.management.internal.MBeanJMXAdapter; import org.apache.geode.management.internal.cli.AbstractCliAroundInterceptor; import org.apache.geode.management.internal.cli.CliUtil; import org.apache.geode.management.internal.cli.GfshParseResult; import org.apache.geode.management.internal.cli.LogWrapper; import org.apache.geode.management.internal.cli.functions.CliFunctionResult; import org.apache.geode.management.internal.cli.functions.ListFunctionFunction; import org.apache.geode.management.internal.cli.functions.UnregisterFunction; import org.apache.geode.management.internal.cli.functions.UserFunctionExecution; import org.apache.geode.management.internal.cli.i18n.CliStrings; import org.apache.geode.management.internal.cli.result.CommandResultException; import org.apache.geode.management.internal.cli.result.CompositeResultData; import org.apache.geode.management.internal.cli.result.ErrorResultData; 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.shell.Gfsh; import org.apache.geode.management.internal.security.ResourceOperation; import org.apache.geode.security.ResourcePermission.Operation; import org.apache.geode.security.ResourcePermission.Resource; 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; /** * * @since GemFire 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_GEODE_FUNCTION}) @ResourceOperation(resource = Resource.DATA, operation = Operation.WRITE) 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_GEODE_FUNCTION}, interceptor = "org.apache.geode.management.internal.cli.commands.FunctionCommands$Interceptor") @ResourceOperation(resource = Resource.DATA, operation = Operation.MANAGE) // 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_GEODE_FUNCTION}) @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ) 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.findMembersOrThrow(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; } }