/*
 * 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.admin.jmx.internal;

import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_TIME_STATISTICS;
import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_SAMPLING_ENABLED;

import java.net.InetAddress;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicLong;

import javax.management.InstanceNotFoundException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationEmitter;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.OperationsException;
import javax.management.ReflectionException;

import mx4j.AbstractDynamicMBean;
import org.apache.logging.log4j.Logger;

import org.apache.geode.admin.AdminDistributedSystem;
import org.apache.geode.admin.AdminException;
import org.apache.geode.admin.CacheVm;
import org.apache.geode.admin.ConfigurationParameter;
import org.apache.geode.admin.GemFireMemberStatus;
import org.apache.geode.admin.RegionSubRegionSnapshot;
import org.apache.geode.admin.StatisticResource;
import org.apache.geode.admin.SystemMember;
import org.apache.geode.admin.SystemMemberCacheServer;
import org.apache.geode.admin.jmx.Agent;
import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.cache.InterestPolicy;
import org.apache.geode.cache.SubscriptionAttributes;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.internal.GemFireVersion;
import org.apache.geode.internal.admin.remote.ClientHealthStats;
import org.apache.geode.logging.internal.log4j.api.LogService;

/**
 * This class uses the JMX Attributes/Operations that use (return/throw) GemFire types. This is the
 * single MBean accessible with ObjectName string {@link MemberInfoWithStatsMBean#MBEAN_NAME}}. This
 * MBean can be used to retrieve the all member details as plain java types.
 *
 * This MBean also acts as a Notification Hub for all the Notifications that are defined for Admin
 * Distributed System.
 *
 *
 * @since GemFire 6.5
 */
public class MemberInfoWithStatsMBean extends AbstractDynamicMBean implements NotificationEmitter {
  private static final Logger logger = LogService.getLogger();

  /* constants defining max no of attributes/operations/notifications */
  private static final int MAX_ATTRIBUTES_COUNT = 3;
  private static final int MAX_OPERATIONS_COUNT = 3;
  private static final int MAX_NOTIFICATIONS_COUNT = 9;

  private static final String NOT_AVAILABLE_STR = "N/A";
  private static final String NOT_AVAILABLE = null;
  private static final Number NOT_AVAILABLE_NUMBER = null;

  /*
   * String constant used for a region that is used on admin side just as a root for rootRegions
   * defined on the member
   */
  private static final String PLACE_HOLDER_ROOT_REGION = "/Root/";

  /* String that are used to form QueryExp/ObjectName for querying MBeanServer */
  private static final String REGION_QUERY_EXPRESSION = "*GemFire.Cache*:*,owner={0},type=Region";
  private static final String STATS_QUERY_EXPRESSION = "*GemFire.Statistic*:*,source={0},name={1}";

  /** mbean name string for this MBean */
  /* default */static final String MBEAN_NAME = "GemFire:type=MemberInfoWithStatsMBean";

  /** ObjectName handle for this MBean */
  private ObjectName objectName;

  /** version of the GemFire Enterprise system that is running */
  private String version;
  private int refreshInterval;
  private String id;

  private Agent agent;
  private AdminDistributedSystemJmxImpl adminDSJmx;

  private NotificationForwarder forwarder;
  private boolean isInitialized;// needs synchronization?

  /**
   * Default Constructor
   *
   * @param agent Admin Agent instance
   * @throws OperationsException if ObjectName can't be formed for this MBean
   */
  MemberInfoWithStatsMBean(Agent agent)
      throws OperationsException, MBeanRegistrationException, AdminException {
    this.agent = agent;
    this.objectName = ObjectName.getInstance(MBEAN_NAME);
    this.version = GemFireVersion.getGemFireVersion();
    this.refreshInterval = -1;
    this.id = NOT_AVAILABLE_STR;
    this.forwarder = new NotificationForwarder(agent.getMBeanServer());
  }

  /**
   * Returns attributes defined for this MBean as an array of MBeanAttributeInfo objects.
   *
   * @return attributes defined as an array of MBeanAttributeInfo objects.
   */
  @Override
  protected MBeanAttributeInfo[] createMBeanAttributeInfo() {
    MBeanAttributeInfo[] attributesInfo = new MBeanAttributeInfo[MAX_ATTRIBUTES_COUNT];

    /*
     * First letter in attribute name has to be 'V' so that getVersion is called. With 'v' it looks
     * for getversion, same for others
     */
    attributesInfo[0] = new MBeanAttributeInfo("Version", String.class.getName(),
        "GemFire Enterprise Version", true, /* readable */
        false, /* writable */
        false);/* has getter with name like 'is****' */

    attributesInfo[1] = new MBeanAttributeInfo("RefreshInterval", String.class.getName(),
        "The interval (in seconds) between auto-polling for updating member & statistics resources. If this is '-1', it means the this MBean has not yet been initialized. First call to getMembers operation will initialize this MBean.",
        true, /* readable */
        false, /* writable */
        false);/* has getter with name like 'is****' */

    attributesInfo[2] = new MBeanAttributeInfo("Id", String.class.getName(),
        "Identifier of the GemFire Enterprise. If this is 'N/A', it means the this MBean has not yet been initialized. First call to getMembers operation will initialize this MBean.",
        true, /* readable */
        false, /* writable */
        false);/* has getter with name like 'is****' */


    return attributesInfo;
  }

  /**
   * Returns operations defined for this MBean as an array of MBeanOperationInfo objects.
   *
   * @return operations defined as an array of MBeanOperationInfo objects.
   */
  @Override
  protected MBeanOperationInfo[] createMBeanOperationInfo() {
    MBeanOperationInfo[] operationsInfo = new MBeanOperationInfo[MAX_OPERATIONS_COUNT];

    operationsInfo[0] = new MBeanOperationInfo("getMembers",
        "Returns ids as strings for all the members - Application Peers & Cache Servers.",
        new MBeanParameterInfo[] {}, String[].class.getName(), MBeanOperationInfo.ACTION_INFO);

    MBeanParameterInfo[] getMemberDetailsArgs = new MBeanParameterInfo[1];
    getMemberDetailsArgs[0] = new MBeanParameterInfo("memberId", String.class.getName(),
        "Id of the member for all the details are to be retrieved.");
    operationsInfo[1] =
        new MBeanOperationInfo("getMemberDetails", "Returns details for a given member",
            getMemberDetailsArgs, Map.class.getName(), MBeanOperationInfo.ACTION_INFO);

    /*
     * For retrieving ObjectNames of existing Region MBeans, MBeanServerConnection.queryMBeans(),
     * could be called
     */
    MBeanParameterInfo[] getRegionSnapArgs = new MBeanParameterInfo[1];
    getRegionSnapArgs[0] = new MBeanParameterInfo("memberId", String.class.getName(),
        "Id of the member on which we want to discover all the region MBean.");
    operationsInfo[2] = new MBeanOperationInfo("getRegions",
        "Returns a java.util.Map of details of regions on a member", getRegionSnapArgs,
        Map.class.getName(), MBeanOperationInfo.ACTION_INFO);


    return operationsInfo;
  }

