/*
 * 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.beans;

import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableList;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.geode.management.JMXNotificationType.ASYNC_EVENT_QUEUE_CLOSED;
import static org.apache.geode.management.JMXNotificationType.ASYNC_EVENT_QUEUE_CREATED;
import static org.apache.geode.management.JMXNotificationType.CACHE_SERVER_STARTED;
import static org.apache.geode.management.JMXNotificationType.CACHE_SERVER_STOPPED;
import static org.apache.geode.management.JMXNotificationType.CACHE_SERVICE_CREATED;
import static org.apache.geode.management.JMXNotificationType.CLIENT_CRASHED;
import static org.apache.geode.management.JMXNotificationType.CLIENT_JOINED;
import static org.apache.geode.management.JMXNotificationType.CLIENT_LEFT;
import static org.apache.geode.management.JMXNotificationType.DISK_STORE_CLOSED;
import static org.apache.geode.management.JMXNotificationType.DISK_STORE_CREATED;
import static org.apache.geode.management.JMXNotificationType.GATEWAY_RECEIVER_CREATED;
import static org.apache.geode.management.JMXNotificationType.GATEWAY_RECEIVER_DESTROYED;
import static org.apache.geode.management.JMXNotificationType.GATEWAY_RECEIVER_STARTED;
import static org.apache.geode.management.JMXNotificationType.GATEWAY_RECEIVER_STOPPED;
import static org.apache.geode.management.JMXNotificationType.GATEWAY_SENDER_CREATED;
import static org.apache.geode.management.JMXNotificationType.GATEWAY_SENDER_PAUSED;
import static org.apache.geode.management.JMXNotificationType.GATEWAY_SENDER_REMOVED;
import static org.apache.geode.management.JMXNotificationType.GATEWAY_SENDER_RESUMED;
import static org.apache.geode.management.JMXNotificationType.GATEWAY_SENDER_STARTED;
import static org.apache.geode.management.JMXNotificationType.GATEWAY_SENDER_STOPPED;
import static org.apache.geode.management.JMXNotificationType.LOCATOR_STARTED;
import static org.apache.geode.management.JMXNotificationType.LOCK_SERVICE_CLOSED;
import static org.apache.geode.management.JMXNotificationType.LOCK_SERVICE_CREATED;
import static org.apache.geode.management.JMXNotificationType.REGION_CLOSED;
import static org.apache.geode.management.JMXNotificationType.REGION_CREATED;
import static org.apache.geode.management.JMXNotificationType.SYSTEM_ALERT;
import static org.apache.geode.management.JMXNotificationUserData.ALERT_LEVEL;
import static org.apache.geode.management.JMXNotificationUserData.MEMBER;
import static org.apache.geode.management.JMXNotificationUserData.THREAD;
import static org.apache.geode.management.internal.AlertDetails.getAlertLevelAsString;
import static org.apache.geode.management.internal.ManagementConstants.AGGREGATE_MBEAN_PATTERN;
import static org.apache.geode.management.internal.ManagementConstants.ASYNC_EVENT_QUEUE_CLOSED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.ASYNC_EVENT_QUEUE_CREATED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.CACHE_SERVER_STARTED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.CACHE_SERVER_STOPPED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.CACHE_SERVICE_CREATED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.CLIENT_CRASHED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.CLIENT_JOINED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.CLIENT_LEFT_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.DISK_STORE_CLOSED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.DISK_STORE_CREATED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.GATEWAY_RECEIVER_CREATED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.GATEWAY_RECEIVER_DESTROYED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.GATEWAY_RECEIVER_STARTED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.GATEWAY_RECEIVER_STOPPED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.GATEWAY_SENDER_CREATED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.GATEWAY_SENDER_PAUSED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.GATEWAY_SENDER_REMOVED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.GATEWAY_SENDER_RESUMED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.GATEWAY_SENDER_STARTED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.GATEWAY_SENDER_STOPPED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.LOCATOR_STARTED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.LOCK_SERVICE_CLOSED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.LOCK_SERVICE_CREATED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.REGION_CLOSED_PREFIX;
import static org.apache.geode.management.internal.ManagementConstants.REGION_CREATED_PREFIX;

import java.lang.management.ManagementFactory;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.ObjectInstance;
import javax.management.ObjectName;

import org.apache.logging.log4j.Logger;

import org.apache.geode.annotations.Immutable;
import org.apache.geode.cache.DiskStore;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.asyncqueue.AsyncEventQueue;
import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.cache.wan.GatewayReceiver;
import org.apache.geode.cache.wan.GatewaySender;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.Locator;
import org.apache.geode.distributed.internal.ClusterDistributionManager;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.distributed.internal.InternalLocator;
import org.apache.geode.distributed.internal.locks.DLockService;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.internal.ClassLoadUtil;
import org.apache.geode.internal.cache.CacheService;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.cache.PartitionedRegionHelper;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.management.AsyncEventQueueMXBean;
import org.apache.geode.management.CacheServerMXBean;
import org.apache.geode.management.DiskStoreMXBean;
import org.apache.geode.management.GatewayReceiverMXBean;
import org.apache.geode.management.GatewaySenderMXBean;
import org.apache.geode.management.LocatorMXBean;
import org.apache.geode.management.LockServiceMXBean;
import org.apache.geode.management.ManagementException;
import org.apache.geode.management.ManagementService;
import org.apache.geode.management.ManagerMXBean;
import org.apache.geode.management.MemberMXBean;
import org.apache.geode.management.RegionMXBean;
import org.apache.geode.management.internal.AlertDetails;
import org.apache.geode.management.internal.FederationComponent;
import org.apache.geode.management.internal.MBeanJMXAdapter;
import org.apache.geode.management.internal.SystemManagementService;
import org.apache.geode.management.membership.ClientMembership;
import org.apache.geode.management.membership.ClientMembershipEvent;
import org.apache.geode.management.membership.ClientMembershipListener;
import org.apache.geode.management.membership.ClientMembershipListenerAdapter;
import org.apache.geode.pdx.internal.PeerTypeRegistration;

/**
 * Acts as an intermediate between MBean layer and Federation Layer. Handles all Call backs from
 * GemFire to instantiate or remove MBeans from GemFire Domain.
 *
 * <p>
 * Even though this class have a lot of utility functions it interacts with the state of the system
 * and contains some state itself.
 */