  /**
   * Returns notifications defined for this MBean as an array of MBeanNotificationInfo objects.
   *
   * @return notification definitions as an array of MBeanNotificationInfo objects.
   */
  @Override
  protected MBeanNotificationInfo[] createMBeanNotificationInfo() {
    MBeanNotificationInfo[] notificationsInfo = new MBeanNotificationInfo[MAX_NOTIFICATIONS_COUNT];

    String[] notificationTypes = new String[] {AdminDistributedSystemJmxImpl.NOTIF_MEMBER_JOINED};
    notificationsInfo[0] =
        new MBeanNotificationInfo(notificationTypes, Notification.class.getName(),
            "A GemFire manager, cache, or other member has joined this distributed system.");

    notificationTypes = new String[] {AdminDistributedSystemJmxImpl.NOTIF_MEMBER_LEFT};
    notificationsInfo[1] =
        new MBeanNotificationInfo(notificationTypes, Notification.class.getName(),
            "A GemFire manager, cache, or other member has left the distributed system.");

    notificationTypes = new String[] {AdminDistributedSystemJmxImpl.NOTIF_MEMBER_CRASHED};
    notificationsInfo[2] =
        new MBeanNotificationInfo(notificationTypes, Notification.class.getName(),
            "A member of this distributed system has crashed instead of leaving cleanly.");

    notificationTypes = new String[] {AdminDistributedSystemJmxImpl.NOTIF_ALERT};
    notificationsInfo[3] =
        new MBeanNotificationInfo(notificationTypes, Notification.class.getName(),
            "A member of this distributed system has generated an alert.");

    notificationTypes = new String[] {AdminDistributedSystemJmxImpl.NOTIF_ADMIN_SYSTEM_DISCONNECT};
    notificationsInfo[4] =
        new MBeanNotificationInfo(notificationTypes, Notification.class.getName(),
            "A GemFire manager, cache, or other member has joined this distributed system.");

    notificationTypes = new String[] {SystemMemberJmx.NOTIF_CACHE_CREATED};
    notificationsInfo[5] =
        new MBeanNotificationInfo(notificationTypes, Notification.class.getName(),
            "A cache got created on a member of this distributed system.");

    notificationTypes = new String[] {SystemMemberJmx.NOTIF_CACHE_CLOSED};
    notificationsInfo[6] = new MBeanNotificationInfo(notificationTypes,
        Notification.class.getName(), "A cache is closed on a member of this distributed system.");

    notificationTypes = new String[] {SystemMemberJmx.NOTIF_REGION_CREATED};
    notificationsInfo[7] =
        new MBeanNotificationInfo(notificationTypes, Notification.class.getName(),
            "A region is created in a cache on a member of this distributed system.");

    notificationTypes = new String[] {SystemMemberJmx.NOTIF_REGION_LOST};
    notificationsInfo[8] =
        new MBeanNotificationInfo(notificationTypes, Notification.class.getName(),
            "A region was removed from a cache on a member of this distributed system.");

    return notificationsInfo;
  }

  /**
   *
   * @return ObjectName of this MBean
   */
  /* default */ ObjectName getObjectName() {
    return objectName;
  }

  /**
   * Returns the version of the GemFire Enterprise instance as a string.
   *
   * @return GemFire Enterprise version string derived from {@link GemFireVersion}
   */
  /* getter for attribute - Version */
  public String getVersion() {
    return version;
  }

  /**
   * @return the refreshInterval
   */
  public int getRefreshInterval() {
    return refreshInterval;
  }

  /**
   * @return the id
   */
  public String getId() {
    return id;
  }

  /**
   * Connects the Admin Agent in the DS
   *
   * @return AdminDistributedSystem MBean ObjectName
   * @throws OperationsException if connection to the DS fails
   * @throws AdminException if connection to the DS fails
   */
  private ObjectName connectToSystem() throws OperationsException, AdminException {
    ObjectName adminDsObjName = agent.connectToSystem();

    AdminDistributedSystem adminDS = agent.getDistributedSystem();
    if (adminDSJmx == null && adminDS instanceof AdminDistributedSystemJmxImpl) {// instanceof
                                                                                 // checks for null
      adminDSJmx = (AdminDistributedSystemJmxImpl) adminDS;
      refreshInterval = adminDSJmx.getRefreshInterval();
      id = adminDSJmx.getId();
      forwarder.registerNotificationListener(adminDSJmx.getObjectName());
    }

    return adminDsObjName;
  }

  /**
   *
   * @return SystemMemberJmx instance for given memberId
   */
  private SystemMemberJmx findMember(String memberId) throws AdminException {
    SystemMemberJmx foundMember = null;

    if (agent.isConnected()) {
      SystemMember[] members = adminDSJmx.getSystemMemberApplications();
      for (SystemMember app : members) {
        if (app.getId().equals(memberId)) {
          foundMember = (SystemMemberJmx) app;
          break;
        }
      }

      if (foundMember == null) {
        members = adminDSJmx.getCacheVms();
        for (SystemMember cacheVm : members) {
          if (cacheVm.getId().equals(memberId)) {
            foundMember = (SystemMemberJmx) cacheVm;
            break;
          }
        }
      }
    }

    return foundMember;
  }

  /**
   * Return ObjectNames for all the Member MBeans in the DS.
   *
   * @return Array of ObjectNames of all Member MBeans
   * @throws OperationsException if (1)agent could not connect in the DS OR (2)Notification Listener
   *         could not be registered for the Admin DS MBean OR (3)fails to retrieve information from
   *         Admin DS
   */
  public String[] getMembers() throws OperationsException {
    String[] members = new String[0];

    try {
      if (!isInitialized) {
        initializeAll(); // initialize if not yet
      }

      if (adminDSJmx != null) {
        CacheVm[] cacheVms = adminDSJmx.getCacheVms();
        SystemMember[] appVms = adminDSJmx.getSystemMemberApplications();

        List<String> membersList = new ArrayList<String>();
        if (cacheVms != null && cacheVms.length != 0) {
          for (SystemMember cacheVm : cacheVms) {
            membersList.add(cacheVm.getId());
          }
        }
        if (appVms != null && appVms.length != 0) {
          for (SystemMember appVm : appVms) {
            membersList.add(appVm.getId());
          }
        }
        members = new String[membersList.size()];
        members = membersList.toArray(members);
      }
    } catch (AdminException e) {
      logger.warn("Exception occurred for operation: getMembers",
          e);
      throw new OperationsException(e.getMessage());
    } catch (Exception e) {
      logger.warn(
          "Exception occurred for operation: getMembers",
          e);
      throw new OperationsException(e.getMessage());
    }

    return members;
  }

  /**
   * Returns information including ObjectNames for all regions on a member with given member id.
   *
   * @param memberId member identifier as a String
   * @return Map of details of all regions on a member with given id
   * @throws OperationsException if fails to retrieve the regions information
   */
  public Map<String, Map<String, ?>> getRegions(String memberId) throws OperationsException {
    Map<String, Map<String, ?>> regionsInfo = new LinkedHashMap<String, Map<String, ?>>();

    if (memberId != null) {
      try {
        SystemMemberJmx foundMember = findMember(memberId);
        if (foundMember != null) {
          SystemMemberCacheJmxImpl cache = (SystemMemberCacheJmxImpl) foundMember.getCache();
          if (cache != null) {
            Map<String, ObjectName> existingRegionMbeans =
                getExistingRegionMbeansFullPaths(memberId);
            // TODO: this is in-efficient
            // Can a region.create JMX notification be used?
            regionsInfo = getAllRegionsDetails(cache, existingRegionMbeans);
            existingRegionMbeans.clear();
          }
        }
      } catch (AdminException e) {
        logger.warn(String.format("Exception occurred for operation: %s for member: %s",
            new Object[] {"getRegions", memberId}),
            e);
        throw new OperationsException(e.getMessage());
      } catch (Exception e) {
        logger.warn(String.format("Exception occurred for operation: %s for member: %s",
            new Object[] {"getRegions", memberId}),
            e);
        throw new OperationsException(e.getMessage());
      }
    }

    return regionsInfo;
  }

  /* **************************************************************************/
  /* ************* INITIALIZE THE ENTIRE ADMIN DS AT A TIME *******************/
  /* **************************************************************************/
  /**
   * Initializes all the possible MBeans for all the members.
   *
   */
  private void initializeAll() throws OperationsException {
    try {
      connectToSystem();
      if (adminDSJmx != null) {
        // Members are already inited after connectToSystem. Now init Cache, Region & Stats MBeans
        SystemMember[] cacheVms = adminDSJmx.getCacheVms();
        for (int i = 0; i < cacheVms.length; i++) {
          try {
            initializeCacheRegionsAndStats((SystemMemberJmx) cacheVms[i]);
          } catch (AdminException e) {
            logger.info(String.format(
                "Exception occurred while intializing : %s. Contiuning with next  ...",
                cacheVms[i].getId()),
                e);
          }
        }
        SystemMember[] appVms = adminDSJmx.getSystemMemberApplications();
        for (int i = 0; i < appVms.length; i++) {
          try {
            initializeCacheRegionsAndStats((SystemMemberJmx) appVms[i]);
          } catch (AdminException e) {
            logger.info(String.format(
                "Exception occurred while intializing : %s. Contiuning with next  ...",
                appVms[i].getId()),
                e);
          }
        }
      }
    } catch (AdminException e) {
      logger.warn("Exception occurred while intializing.", e);
      throw new OperationsException(e.getMessage());
    } catch (Exception e) {
      logger.warn("Exception occurred while intializing.", e);
      throw new OperationsException(e.getMessage());
    }

    isInitialized = true;
  }

  /**
   * Initializes Cache, Regions & Statistics Types MBeans for the given Member.
   *
   * @param memberJmx Member Mbean instance
   * @throws OperationsException if fails to initialize required MBeans
   * @throws AdminException if fails to initialize required MBeans
   */
  private void initializeCacheRegionsAndStats(SystemMemberJmx memberJmx)
      throws OperationsException, AdminException {
    if (memberJmx != null) {
      SystemMemberCacheJmxImpl cache = (SystemMemberCacheJmxImpl) memberJmx.getCache();
      if (cache != null) {
        RegionSubRegionSnapshot regionSnapshot = cache.getRegionSnapshot();
        initializeRegionSubRegions(cache, regionSnapshot);
      }
      initStats(memberJmx);
    }
  }

  /**
   * Initializes statistics for a member with the given mbean.
   *
   * @param memberJmx Member Mbean instance
   * @throws AdminException if fails to initialize required statistic MBeans
   */
  private void initStats(SystemMemberJmx memberJmx) throws AdminException {
    StatisticResource[] statResources = memberJmx.getStats();
    for (StatisticResource statResource : statResources) {
      statResource.getStatistics();
    }
  }

  /**
   * Initializes all regions & its subregions using the Cache MBean and the RegionSubRegionSnapshot
   * for this cache MBean.
   *
   * @param cache Cache MBean resource
   * @param regionSnapshot RegionSubRegionSnapshot instance for the cache
   * @throws MalformedObjectNameException if fails to initialize the region MBean
   * @throws AdminException if fails to initialize the region MBean
   */
  @SuppressWarnings("rawtypes")
  private void initializeRegionSubRegions(SystemMemberCacheJmxImpl cache,
      RegionSubRegionSnapshot regionSnapshot) throws MalformedObjectNameException, AdminException {
    String fullPath = regionSnapshot.getFullPath();
    if (!fullPath.equals(PLACE_HOLDER_ROOT_REGION)) {
      fullPath = fullPath.substring(PLACE_HOLDER_ROOT_REGION.length() - 1);

      cache.manageRegion(fullPath);
    }

    Set subRegionSnapshots = regionSnapshot.getSubRegionSnapshots();

    for (Iterator iterator = subRegionSnapshots.iterator(); iterator.hasNext();) {
      RegionSubRegionSnapshot subRegion = (RegionSubRegionSnapshot) iterator.next();
      try {
        initializeRegionSubRegions(cache, subRegion);
      } catch (AdminException e) {
        logger.info(
            String.format("Exception occurred while intializing : %s. Contiuning with next  ...",
                subRegion.getFullPath()),
            e);
      }
    }
  }


  /* **************************************************************************/
  /* ********************** EVERYTHING HYPERIC NEEDS **************************/
  /* **************************************************************************/

  /* constants defined that could be used simply retrieve needed info from Map */
  private static final String TYPE_NAME_CACHESERVER = "Cache Server";
  private static final String TYPE_NAME_APPLICATION = "Application Peer";
  /*
   * NOTE - (My Understanding about the followings - abhishek) 1. CacheVM - a VM started using Cache
   * Server Launcher. This is considered to be a dedicated cache VM because there is only GemFire
   * Cache code running here. 2. ApplicationVM - a VM started with a written code using APIs and we
   * can not guarantee that there will be ONLY GemFire code running in this VM. 3. Cache Server -
   * Responsible for serving requests from the clients. There could be multiple of these per Cache
   * and hence per VM - one of 1 or 2 above. These could be specified by <cache-server> (or
   * deprecated <bridge-server>) element(s) in the cache-xml file or using an API
   * Cache.addCacheServer().
   */