public class ManagementAdapter {

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

  @Immutable
  private static final List<String> INTERNAL_LOCK_SERVICES =
      unmodifiableList(asList(DLockService.DTLS, DLockService.LTLS,
          PartitionedRegionHelper.PARTITION_LOCK_SERVICE_NAME,
          PeerTypeRegistration.LOCK_SERVICE_NAME));

  private final MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
  private final Object regionOpLock = new Object();

  private SystemManagementService service;
  private InternalCache internalCache;
  private String memberSource;
  private NotificationBroadcasterSupport memberLevelNotificationEmitter;
  private MemberMBean memberBean;
  private MBeanAggregator aggregator;
  private MemberMBeanBridge memberMBeanBridge;

  private volatile boolean serviceInitialised;

  /**
   * Adapter life cycle is tied with the Cache. So its better to make all cache level artifacts as
   * instance variable
   */
  void handleCacheCreation(InternalCache cache) throws ManagementException {
    try {
      internalCache = cache;
      service = (SystemManagementService) ManagementService.getManagementService(internalCache);

      memberMBeanBridge = new MemberMBeanBridge(internalCache, service).init();
      memberBean = new MemberMBean(memberMBeanBridge);
      memberLevelNotificationEmitter = memberBean;
      memberSource = MBeanJMXAdapter.getMemberNameOrUniqueId(cache.getMyId());

      // Type casting to MemberMXBean to expose only those methods described in interface
      ObjectName objectName = MBeanJMXAdapter.getMemberMBeanName(cache.getMyId());
      ObjectName federatedName = service.registerInternalMBean(memberBean, objectName);
      service.federate(federatedName, MemberMXBean.class, true);

      serviceInitialised = true;

      // Service initialised is only for ManagementService and not necessarily Manager service.

      // For situations where locator is created before any cache is created
      if (InternalLocator.hasLocator()) {
        handleLocatorStart(InternalLocator.getLocator());
      }

      if (cache.getInternalDistributedSystem().getConfig().getJmxManager()) {
        service.createManager();
        if (cache.getInternalDistributedSystem().getConfig().getJmxManagerStart()) {
          service.startManager();
        }
      }

    } finally {
      if (!serviceInitialised && service != null) {
        service.close();
        if (logger.isDebugEnabled()) {
          logger.debug("Management Service Could not initialise hence closing");
        }

      } else {
        if (logger.isDebugEnabled()) {
          logger.debug("Management Service is initialised and Running");
        }

      }
    }
  }

  /**
   * Handles all the distributed mbean creation part when a Manager is started
   */
  void handleManagerStart() throws ManagementException {
    if (!isServiceInitialised("handleManagerStart")) {
      return;
    }

    DistributedSystemBridge distributedSystemBridge =
        new DistributedSystemBridge(service, internalCache);
    aggregator = new MBeanAggregator(distributedSystemBridge);

    // register the aggregator for Federation framework to use
    service.addProxyListener(aggregator);

    // get the local member mbean as it need to be provided to aggregator first
    MemberMXBean localMemberMXBean = service.getMemberMXBean();

    ObjectName memberObjectName = MBeanJMXAdapter.getMemberMBeanName(
        InternalDistributedSystem.getConnectedInstance().getDistributedMember());

    FederationComponent memberFederation =
        service.getLocalManager().getFedComponents().get(memberObjectName);

    service.afterCreateProxy(memberObjectName, MemberMXBean.class, localMemberMXBean,
        memberFederation);

    MBeanJMXAdapter jmxAdapter = service.getJMXAdapter();
    Map<ObjectName, Object> registeredMBeans = jmxAdapter.getLocalGemFireMBean();

    for (ObjectName objectName : registeredMBeans.keySet()) {
      if (objectName.equals(memberObjectName)) {
        continue;
      }
      Object object = registeredMBeans.get(objectName);
      try {
        ObjectInstance instance = mbeanServer.getObjectInstance(objectName);
        String className = instance.getClassName();
        Class clazz = ClassLoadUtil.classFromName(className);
        Type[] interfaceTypes = clazz.getGenericInterfaces();

        FederationComponent federation =
            service.getLocalManager().getFedComponents().get(objectName);

        for (Type interfaceType : interfaceTypes) {
          Class interfaceTypeAsClass = (Class) interfaceType;
          service.afterCreateProxy(objectName, interfaceTypeAsClass, object, federation);

        }
      } catch (InstanceNotFoundException e) {
        if (logger.isDebugEnabled()) {
          logger.debug("Failed in Registering distributed mbean ");
        }
        throw new ManagementException(e);
      } catch (ClassNotFoundException e) {
        if (logger.isDebugEnabled()) {
          logger.debug("Failed in Registering distributed mbean");
        }
        throw new ManagementException(e);
      }
    }
  }

  /**
   * Handles all the clean up activities when a Manager is stopped It clears the distributed mbeans
   * and underlying data structures
   */
  void handleManagerStop() throws ManagementException {
    if (!isServiceInitialised("handleManagerStop")) {
      return;
    }

    MemberMXBean localMemberMXBean = service.getMemberMXBean();

    ObjectName memberObjectName = MBeanJMXAdapter.getMemberMBeanName(
        InternalDistributedSystem.getConnectedInstance().getDistributedMember());

    FederationComponent memberFederation =
        service.getLocalManager().getFedComponents().get(memberObjectName);

    service.afterRemoveProxy(memberObjectName, MemberMXBean.class, localMemberMXBean,
        memberFederation);

    ObjectName aggregateMBeanPattern = aggregateMBeanPattern();
    MBeanJMXAdapter jmxAdapter = service.getJMXAdapter();
    Map<ObjectName, Object> registeredMBeans = jmxAdapter.getLocalGemFireMBean();
    for (ObjectName objectName : registeredMBeans.keySet()) {
      if (objectName.equals(memberObjectName)) {
        continue;
      }
      if (aggregateMBeanPattern.apply(objectName)) {
        continue;
      }
      Object object = registeredMBeans.get(objectName);
      try {
        ObjectInstance instance = mbeanServer.getObjectInstance(objectName);
        String className = instance.getClassName();
        Class clazz = ClassLoadUtil.classFromName(className);
        Type[] interfaceTypes = clazz.getGenericInterfaces();

        FederationComponent federation =
            service.getLocalManager().getFedComponents().get(objectName);

        for (Type interfaceType : interfaceTypes) {
          Class interfaceTypeClass = (Class) interfaceType;
          service.afterRemoveProxy(objectName, interfaceTypeClass, object, federation);
        }
      } catch (InstanceNotFoundException | ClassNotFoundException e) {
        logger.warn("Failed to invoke aggregator for {} with exception {}", objectName,
            e.getMessage(), e);
      }
    }

    service.removeProxyListener(aggregator);
    aggregator = null;
  }

  /**
   * Assumption is always cache and MemberMbean has been will be created first
   */
  void handleManagerCreation() throws ManagementException {
    if (!isServiceInitialised("handleManagerCreation")) {
      return;
    }

    ObjectName objectName = MBeanJMXAdapter.getManagerName();
    ManagerMBeanBridge managerMBeanBridge = new ManagerMBeanBridge(service);
    ManagerMXBean managerMXBean = new ManagerMBean(managerMBeanBridge);

    service.registerInternalMBean(managerMXBean, objectName);
  }

  /**
   * Handles Region Creation. This is the call back which will create the specified RegionMXBean and
   * will send a notification on behalf of Member Mbean
   *
   * @param region the region for which the call back is invoked
   */
  <K, V> void handleRegionCreation(Region<K, V> region) throws ManagementException {
    if (!isServiceInitialised("handleRegionCreation")) {
      return;
    }

    // Moving region creation operation inside a guarded block
    // After getting access to regionOpLock it again checks for region
    // destroy status

    synchronized (regionOpLock) {
      if (region.isDestroyed()) {
        return;
      }

      // Bridge is responsible for extracting data from GemFire Layer
      RegionMBeanBridge<K, V> regionMBeanBridge = RegionMBeanBridge.getInstance(region);
      RegionMXBean regionMXBean = new RegionMBean<>(regionMBeanBridge);
      ObjectName objectName = MBeanJMXAdapter.getRegionMBeanName(
          internalCache.getDistributedSystem().getDistributedMember(), region.getFullPath());
      ObjectName federatedName = service.registerInternalMBean(regionMXBean, objectName);
      service.federate(federatedName, RegionMXBean.class, true);

      Notification notification = new Notification(REGION_CREATED, memberSource,
          SequenceNumber.next(), System.currentTimeMillis(),
          REGION_CREATED_PREFIX + region.getFullPath());
      memberLevelNotificationEmitter.sendNotification(notification);

      memberMBeanBridge.addRegion(region);
    }
  }

  /**
   * Handles Disk Creation. Will create DiskStoreMXBean and will send a notification
   */
  void handleDiskCreation(DiskStore diskStore) throws ManagementException {
    if (!isServiceInitialised("handleDiskCreation")) {
      return;
    }

    DiskStoreMBeanBridge diskStoreMBeanBridge = new DiskStoreMBeanBridge(diskStore);
    DiskStoreMXBean diskStoreMXBean = new DiskStoreMBean(diskStoreMBeanBridge);
    ObjectName objectName = MBeanJMXAdapter.getDiskStoreMBeanName(
        internalCache.getDistributedSystem().getDistributedMember(), diskStore.getName());
    ObjectName federatedName = service.registerInternalMBean(diskStoreMXBean, objectName);
    service.federate(federatedName, DiskStoreMXBean.class, true);

    Notification notification = new Notification(DISK_STORE_CREATED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(),
        DISK_STORE_CREATED_PREFIX + diskStore.getName());
    memberLevelNotificationEmitter.sendNotification(notification);

    memberMBeanBridge.addDiskStore(diskStore);
  }