  private static final String MEMBER_ID = DistributionConfig.GEMFIRE_PREFIX + "member.id.string";
  private static final String MEMBER_NAME =
      DistributionConfig.GEMFIRE_PREFIX + "member.name.string";
  private static final String MEMBER_HOST =
      DistributionConfig.GEMFIRE_PREFIX + "member.host.string";
  private static final String MEMBER_PORT = DistributionConfig.GEMFIRE_PREFIX + "member.port.int";
  private static final String MEMBER_UPTIME =
      DistributionConfig.GEMFIRE_PREFIX + "member.uptime.long";
  private static final String MEMBER_CLIENTS =
      DistributionConfig.GEMFIRE_PREFIX + "member.clients.map";
  private static final String MEMBER_REGIONS =
      DistributionConfig.GEMFIRE_PREFIX + "member.regions.map";
  private static final String MEMBER_TYPE =
      DistributionConfig.GEMFIRE_PREFIX + "member.type.string";
  private static final String IS_SERVER =
      DistributionConfig.GEMFIRE_PREFIX + "member.isserver.boolean";
  private static final String IS_GATEWAY =
      DistributionConfig.GEMFIRE_PREFIX + "member.isgateway.boolean";

  private static final String MEMBER_STATSAMPLING_ENABLED =
      DistributionConfig.GEMFIRE_PREFIX + "member.config.statsamplingenabled.boolean";
  private static final String MEMBER_TIME_STATS_ENABLED =
      DistributionConfig.GEMFIRE_PREFIX + "member.config.timestatsenabled.boolean";

  private static final String STATS_PROCESSCPUTIME =
      DistributionConfig.GEMFIRE_PREFIX + "member.stat.processcputime.long";
  private static final String STATS_CPUS =
      DistributionConfig.GEMFIRE_PREFIX + "member.stat.cpus.int";
  private static final String STATS_USEDMEMORY =
      DistributionConfig.GEMFIRE_PREFIX + "member.stat.usedmemory.long";
  private static final String STATS_MAXMEMORY =
      DistributionConfig.GEMFIRE_PREFIX + "member.stat.maxmemory.long";
  private static final String STATS_GETS =
      DistributionConfig.GEMFIRE_PREFIX + "member.stat.gets.int";
  private static final String STATS_GETTIME =
      DistributionConfig.GEMFIRE_PREFIX + "member.stat.gettime.long";
  private static final String STATS_PUTS =
      DistributionConfig.GEMFIRE_PREFIX + "member.stat.puts.int";
  private static final String STATS_PUTTIME =
      DistributionConfig.GEMFIRE_PREFIX + "member.stat.puttime.long";

  private static final String REGION_NAME =
      DistributionConfig.GEMFIRE_PREFIX + "region.name.string";
  private static final String REGION_PATH =
      DistributionConfig.GEMFIRE_PREFIX + "region.path.string";
  private static final String REGION_SCOPE =
      DistributionConfig.GEMFIRE_PREFIX + "region.scope.string";
  private static final String REGION_DATAPOLICY =
      DistributionConfig.GEMFIRE_PREFIX + "region.datapolicy.string";
  private static final String REGION_INTERESTPOLICY =
      DistributionConfig.GEMFIRE_PREFIX + "region.interestpolicy.string";
  private static final String REGION_ENTRYCOUNT =
      DistributionConfig.GEMFIRE_PREFIX + "region.entrycount.int";
  private static final String REGION_DISKATTRS =
      DistributionConfig.GEMFIRE_PREFIX + "region.diskattrs.string";

  private static final String CLIENT_ID = DistributionConfig.GEMFIRE_PREFIX + "client.id.string";
  private static final String CLIENT_NAME =
      DistributionConfig.GEMFIRE_PREFIX + "client.name.string";
  private static final String CLIENT_HOST =
      DistributionConfig.GEMFIRE_PREFIX + "client.host.string";
  private static final String CLIENT_QUEUESIZE =
      DistributionConfig.GEMFIRE_PREFIX + "client.queuesize.int";
  private static final String CLIENT_STATS_GETS =
      DistributionConfig.GEMFIRE_PREFIX + "client.stats.gets.int";
  private static final String CLIENT_STATS_PUTS =
      DistributionConfig.GEMFIRE_PREFIX + "client.stats.puts.int";
  private static final String CLIENT_STATS_CACHEMISSES =
      DistributionConfig.GEMFIRE_PREFIX + "client.stats.cachemisses.int";
  private static final String CLIENT_STATS_CPUUSAGE =
      DistributionConfig.GEMFIRE_PREFIX + "client.stats.cpuusage.long";
  private static final String CLIENT_STATS_CPUS =
      DistributionConfig.GEMFIRE_PREFIX + "client.stats.cpus.int";
  private static final String CLIENT_STATS_UPDATETIME =
      DistributionConfig.GEMFIRE_PREFIX + "client.stats.updatetime.long";
  private static final String CLIENT_STATS_THREADS =
      DistributionConfig.GEMFIRE_PREFIX + "client.stats.threads.int";

  /**
   *
   * @return All the required details for a member with given memberId
   */
  public Map<String, Object> getMemberDetails(String memberId) throws OperationsException {
    Map<String, Object> allDetails = new TreeMap<String, Object>();

    if (memberId != null) {
      try {
        SystemMemberJmx member = findMember(memberId);
        if (member != null) {
          SystemMemberCacheJmxImpl cache = (SystemMemberCacheJmxImpl) member.getCache();
          GemFireMemberStatus snapshot = cache.getSnapshot();
          boolean isServer = snapshot.getIsServer();
          boolean isGatewayHub = snapshot.getIsGatewayHub();

          // 1. Member info
          allDetails.put(MEMBER_ID, member.getId());
          allDetails.put(MEMBER_NAME, member.getName());
          String host = member.getHost();// from of GemFireVM.getHost
          InetAddress hostAddr = member.getHostAddress();
          // possibility of null host address
          if (hostAddr != null) {
            host = hostAddr.getHostName();
          }
          allDetails.put(MEMBER_HOST, host);
          allDetails.put(MEMBER_UPTIME, snapshot.getUpTime());
          allDetails.put(IS_SERVER, isServer);
          allDetails.put(IS_GATEWAY, isGatewayHub);

          String memberType = "";
          if (member instanceof CacheServerJmxImpl) {
            memberType = TYPE_NAME_CACHESERVER;
          } else {// Mark it of Application type if neither a gateway hub nor a server
            memberType = TYPE_NAME_APPLICATION;
          }
          allDetails.put(MEMBER_TYPE, memberType);

          // 2. Region info
          Map<String, ObjectName> existingRegionMbeans = getExistingRegionMbeansFullPaths(memberId);
          allDetails.put(MEMBER_REGIONS, getAllRegionsDetails(cache, existingRegionMbeans));
          existingRegionMbeans.clear();

          // 3. Clients info
          allDetails.put(MEMBER_CLIENTS, getClientDetails(snapshot));

          boolean statSamplingEnabled = true;
          // assuming will never return as per current implementation
          ConfigurationParameter[] configParams = member.getConfiguration();
          for (ConfigurationParameter configParam : configParams) {
            if (STATISTIC_SAMPLING_ENABLED.equals(configParam.getName())) {
              allDetails.put(MEMBER_STATSAMPLING_ENABLED, configParam.getValue());
              statSamplingEnabled = Boolean.parseBoolean("" + configParam.getValue());
            } else if (ENABLE_TIME_STATISTICS.equals(configParam.getName())) {
              allDetails.put(MEMBER_TIME_STATS_ENABLED, configParam.getValue());
            }
          }

          // 5. Stats info
          allDetails.putAll(getRequiredStats(member, statSamplingEnabled));

          SystemMemberCacheServer[] cacheServers = cache.getCacheServers();
          // attempt refreshing the cache info once
          if (cacheServers.length == 0) {
            cache.refresh();
            cacheServers = cache.getCacheServers();
          }
          Integer memberCacheServerPort = Integer.valueOf(0);
          if (cacheServers.length != 0) {
            /*
             * Taking the first cache server port. We don't recommend multiple cache severs for a
             * cache.
             */
            memberCacheServerPort = Integer.valueOf(cacheServers[0].getPort());
          }
          allDetails.put(MEMBER_PORT, memberCacheServerPort);
        }

      } catch (AdminException e) {
        logger.warn(String.format("Exception occurred for operation: %s for member: %s",
            new Object[] {"getMemberDetails", memberId}),
            e);
        throw new OperationsException(e.getMessage());
      } catch (Exception e) {
        logger.warn(String.format("Exception occurred for operation: %s for member: %s",
            new Object[] {"getMemberDetails", memberId}),
            e);
        throw new OperationsException(e.getMessage());
      }
    }

    return allDetails;
  }

  /**
   *
   * @return Map of client details
   */
  @SuppressWarnings("rawtypes")
  private Map<String, Map<String, ?>> getClientDetails(GemFireMemberStatus snapshot) {
    Map<String, Map<String, ?>> clientsInfo = new LinkedHashMap<String, Map<String, ?>>();

    Set connectedClients = snapshot.getConnectedClients();
    if (!connectedClients.isEmpty()) {
      Map clientHealthStatsMap = snapshot.getClientHealthStats();

      for (Iterator iterator = connectedClients.iterator(); iterator.hasNext();) {
        Map<String, Object> clientData = new HashMap<String, Object>();
        String clientId = (String) iterator.next();
        String host = snapshot.getClientHostName(clientId);
        clientData.put(CLIENT_ID, clientId);
        clientData.put(CLIENT_NAME, extractClientName(clientId, host));
        clientData.put(CLIENT_HOST, host);
        clientData.put(CLIENT_QUEUESIZE, snapshot.getClientQueueSize(clientId));

        ClientHealthStats clientHealthStats =
            (ClientHealthStats) clientHealthStatsMap.get(clientId);
        if (clientHealthStats != null) {
          clientData.put(CLIENT_STATS_GETS, clientHealthStats.getNumOfGets());
          clientData.put(CLIENT_STATS_PUTS, clientHealthStats.getNumOfPuts());
          clientData.put(CLIENT_STATS_CACHEMISSES, clientHealthStats.getNumOfMisses());
          clientData.put(CLIENT_STATS_CPUUSAGE, clientHealthStats.getProcessCpuTime());
          clientData.put(CLIENT_STATS_CPUS, clientHealthStats.getCpus());
          clientData.put(CLIENT_STATS_UPDATETIME, clientHealthStats.getUpdateTime().getTime());
          clientData.put(CLIENT_STATS_THREADS, clientHealthStats.getNumOfThreads());
        } else {
          clientData.put(CLIENT_STATS_GETS, Integer.valueOf(0));
          clientData.put(CLIENT_STATS_PUTS, Integer.valueOf(0));
          clientData.put(CLIENT_STATS_CACHEMISSES, Integer.valueOf(0));
          clientData.put(CLIENT_STATS_CPUUSAGE, Long.valueOf(0));
          clientData.put(CLIENT_STATS_CPUS, Integer.valueOf(0));
          clientData.put(CLIENT_STATS_UPDATETIME, Long.valueOf(0));
          clientData.put(CLIENT_STATS_THREADS, Integer.valueOf(0));
        }

        clientsInfo.put(clientId, clientData);
      }
    }

    return clientsInfo;
  }

  /**
   * Returns a Map containing information about regions.
   *
   * @param cache Reference to an MBean representing a Cache on a member
   * @param existingRegionMbeans Map of Path against Region MBean ObjectNames
   * @return Map of all region details
   * @throws OperationsException if fails to retrieve
   */
  private Map<String, Map<String, ?>> getAllRegionsDetails(SystemMemberCacheJmxImpl cache,
      Map<String, ObjectName> existingRegionMbeans) throws OperationsException {
    Map<String, Map<String, ?>> regionsInfo = new TreeMap<String, Map<String, ?>>();

    if (cache != null) {
      try {
        RegionSubRegionSnapshot regionSnapshot = cache.getRegionSnapshot();
        collectAllRegionsDetails(cache, regionSnapshot, regionsInfo, existingRegionMbeans);
      } catch (AdminException e) {
        logger.warn("Exception occurred while getting region details.", e);
        throw new OperationsException(e.getMessage());
      } catch (Exception e) {
        logger.warn("Exception occurred while getting region details.", e);
        throw new OperationsException(e.getMessage());
      }
    }

    return regionsInfo;
  }