  /**
   * Handles LockService Creation
   *
   */
  void handleLockServiceCreation(DLockService lockService) throws ManagementException {
    if (!isServiceInitialised("handleLockServiceCreation")) {
      return;
    }
    // Internal Locks Should not be exposed to client for monitoring
    if (INTERNAL_LOCK_SERVICES.contains(lockService.getName())) {
      return;
    }

    LockServiceMBeanBridge lockServiceMBeanBridge = new LockServiceMBeanBridge(lockService);
    LockServiceMXBean lockServiceMXBean = new LockServiceMBean(lockServiceMBeanBridge);
    ObjectName objectName = MBeanJMXAdapter.getLockServiceMBeanName(
        internalCache.getDistributedSystem().getDistributedMember(), lockService.getName());
    ObjectName federatedName =
        service.registerInternalMBean(lockServiceMXBean, objectName);
    service.federate(federatedName, LockServiceMXBean.class, true);

    Notification notification = new Notification(LOCK_SERVICE_CREATED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(),
        LOCK_SERVICE_CREATED_PREFIX + lockService.getName());
    memberLevelNotificationEmitter.sendNotification(notification);

    memberMBeanBridge.addLockServiceStats(lockService);
  }

  /**
   * Handles GatewaySender creation
   *
   * @param sender the specific gateway sender
   */
  void handleGatewaySenderCreation(GatewaySender sender) throws ManagementException {
    if (!isServiceInitialised("handleGatewaySenderCreation")) {
      return;
    }

    GatewaySenderMBeanBridge gatewaySenderMBeanBridge = new GatewaySenderMBeanBridge(sender);
    GatewaySenderMXBean gatewaySenderMXBean = new GatewaySenderMBean(gatewaySenderMBeanBridge);
    ObjectName objectName = MBeanJMXAdapter.getGatewaySenderMBeanName(
        internalCache.getDistributedSystem().getDistributedMember(), sender.getId());
    ObjectName federatedName = service.registerInternalMBean(gatewaySenderMXBean, objectName);
    service.federate(federatedName, GatewaySenderMXBean.class, true);

    Notification notification = new Notification(GATEWAY_SENDER_CREATED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(), GATEWAY_SENDER_CREATED_PREFIX);
    memberLevelNotificationEmitter.sendNotification(notification);
  }

  /**
   * Handles Gateway receiver creation
   *
   * @param gatewayReceiver specific gateway receiver
   */
  void handleGatewayReceiverCreate(GatewayReceiver gatewayReceiver) throws ManagementException {
    if (!isServiceInitialised("handleGatewayReceiverCreate")) {
      return;
    }
    if (!gatewayReceiver.isManualStart()) {
      return;
    }

    createGatewayReceiverMBean(gatewayReceiver);
  }

  private void createGatewayReceiverMBean(GatewayReceiver gatewayReceiver) {
    GatewayReceiverMBeanBridge gatewayReceiverMBeanBridge =
        new GatewayReceiverMBeanBridge(gatewayReceiver);
    GatewayReceiverMXBean gatewayReceiverMXBean =
        new GatewayReceiverMBean(gatewayReceiverMBeanBridge);
    ObjectName objectName = MBeanJMXAdapter
        .getGatewayReceiverMBeanName(internalCache.getDistributedSystem().getDistributedMember());
    ObjectName federatedName = service.registerInternalMBean(gatewayReceiverMXBean, objectName);
    service.federate(federatedName, GatewayReceiverMXBean.class, true);

    Notification notification = new Notification(GATEWAY_RECEIVER_CREATED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(), GATEWAY_RECEIVER_CREATED_PREFIX);
    memberLevelNotificationEmitter.sendNotification(notification);
  }

  void handleGatewayReceiverDestroy() throws ManagementException {
    if (!isServiceInitialised("handleGatewayReceiverDestroy")) {
      return;
    }

    GatewayReceiverMBean gatewayReceiverMBean =
        (GatewayReceiverMBean) service.getLocalGatewayReceiverMXBean();
    GatewayReceiverMBeanBridge gatewayReceiverMBeanBridge = gatewayReceiverMBean.getBridge();

    gatewayReceiverMBeanBridge.destroyServer();

    ObjectName objectName = MBeanJMXAdapter
        .getGatewayReceiverMBeanName(internalCache.getDistributedSystem().getDistributedMember());
    service.unregisterMBean(objectName);

    Notification notification = new Notification(GATEWAY_RECEIVER_DESTROYED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(), GATEWAY_RECEIVER_DESTROYED_PREFIX);
    memberLevelNotificationEmitter.sendNotification(notification);
  }