  /**
   * Collects all the region details from the RegionSubRegionSnapshot instance passed and the Cache
   * MBean. Checks in the set of existingRegionMbeans before initializing Region Mbeans if there are
   * not initialized yet.
   *
   * @param cache Cache MBean instance
   * @param regionSnapshot RegionSubRegionSnapshot instance
   * @param regionsInfo Map of regions information that gets populated recursively
   * @param existingRegionMbeans Map of ObjectNames of existing region MBeans
   * @throws AdminException if unable to initialize region MBean
   * @throws OperationsException if fails to retrieve the Region MBean attribute info
   * @throws MBeanException if fails to retrieve the Region MBean attribute info
   * @throws ReflectionException if fails to retrieve the Region MBean attribute info
   */
  @SuppressWarnings("rawtypes")
  private void collectAllRegionsDetails(SystemMemberCacheJmxImpl cache,
      RegionSubRegionSnapshot regionSnapshot, Map<String, Map<String, ?>> regionsInfo,
      Map<String, ObjectName> existingRegionMbeans)
      throws AdminException, OperationsException, MBeanException, ReflectionException {
    String fullPath = regionSnapshot.getFullPath();
    if (!fullPath.equals(PLACE_HOLDER_ROOT_REGION)) {
      fullPath = fullPath.substring(PLACE_HOLDER_ROOT_REGION.length() - 1);
      String name = regionSnapshot.getName();
      Integer entryCount = Integer.valueOf(regionSnapshot.getEntryCount());
      Map<String, Object> details = new TreeMap<String, Object>();
      details.put(REGION_NAME, name);
      details.put(REGION_PATH, fullPath);
      details.put(REGION_ENTRYCOUNT, entryCount);

      ObjectName regionObjectName = existingRegionMbeans.get(fullPath);
      if (regionObjectName == null) {// initialize if has not yet been
        regionObjectName = cache.manageRegion(fullPath);
      }

      Object attribute = getAttribute(regionObjectName, "scope", NOT_AVAILABLE);
      attribute = attribute != null ? attribute.toString() : attribute;
      details.put(REGION_SCOPE, attribute);

      attribute = getAttribute(regionObjectName, "dataPolicy", NOT_AVAILABLE);
      attribute = attribute != null ? attribute.toString() : attribute;
      details.put(REGION_DATAPOLICY, attribute);

      SubscriptionAttributes interestPolicyAttr =
          (SubscriptionAttributes) getAttribute(regionObjectName, "subscriptionAttributes", null);
      String interestPolicyStr = NOT_AVAILABLE;
      if (interestPolicyAttr != null) {
        InterestPolicy interestPolicy = interestPolicyAttr.getInterestPolicy();
        if (interestPolicy != null) {
          interestPolicyStr = interestPolicy.toString();
        }
      }
      details.put(REGION_INTERESTPOLICY, interestPolicyStr);

      attribute = getAttribute(regionObjectName, "diskWriteAttributes", NOT_AVAILABLE);
      attribute = attribute != null ? attribute.toString() : attribute;
      details.put(REGION_DISKATTRS, attribute);

      regionsInfo.put(fullPath, details);
    }

    Set subRegionSnapshots = regionSnapshot.getSubRegionSnapshots();

    for (Iterator iterator = subRegionSnapshots.iterator(); iterator.hasNext();) {
      RegionSubRegionSnapshot subRegion = (RegionSubRegionSnapshot) iterator.next();
      collectAllRegionsDetails(cache, subRegion, regionsInfo, existingRegionMbeans);
    }
  }

  /**
   * Checks if the given host name string contains ':' as in IPv6 host address.
   *
   * @param host host name string
   * @return true if the host string contains ':', false otherwise
   */
  private static boolean isIPv6(String host) {
    return host.contains(":");
  }

  /**
   * Checks if the given host name is actually a String representation of an IPv4 address.
   *
   * @param host host name string
   * @return true if given host name is a String representation of an IPv4 address, false otherwise
   */
  private static boolean isIPv4(String host) {
    String regex = "\\d{1,3}.\\d{1,3}.\\d{1,3}.\\d{1,3}";

    return host.matches(regex);
  }

  /**
   * Excludes the host name from the client id and returns the String. If the host name can not be
   * detected, returns an empty string. Typically, the client id looks like:
   * HOST(VM_PID:VM_KIND):PORT:RANDOM_STRING:CLIENT_NAME
   *
   * Extracts the client name from the client id. If the client id is not in the expected format,
   * returns 'N/A'
   *
   * @param clientId string identifier for a client
   * @param host host name (FQDN) the client is running on
   * @return name extracted from given client id
   */
  /*
   * Some examples of Client Id format: (1) Java Client:
   * nase(21716:loner):51789:42e9a0bf:client_nase_21716 nase(2560:loner):2:7a84729a:Feeder
   *
   * (2) Native Client: nase(21045:loner):2:GFNative_OnNnEpyRWL:ExampleDistributedSystem
   *
   * (3) IPv6 Host whose name can not be resolved:
   * fdf0:76cf:a0ed:9449:0:0:0:1001(21716:loner):51789:42e9a0b:client_nase_21716
   * fdf0:76cf:a0ed:9449:0:0:0:1001:51789:42e9a0b:client_nase_21716
   */
  private static String extractClientName(String clientId, String host) {
    /* This isIPv6, isIPv4, extractClientName is taken from GFMon code base */
    String hostExcludedId = "";
    if ((isIPv6(host) || isIPv4(host)) && clientId.startsWith(host)) {
      hostExcludedId = clientId.substring(host.length());
    } else {
      int firstDotIndex = host.indexOf(".");
      if (firstDotIndex != -1) {
        String hostShortName = host.substring(0, firstDotIndex);
        hostExcludedId = clientId.substring(hostShortName.length());
      }
    }

    String vmPIDAndKindRegex = "\\(\\w+:\\w+\\)";
    String regex = "(\\<ec\\>)?:[0-9]+(:\\w+){2}+";
    String name = NOT_AVAILABLE;
    String temp = hostExcludedId;

    int openIndex = temp.indexOf("(");
    if (openIndex != -1) {
      regex = vmPIDAndKindRegex + regex;
    }

    if (temp.matches(regex)) {
      String[] splitted = temp.split(":");
      name = splitted[splitted.length - 1];
    }

    return name;
  }