  /**
   * Handles Gateway receiver creation
   *
   * @param gatewayReceiver specific gateway receiver
   */
  void handleGatewayReceiverStart(GatewayReceiver gatewayReceiver) throws ManagementException {
    if (!isServiceInitialised("handleGatewayReceiverStart")) {
      return;
    }

    if (!gatewayReceiver.isManualStart()) {
      createGatewayReceiverMBean(gatewayReceiver);
    }

    GatewayReceiverMBean gatewayReceiverMBean =
        (GatewayReceiverMBean) service.getLocalGatewayReceiverMXBean();
    GatewayReceiverMBeanBridge gatewayReceiverMBeanBridge = gatewayReceiverMBean.getBridge();

    gatewayReceiverMBeanBridge.startServer();

    Notification notification = new Notification(GATEWAY_RECEIVER_STARTED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(), GATEWAY_RECEIVER_STARTED_PREFIX);
    memberLevelNotificationEmitter.sendNotification(notification);
  }

  void handleGatewayReceiverStop() throws ManagementException {
    if (!isServiceInitialised("handleGatewayReceiverStop")) {
      return;
    }

    GatewayReceiverMBean gatewayReceiverMBean =
        (GatewayReceiverMBean) service.getLocalGatewayReceiverMXBean();
    GatewayReceiverMBeanBridge gatewayReceiverMBeanBridge = gatewayReceiverMBean.getBridge();

    gatewayReceiverMBeanBridge.stopServer();

    Notification notification = new Notification(GATEWAY_RECEIVER_STOPPED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(), GATEWAY_RECEIVER_STOPPED_PREFIX);
    memberLevelNotificationEmitter.sendNotification(notification);
  }

  void handleAsyncEventQueueCreation(AsyncEventQueue asyncEventQueue) throws ManagementException {
    if (!isServiceInitialised("handleAsyncEventQueueCreation")) {
      return;
    }

    AsyncEventQueueMBeanBridge asyncEventQueueMBeanBridge =
        new AsyncEventQueueMBeanBridge(asyncEventQueue);
    AsyncEventQueueMXBean asyncEventQueueMXBean =
        new AsyncEventQueueMBean(asyncEventQueueMBeanBridge);
    ObjectName objectName = MBeanJMXAdapter.getAsyncEventQueueMBeanName(
        internalCache.getDistributedSystem().getDistributedMember(), asyncEventQueue.getId());
    ObjectName federatedName = service.registerInternalMBean(asyncEventQueueMXBean, objectName);
    service.federate(federatedName, AsyncEventQueueMXBean.class, true);

    Notification notification = new Notification(ASYNC_EVENT_QUEUE_CREATED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(), ASYNC_EVENT_QUEUE_CREATED_PREFIX);
    memberLevelNotificationEmitter.sendNotification(notification);
  }

  void handleAsyncEventQueueRemoval(AsyncEventQueue asyncEventQueue) throws ManagementException {
    if (!isServiceInitialised("handleAsyncEventQueueRemoval")) {
      return;
    }

    ObjectName objectName = MBeanJMXAdapter.getAsyncEventQueueMBeanName(
        internalCache.getDistributedSystem().getDistributedMember(), asyncEventQueue.getId());

    try {
      AsyncEventQueueMBean asyncEventQueueMBean =
          (AsyncEventQueueMBean) service.getLocalAsyncEventQueueMXBean(asyncEventQueue.getId());
      if (asyncEventQueueMBean == null) {
        return;
      }

      asyncEventQueueMBean.stopMonitor();

    } catch (ManagementException e) {
      // If no bean found its a NO-OP
      if (logger.isDebugEnabled()) {
        logger.debug(e.getMessage(), e);
      }
      return;
    }

    service.unregisterMBean(objectName);

    Notification notification = new Notification(ASYNC_EVENT_QUEUE_CLOSED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(),
        ASYNC_EVENT_QUEUE_CLOSED_PREFIX + asyncEventQueue.getId());
    memberLevelNotificationEmitter.sendNotification(notification);
  }

  /**
   * Sends the alert with the Object source as member. This notification will get filtered out for
   * particular alert level
   */
  void handleSystemNotification(AlertDetails alertDetails) {
    if (!isServiceInitialised("handleSystemNotification")) {
      return;
    }

    if (service.isManager()) {
      String systemSource = "DistributedSystem("
          + service.getDistributedSystemMXBean().getDistributedSystemId() + ")";
      Notification notification = new Notification(SYSTEM_ALERT, systemSource,
          SequenceNumber.next(), alertDetails.getMsgTime().getTime(), alertDetails.getMsg());
      notification.setUserData(prepareUserData(alertDetails));
      service.handleNotification(notification);
    }
  }

  private Map<String, String> prepareUserData(AlertDetails alertDetails) {
    Map<String, String> userData = new HashMap<>();

    userData.put(ALERT_LEVEL, getAlertLevelAsString(alertDetails.getAlertLevel()));
    userData.put(THREAD, alertDetails.getSource());
    userData.put(MEMBER, getNameOrId(alertDetails.getSender()));

    return userData;
  }

  /**
   * Assumption is its a cache server instance. For Gateway receiver there will be a separate method
   *
   * @param cacheServer cache server instance
   */
  void handleCacheServerStart(CacheServer cacheServer) {
    if (!isServiceInitialised("handleCacheServerStart")) {
      return;
    }

    CacheServerBridge cacheServerBridge = new CacheServerBridge(internalCache, cacheServer);
    cacheServerBridge.setMemberMBeanBridge(memberMBeanBridge);
    CacheServerMBean cacheServerMBean = new CacheServerMBean(cacheServerBridge);
    ObjectName objectName = MBeanJMXAdapter.getClientServiceMBeanName(
        cacheServer.getPort(), internalCache.getDistributedSystem().getDistributedMember());
    ObjectName federatedName = service.registerInternalMBean(cacheServerMBean, objectName);

    ClientMembershipListener managementClientListener = new CacheServerMembershipListenerAdapter(
        cacheServerMBean, memberLevelNotificationEmitter, federatedName);
    ClientMembership.registerClientMembershipListener(managementClientListener);
    cacheServerBridge.setClientMembershipListener(managementClientListener);

    service.federate(federatedName, CacheServerMXBean.class, true);

    Notification notification = new Notification(CACHE_SERVER_STARTED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(), CACHE_SERVER_STARTED_PREFIX);
    memberLevelNotificationEmitter.sendNotification(notification);

    memberMBeanBridge.setCacheServer(true);
  }

  /**
   * Assumption is its a cache server instance. For Gateway receiver there will be a separate method
   */
  void handleCacheServerStop(CacheServer server) {
    if (!isServiceInitialised("handleCacheServerStop")) {
      return;
    }

    CacheServerMBean cacheServerMBean =
        (CacheServerMBean) service.getLocalCacheServerMXBean(server.getPort());

    ClientMembershipListener clientMembershipListener =
        cacheServerMBean.getBridge().getClientMembershipListener();
    if (clientMembershipListener != null) {
      ClientMembership.unregisterClientMembershipListener(clientMembershipListener);
    }

    cacheServerMBean.stopMonitor();

    ObjectName objectName = MBeanJMXAdapter.getClientServiceMBeanName(server.getPort(),
        internalCache.getDistributedSystem().getDistributedMember());
    service.unregisterMBean(objectName);

    Notification notification = new Notification(CACHE_SERVER_STOPPED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(), CACHE_SERVER_STOPPED_PREFIX);
    memberLevelNotificationEmitter.sendNotification(notification);

    memberMBeanBridge.setCacheServer(false);
  }

  void handleCacheRemoval() throws ManagementException {
    if (!isServiceInitialised("handleCacheRemoval")) {
      return;
    }

    serviceInitialised = false;
    try {
      cleanUpMonitors();
      cleanBridgeResources();
    } catch (Exception e) {
      if (logger.isDebugEnabled()) {
        logger.debug(e.getMessage(), e);
      }
    }

    try {
      service.close();
    } catch (Exception e) {
      logger.warn(e.getMessage(), e);
    } finally {
      internalCache = null;
      service = null;
      memberMBeanBridge = null;
      memberBean = null;
      memberLevelNotificationEmitter = null;
    }
  }

  private String getNameOrId(DistributedMember member) {
    if (member == null) {
      return memberSource;
    }
    return isNotBlank(member.getName()) ? member.getName() : member.getId();
  }

  private void cleanUpMonitors() {
    MemberMBean memberMBean = (MemberMBean) service.getMemberMXBean();
    if (memberMBean != null) {
      memberMBean.stopMonitor();
    }

    Set<GatewaySender> gatewaySenders = internalCache.getGatewaySenders();

    if (gatewaySenders != null && !gatewaySenders.isEmpty()) {
      for (GatewaySender gatewaySender : gatewaySenders) {
        GatewaySenderMBean gatewaySenderMBean =
            (GatewaySenderMBean) service.getLocalGatewaySenderMXBean(gatewaySender.getId());
        if (gatewaySenderMBean != null) {
          gatewaySenderMBean.stopMonitor();
        }
      }
    }

    GatewayReceiverMBean gatewayReceiverMBean =
        (GatewayReceiverMBean) service.getLocalGatewayReceiverMXBean();
    if (gatewayReceiverMBean != null) {
      gatewayReceiverMBean.stopMonitor();
    }
  }

  private void cleanBridgeResources() {
    List<CacheServer> cacheServers = internalCache.getCacheServers();

    if (cacheServers != null && !cacheServers.isEmpty()) {
      for (CacheServer cacheServer : cacheServers) {
        CacheServerMBean cacheServerMBean =
            (CacheServerMBean) service.getLocalCacheServerMXBean(cacheServer.getPort());

        if (cacheServerMBean != null) {
          ClientMembershipListener listener =
              cacheServerMBean.getBridge().getClientMembershipListener();

          if (listener != null) {
            ClientMembership.unregisterClientMembershipListener(listener);
          }
        }
      }
    }
  }

  /**
   * Handles particular region destroy or close operation it will remove the corresponding MBean
   */
  void handleRegionRemoval(Region region) throws ManagementException {
    if (!isServiceInitialised("handleRegionRemoval")) {
      return;
    }

    // Moved region remove operation to a guarded block. If a region is getting created it won't
    // allow it to destroy any region.

    synchronized (regionOpLock) {
      ObjectName objectName = MBeanJMXAdapter.getRegionMBeanName(
          internalCache.getDistributedSystem().getDistributedMember(), region.getFullPath());

      try {
        RegionMBean regionMBean = (RegionMBean) service.getLocalRegionMBean(region.getFullPath());
        if (regionMBean != null) {
          regionMBean.stopMonitor();
        }
      } catch (ManagementException e) {
        // If no bean found its a NO-OP
        // Mostly for situation like DiskAccessException while creating region
        // which does a compensatory close region
        if (logger.isDebugEnabled()) {
          logger.debug(e.getMessage(), e);
        }
        return;
      }

      service.unregisterMBean(objectName);

      Notification notification = new Notification(REGION_CLOSED, memberSource,
          SequenceNumber.next(), System.currentTimeMillis(),
          REGION_CLOSED_PREFIX + region.getFullPath());
      memberLevelNotificationEmitter.sendNotification(notification);

      memberMBeanBridge.removeRegion(region);
    }
  }