  /**
   * Returns a Map of all the statistics required for Hyperic currently. It relies on the attribute
   * of the StatisticsResource Mbeans.
   *
   * @param member instance for which the stats are needed
   * @return Map of all the statistics required for Hyperic currently.
   * @throws OperationsException exceptions thrown while retrieving the attributes
   */
  private Map<String, Object> getRequiredStats(SystemMemberJmx member, boolean statSamplingEnabled)
      throws OperationsException {
    Map<String, Object> statDetails = new TreeMap<String, Object>();

    try {
      if (!statSamplingEnabled) {
        statDetails.put(STATS_PROCESSCPUTIME, NOT_AVAILABLE_NUMBER);
        statDetails.put(STATS_CPUS, NOT_AVAILABLE_NUMBER);
        statDetails.put(STATS_MAXMEMORY, NOT_AVAILABLE_NUMBER);
        statDetails.put(STATS_USEDMEMORY, NOT_AVAILABLE_NUMBER);
        statDetails.put(STATS_GETS, NOT_AVAILABLE_NUMBER);
        statDetails.put(STATS_GETTIME, NOT_AVAILABLE_NUMBER);
        statDetails.put(STATS_PUTS, NOT_AVAILABLE_NUMBER);
        statDetails.put(STATS_PUTTIME, NOT_AVAILABLE_NUMBER);
      } else {
        MBeanServer mBeanServer = agent.getMBeanServer();
        Number defaultVal = NOT_AVAILABLE_NUMBER;
        Number processCpuTime = defaultVal;
        Number cpus = defaultVal;
        Number maxMemory = defaultVal;
        Number usedMemory = defaultVal;
        Number gets = defaultVal;
        Number getTime = defaultVal;
        Number puts = defaultVal;
        Number putTime = defaultVal;

        ObjectName[] vmMemoryUsageStats = getExistingStats(member.getId(), "vmHeapMemoryStats");
        ObjectName[] vmStats = getExistingStats(member.getId(), "vmStats");
        ObjectName[] cachePerfStats = getExistingStats(member.getId(), "cachePerfStats");
        boolean needToReinit = false;
        if (vmMemoryUsageStats.length == 0 || vmStats.length == 0 || cachePerfStats.length == 0) {
          // if the StatisticResource MBeans are not created
          needToReinit = true;
        }
        if (!needToReinit) {
          /*
           * To handle a case when the StatisticResource MBeans are created but not registered with
           * RefreshTimer. If VMMemoryUsageStats are present, maxMemory should always be non-zero.
           */
          for (int i = 0; i < vmMemoryUsageStats.length; i++) {// ideally there should be a single
                                                               // instance
            String type = (String) mBeanServer.getAttribute(vmMemoryUsageStats[i], "type");

            if ("VMMemoryUsageStats".equals(type)) { // first instance that has Statistics Type name
              maxMemory = (Number) getAttribute(vmMemoryUsageStats[i], "maxMemory", defaultVal);
              break;
            }
          }

          needToReinit = 0 == maxMemory.longValue();
        }

        if (needToReinit) {
          logger.info("Re-initializing statistics for: {}",
              member.getId());
          initStats(member);

          vmMemoryUsageStats = getExistingStats(member.getId(), "vmHeapMemoryStats");
          vmStats = getExistingStats(member.getId(), "vmStats");
          cachePerfStats = getExistingStats(member.getId(), "cachePerfStats");
        }

        for (int i = 0; i < vmMemoryUsageStats.length; i++) {// ideally there should be a single
                                                             // instance
          String type = (String) mBeanServer.getAttribute(vmMemoryUsageStats[i], "type");

          if ("VMMemoryUsageStats".equals(type)) { // first instance that has Statistics Type name
            maxMemory = (Number) getAttribute(vmMemoryUsageStats[i], "maxMemory", defaultVal);
            usedMemory = (Number) getAttribute(vmMemoryUsageStats[i], "usedMemory", defaultVal);
            break;
          }
        }

        for (int i = 0; i < vmStats.length; i++) {// ideally there should be a single instance
          String type = (String) mBeanServer.getAttribute(vmStats[i], "type");

          if ("VMStats".equals(type)) { // first instance that has Statistics Type name
            processCpuTime = (Number) getAttribute(vmStats[i], "processCpuTime", defaultVal);
            cpus = (Number) getAttribute(vmStats[i], "cpus", defaultVal);
            break;
          }
        }

        for (int i = 0; i < cachePerfStats.length; i++) {// ideally there should be a single
                                                         // instance
          String type = (String) mBeanServer.getAttribute(cachePerfStats[i], "type");

          if ("CachePerfStats".equals(type)) { // first instance that has Statistics Type name
            gets = (Number) getAttribute(cachePerfStats[i], "gets", defaultVal);
            getTime = (Number) getAttribute(cachePerfStats[i], "getTime", defaultVal);
            puts = (Number) getAttribute(cachePerfStats[i], "puts", defaultVal);
            putTime = (Number) getAttribute(cachePerfStats[i], "putTime", defaultVal);
            break;
          }
        }

        statDetails.put(STATS_PROCESSCPUTIME, processCpuTime == NOT_AVAILABLE_NUMBER
            ? NOT_AVAILABLE_NUMBER : processCpuTime.longValue());
        statDetails.put(STATS_CPUS,
            cpus == NOT_AVAILABLE_NUMBER ? NOT_AVAILABLE_NUMBER : cpus.intValue());
        statDetails.put(STATS_MAXMEMORY,
            maxMemory == NOT_AVAILABLE_NUMBER ? NOT_AVAILABLE_NUMBER : maxMemory.longValue());
        statDetails.put(STATS_USEDMEMORY,
            usedMemory == NOT_AVAILABLE_NUMBER ? NOT_AVAILABLE_NUMBER : usedMemory.longValue());
        statDetails.put(STATS_GETS,
            gets == NOT_AVAILABLE_NUMBER ? NOT_AVAILABLE_NUMBER : gets.intValue());
        statDetails.put(STATS_GETTIME,
            getTime == NOT_AVAILABLE_NUMBER ? NOT_AVAILABLE_NUMBER : getTime.intValue());
        statDetails.put(STATS_PUTS,
            puts == NOT_AVAILABLE_NUMBER ? NOT_AVAILABLE_NUMBER : puts.intValue());
        statDetails.put(STATS_PUTTIME,
            putTime == NOT_AVAILABLE_NUMBER ? NOT_AVAILABLE_NUMBER : putTime.longValue());
      }
    } catch (Exception e) {
      logger.warn(e.getMessage(), e);
      throw new OperationsException(e.getMessage());
    }

    return statDetails;
  }

  /**
   * Returns attribute with given attribute name on MBean with given ObjectName.
   *
   *
   * @param objectName ObjectName for the MBean
   * @param attribute attribute name
   * @param unavailableValue return this value if the attribute value is null
   * @return value of attribute with given attribute name
   * @throws OperationsException if attribute is not found for MBean with this ObjectName or MBean
   *         instance is not found
   * @throws MBeanException if MBeans getter throws exception
   * @throws ReflectionException thrown when trying to invoke the setter.
   */
  private Object getAttribute(ObjectName objectName, String attribute, Object unavailableValue)
      throws OperationsException, MBeanException, ReflectionException {
    /* NOTE: callers methods rely on non-null value being returned */
    Object value = null;

    MBeanServer mBeanServer = agent.getMBeanServer();
    value = mBeanServer.getAttribute(objectName, attribute);

    value = (value != null) ? value : unavailableValue;

    return value;
  }

  /**
   * Return Map of region full against the ObjectName of existing region MBeans.
   *
   * @param memberId string identifier of a member
   * @return Map of region path vs ObjectName for existing region MBeans
   * @throws MalformedObjectNameException If the query expression used is not valid
   */
  private Map<String, ObjectName> getExistingRegionMbeansFullPaths(String memberId)
      throws MalformedObjectNameException {
    Map<String, ObjectName> pathsToObjName = new HashMap<String, ObjectName>();

    if (memberId != null && memberId.trim().length() != 0) {
      Object[] params = new Object[] {MBeanUtil.makeCompliantMBeanNameProperty(memberId)};
      Set<ObjectName> queryNames = queryObjectNames(REGION_QUERY_EXPRESSION, params);
      for (ObjectName objectName : queryNames) {
        pathsToObjName.put(objectName.getKeyProperty("path"), objectName);
      }
    }

    return pathsToObjName;
  }