  void handleDiskRemoval(DiskStore diskStore) throws ManagementException {
    if (!isServiceInitialised("handleDiskRemoval")) {
      return;
    }

    ObjectName objectName = MBeanJMXAdapter.getDiskStoreMBeanName(
        internalCache.getDistributedSystem().getDistributedMember(), diskStore.getName());

    try {
      DiskStoreMBean diskStoreMBean =
          (DiskStoreMBean) service.getLocalDiskStoreMBean(diskStore.getName());
      if (diskStoreMBean == null) {
        return;
      }
      diskStoreMBean.stopMonitor();
    } catch (ManagementException e) {
      // If no bean found its a NO-OP
      if (logger.isDebugEnabled()) {
        logger.debug(e.getMessage(), e);
      }
      return;
    }

    service.unregisterMBean(objectName);

    Notification notification = new Notification(DISK_STORE_CLOSED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(),
        DISK_STORE_CLOSED_PREFIX + diskStore.getName());
    memberLevelNotificationEmitter.sendNotification(notification);

    memberMBeanBridge.removeDiskStore(diskStore);
  }

  void handleLockServiceRemoval(DLockService lockService) throws ManagementException {
    if (!isServiceInitialised("handleLockServiceRemoval")) {
      return;
    }

    ObjectName objectName = MBeanJMXAdapter.getLockServiceMBeanName(
        internalCache.getDistributedSystem().getDistributedMember(), lockService.getName());

    service.unregisterMBean(objectName);

    Notification notification = new Notification(LOCK_SERVICE_CLOSED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(),
        LOCK_SERVICE_CLOSED_PREFIX + lockService.getName());
    memberLevelNotificationEmitter.sendNotification(notification);
  }

  /**
   * Handles management side call backs for a locator creation and start. Assumption is a cache will
   * be created before hand.
   *
   * <p>
   * There is no corresponding handleStopLocator() method. Locator will close the cache whenever its
   * stopped and it should also shutdown all the management services by closing the cache.
   *
   * @param locator instance of locator which is getting started
   */
  void handleLocatorStart(Locator locator) throws ManagementException {
    if (!isServiceInitialised("handleLocatorCreation")) {
      return;
    }

    ObjectName objectName = MBeanJMXAdapter
        .getLocatorMBeanName(internalCache.getDistributedSystem().getDistributedMember());
    LocatorMBeanBridge locatorMBeanBridge = new LocatorMBeanBridge(locator);
    LocatorMBean locatorMBean = new LocatorMBean(locatorMBeanBridge);
    ObjectName federatedName = service.registerInternalMBean(locatorMBean, objectName);
    service.federate(federatedName, LocatorMXBean.class, true);

    Notification notification = new Notification(LOCATOR_STARTED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(), LOCATOR_STARTED_PREFIX);
    memberLevelNotificationEmitter.sendNotification(notification);
  }

  void handleGatewaySenderStart(GatewaySender gatewaySender) throws ManagementException {
    if (!isServiceInitialised("handleGatewaySenderStart")) {
      return;
    }
    if (gatewaySender.getRemoteDSId() < 0) {
      return;
    }

    GatewaySenderMBean gatewaySenderMBean =
        (GatewaySenderMBean) service.getLocalGatewaySenderMXBean(gatewaySender.getId());

    gatewaySenderMBean.getBridge().setDispatcher();

    Notification notification = new Notification(GATEWAY_SENDER_STARTED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(),
        GATEWAY_SENDER_STARTED_PREFIX + gatewaySender.getId());
    memberLevelNotificationEmitter.sendNotification(notification);
  }

  void handleGatewaySenderStop(GatewaySender gatewaySender) throws ManagementException {
    if (!isServiceInitialised("handleGatewaySenderStop")) {
      return;
    }

    Notification notification = new Notification(GATEWAY_SENDER_STOPPED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(),
        GATEWAY_SENDER_STOPPED_PREFIX + gatewaySender.getId());
    memberLevelNotificationEmitter.sendNotification(notification);
  }

  void handleGatewaySenderPaused(GatewaySender gatewaySender) throws ManagementException {
    if (!isServiceInitialised("handleGatewaySenderPaused")) {
      return;
    }

    Notification notification = new Notification(GATEWAY_SENDER_PAUSED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(),
        GATEWAY_SENDER_PAUSED_PREFIX + gatewaySender.getId());
    memberLevelNotificationEmitter.sendNotification(notification);
  }

  void handleGatewaySenderResumed(GatewaySender gatewaySender) throws ManagementException {
    if (!isServiceInitialised("handleGatewaySenderResumed")) {
      return;
    }

    Notification notification = new Notification(GATEWAY_SENDER_RESUMED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(),
        GATEWAY_SENDER_RESUMED_PREFIX + gatewaySender.getId());
    memberLevelNotificationEmitter.sendNotification(notification);
  }

  void handleGatewaySenderRemoved(GatewaySender gatewaySender) throws ManagementException {
    if (!isServiceInitialised("handleGatewaySenderRemoved")) {
      return;
    }
    if (gatewaySender.getRemoteDSId() < 0) {
      return;
    }

    GatewaySenderMBean gatewaySenderMBean =
        (GatewaySenderMBean) service.getLocalGatewaySenderMXBean(gatewaySender.getId());
    gatewaySenderMBean.stopMonitor();

    ObjectName objectName = MBeanJMXAdapter.getGatewaySenderMBeanName(
        internalCache.getDistributedSystem().getDistributedMember(), gatewaySender.getId());
    service.unregisterMBean(objectName);

    Notification notification = new Notification(GATEWAY_SENDER_REMOVED, memberSource,
        SequenceNumber.next(), System.currentTimeMillis(),
        GATEWAY_SENDER_REMOVED_PREFIX + gatewaySender.getId());
    memberLevelNotificationEmitter.sendNotification(notification);
  }

  void handleCacheServiceCreation(CacheService cacheService) throws ManagementException {
    if (!isServiceInitialised("handleCacheServiceCreation")) {
      return;
    }

    // Don't register the CacheServices in the Locator
    InternalDistributedMember member =
        internalCache.getInternalDistributedSystem().getDistributedMember();
    if (member.getVmKind() == ClusterDistributionManager.LOCATOR_DM_TYPE) {
      return;
    }

    CacheServiceMBeanBase cacheServiceMBean = cacheService.getMBean();
    if (cacheServiceMBean != null) {
      String id = cacheServiceMBean.getId();
      ObjectName objectName = MBeanJMXAdapter.getCacheServiceMBeanName(member, id);
      ObjectName federatedName = service.registerInternalMBean(cacheServiceMBean, objectName);
      service.federate(federatedName, cacheServiceMBean.getInterfaceClass(), true);

      Notification notification = new Notification(CACHE_SERVICE_CREATED, memberSource,
          SequenceNumber.next(), System.currentTimeMillis(),
          CACHE_SERVICE_CREATED_PREFIX + id);
      memberLevelNotificationEmitter.sendNotification(notification);
    }
  }

  private ObjectName aggregateMBeanPattern() {
    try {
      return new ObjectName(AGGREGATE_MBEAN_PATTERN);
    } catch (MalformedObjectNameException | NullPointerException e) {
      throw new ManagementException(e);
    }
  }

  private boolean isServiceInitialised(String method) {
    if (!serviceInitialised) {
      if (logger.isDebugEnabled()) {
        logger.debug("Management Service is not initialised hence returning from {}", method);
      }
    }

    return serviceInitialised;
  }

  /**
   * Propagates client joined/left notifications
   */
  private static class CacheServerMembershipListenerAdapter
      extends ClientMembershipListenerAdapter {

    private final NotificationBroadcasterSupport serverLevelNotificationEmitter;
    private final NotificationBroadcasterSupport memberLevelNotificationEmitter;
    private final String serverSource;

    private CacheServerMembershipListenerAdapter(
        NotificationBroadcasterSupport serverLevelNotificationEmitter,
        NotificationBroadcasterSupport memberLevelNotificationEmitter,
        ObjectName serverSource) {
      this.serverLevelNotificationEmitter = serverLevelNotificationEmitter;
      this.memberLevelNotificationEmitter = memberLevelNotificationEmitter;
      this.serverSource = serverSource.toString();
    }

    /**
     * Invoked when a client has connected to this process or when this process has connected to a
     * CacheServer.
     */
    @Override
    public void memberJoined(ClientMembershipEvent event) {
      Notification notification = new Notification(CLIENT_JOINED, serverSource,
          SequenceNumber.next(), System.currentTimeMillis(),
          CLIENT_JOINED_PREFIX + event.getMemberId());

      serverLevelNotificationEmitter.sendNotification(notification);
      memberLevelNotificationEmitter.sendNotification(notification);
    }

    /**
     * Invoked when a client has gracefully disconnected from this process or when this process has
     * gracefully disconnected from a CacheServer.
     */
    @Override
    public void memberLeft(ClientMembershipEvent event) {
      Notification notification = new Notification(CLIENT_LEFT, serverSource,
          SequenceNumber.next(), System.currentTimeMillis(),
          CLIENT_LEFT_PREFIX + event.getMemberId());

      serverLevelNotificationEmitter.sendNotification(notification);
      memberLevelNotificationEmitter.sendNotification(notification);
    }

    /**
     * Invoked when a client has unexpectedly disconnected from this process or when this process
     * has unexpectedly disconnected from a CacheServer.
     */
    @Override
    public void memberCrashed(ClientMembershipEvent event) {
      Notification notification = new Notification(CLIENT_CRASHED, serverSource,
          SequenceNumber.next(), System.currentTimeMillis(),
          CLIENT_CRASHED_PREFIX + event.getMemberId());

      serverLevelNotificationEmitter.sendNotification(notification);
      memberLevelNotificationEmitter.sendNotification(notification);
    }
  }
}