  /**
   * Returns an array of ObjectNames existing statistics types MBeans
   *
   * @param memberId string identifier of a member
   * @param name text id of the stats which appears in the stats ObjectName as name keyProperty
   * @return Array of Stats MBean ObjectNames
   * @throws MalformedObjectNameException If the query expression used is not valid
   */
  private ObjectName[] getExistingStats(String memberId, String name)
      throws MalformedObjectNameException {
    ObjectName[] statObjectNames = new ObjectName[0];

    if (memberId != null && memberId.trim().length() != 0) {
      Object[] params = new Object[] {MBeanUtil.makeCompliantMBeanNameProperty(memberId), name};
      Set<ObjectName> queryNames = queryObjectNames(STATS_QUERY_EXPRESSION, params);
      statObjectNames = new ObjectName[queryNames.size()];
      statObjectNames = queryNames.toArray(statObjectNames);
    }

    return statObjectNames;
  }

  /**
   * Queries the MBean server with the string formed using placing the params in the parameterized
   * string passed as queryStr.
   *
   * @param queryStr parameterized string
   * @param params params to put in the string
   * @return results of an ObjectName query
   * @throws MalformedObjectNameException If the query expression ObjectName formed is not valid
   */
  private Set<ObjectName> queryObjectNames(String queryStr, Object... params)
      throws MalformedObjectNameException {
    Set<ObjectName> queried = Collections.emptySet();

    queryStr = MessageFormat.format(queryStr, params);
    ObjectName queryExp = ObjectName.getInstance(queryStr);
    queried = agent.getMBeanServer().queryNames(null, queryExp);

    return queried;
  }


  /* *************************************************************************/
  /* **************** NOTIFICATION EMITTER IMPLEMENTATION ********************/
  /* *************************************************************************/

  /**
   * @see NotificationEmitter#addNotificationListener(NotificationListener, NotificationFilter,
   *      Object)
   */
  @Override
  public void addNotificationListener(NotificationListener listener, NotificationFilter filter,
      Object handback) throws IllegalArgumentException {
    forwarder.addNotificationListener(listener, filter, handback);
  }

  /**
   * @see NotificationEmitter#removeNotificationListener(NotificationListener)
   */
  @Override
  public void removeNotificationListener(NotificationListener listener)
      throws ListenerNotFoundException {
    forwarder.removeNotificationListener(listener);
  }

  /**
   * @see NotificationEmitter#getNotificationInfo()
   */
  @Override
  public MBeanNotificationInfo[] getNotificationInfo() {
    return getMBeanInfo().getNotifications();
  }

  /**
   * @see NotificationEmitter#removeNotificationListener(NotificationListener, NotificationFilter,
   *      Object)
   */
  @Override
  public void removeNotificationListener(NotificationListener listener, NotificationFilter filter,
      Object handback) throws ListenerNotFoundException {
    forwarder.removeNotificationListener(listener, filter, handback);
  }

}


/**
 * This class acts as a hub for the Notifications defined on AdminDistributedSystem & SystemMember
 * MBeans. This acts as a listener for these notifications and broadcasts them as notifications from
 * the {@link MemberInfoWithStatsMBean} MBean. This class extends
 * {@link NotificationBroadcasterSupport} only to have the functionality to send notifications.
 *
 *
 * @since GemFire 6.5
 */
class NotificationForwarder extends NotificationBroadcasterSupport implements NotificationListener {

  private static final Logger logger = LogService.getLogger();

  /* sequence generator for notifications from GemFireTypesWrapper MBean */
  @MakeNotStatic
  private static final AtomicLong notificationSequenceNumber = new AtomicLong();

  /* reference to the MBeanServer instance */
  private MBeanServer mBeanServer;

  /**
   * Default Constructor
   *
   * @param mBeanServer reference to the MBeanServer instance
   */
  /* default */ NotificationForwarder(MBeanServer mBeanServer) {
    this.mBeanServer = mBeanServer;
  }

  /**
   * Handles notifications as: 1. Member Joined: Registers this NotificationForwarder as a
   * notification listener for Cache/Region Notifications. 2. Member Left/Crashed: Unregisters this
   * NotificationForwarder as a notification listener for Cache/Region Notifications. 3.
   * AdminDistributedSystem Disconnected: Unregisters this NotificationForwarder as a notification
   * listener for member Notifications.
   *
   * Forwards the notifications to the JMX Clients that have registered for notifications on this
   * MBean
   *
   * @param notification notification to be handled
   * @param handback handback object used while NotificationForwarder was registered
   *
   * @see NotificationListener#handleNotification(Notification, Object)
   */
  @Override
  public void handleNotification(Notification notification, Object handback) {
    Object notifSource = notification.getSource();
    if (AdminDistributedSystemJmxImpl.NOTIF_MEMBER_JOINED.equals(notification.getType())) {
      ObjectName source = (ObjectName) notifSource;
      // initialize statistics/register with refreshTimer for new member
      String[] noArgs = {};
      try {
        ObjectName[] stats =
            (ObjectName[]) mBeanServer.invoke(source, "manageStats", noArgs, noArgs);
        if (stats != null) {
          for (ObjectName stat : stats) {
            mBeanServer.invoke(stat, "getStatistics", noArgs, noArgs);
          }
        }
        logger.debug("getStatistics call completed with no exceptions.");
      } catch (ReflectionException e) {
        logger.info(String.format("Exception while initializing statistics for: %s",
            source.toString()),
            e);
      } catch (MBeanException e) {
        logger.info(String.format("Exception while initializing statistics for: %s",
            source.toString()),
            e);
      } catch (InstanceNotFoundException e) {
        logger.info(String.format("Exception while initializing statistics for: %s",
            source.toString()),
            e);
      }
      // register this listener for joined member's cache/region notifications
      try {
        registerNotificationListener(source);
      } catch (OperationsException e) {
        logger.info(String.format("Exception while registering notification listener for: %s",
            source.toString()),
            e);
      }
    }

    // TODO: Check if same notification instance can be reused by simply changing the sequence
    // number
    notification = new Notification(notification.getType(), notifSource,
        notificationSequenceNumber.addAndGet(1L), notification.getTimeStamp(),
        notification.getMessage());

    sendNotification(notification);
  }

  /**
   * Registers itself as a NotificationListener for Notifications sent from MBean with the
   * ObjectName given as source.
   *
   * @param source source of notifications
   * @throws InstanceNotFoundException The MBean name provided does not match any of the registered
   *         MBeans.
   */
  /* default */void registerNotificationListener(ObjectName source)
      throws InstanceNotFoundException {
    mBeanServer.addNotificationListener(source, this, null/* handback */, source);
  }

  /**
   * Unregisters itself as a NotificationListener for Notifications sent from MBean with the
   * ObjectName given as source.
   *
   * @param source source of notifications
   * @throws InstanceNotFoundException The MBean name provided does not match any of the registered
   *         MBeans.
   * @throws ListenerNotFoundException The listener is not registered in the MBean.
   */
  /* default */void unregisterNotificationListener(ObjectName source)
      throws InstanceNotFoundException, ListenerNotFoundException {
    mBeanServer.removeNotificationListener(source, this);
  }
}
