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

import java.lang.management.ManagementFactory;
import java.lang.reflect.Type;
import java.text.MessageFormat;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationEmitter;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.ReflectionException;

import org.apache.logging.log4j.Logger;

import org.apache.geode.annotations.internal.MutableForTesting;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.internal.ClassLoadUtil;
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.DistributedLockServiceMXBean;
import org.apache.geode.management.DistributedRegionMXBean;
import org.apache.geode.management.DistributedSystemMXBean;
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.ManagerMXBean;
import org.apache.geode.management.MemberMXBean;
import org.apache.geode.management.RegionMXBean;

/**
 * Utility class to interact with the JMX server
 *
 *
 */
public class MBeanJMXAdapter implements ManagementConstants {
  /** The <code>MBeanServer</code> for this application */
  @MutableForTesting
  public static MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();

  private final Map<ObjectName, Object> localGemFireMBean;

  private final DistributedMember distMember;

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

  /**
   * public constructor
   */
  public MBeanJMXAdapter(DistributedMember distMember) {
    this.localGemFireMBean = new ConcurrentHashMap<>();
    this.distMember = distMember;
  }

  /**
   * This method will register an MBean in GemFire domain. Even if the client provides a domain name
   * it will be ignored and GemFire domain name will be used.
   *
   * This method checks the local Filter for registering the MBean. If filtered the MBean wont be
   * registered. Although the filter will remember the filtered MBean and register it once the
   * filter is removed.
   *
   * @return modified ObjectName
   */
  public ObjectName registerMBean(Object object, ObjectName objectName, boolean isGemFireMBean) {
    ObjectName newObjectName = objectName;
    try {
      if (!isGemFireMBean) {
        String member = getMemberNameOrUniqueId(distMember);
        String objectKeyProperty = objectName.getKeyPropertyListString();

        newObjectName = ObjectName.getInstance(
            OBJECTNAME__PREFIX + objectKeyProperty + KEYVAL_SEPARATOR + "member=" + member);
      }

      if (isRegistered(newObjectName)) {
        return newObjectName;
      }

      mbeanServer.registerMBean(object, newObjectName);
      this.localGemFireMBean.put(newObjectName, object);

    } catch (InstanceAlreadyExistsException | NullPointerException | MalformedObjectNameException
        | NotCompliantMBeanException | MBeanRegistrationException e) {
      throw new ManagementException(e);
    }
    return newObjectName;
  }

  /**
   * Checks whether an MBean implements notification support classes or not
   *
   * @return if this MBean can be a notification broadcaster
   */
  public boolean hasNotificationSupport(ObjectName objectName) {
    try {
      if (!isRegistered(objectName)) {
        return false;
      }
      ObjectInstance instance = mbeanServer.getObjectInstance(objectName);
      String className = instance.getClassName();
      Class cls = ClassLoadUtil.classFromName(className);
      Type[] intfTyps = cls.getGenericInterfaces();
      for (Type intfTyp1 : intfTyps) {
        Class intfTyp = (Class) intfTyp1;
        if (intfTyp.equals(NotificationEmitter.class)) {
          return true;
        }
      }
      Class superClassType = (Class) cls.getGenericSuperclass();
      if (superClassType != null && superClassType.equals(NotificationBroadcasterSupport.class)) {
        return true;
      }
    } catch (InstanceNotFoundException | ClassNotFoundException e) {
      throw new ManagementException(e);
    }
    return false;
  }

  /**
   * This method will register an MBean in GemFire domain. Even if the client provides a domain name
   * it will be ignored and GemFire domain name will be used.
   *
   * This method checks the local Filter for registering the MBean. If filtered the MBean wont be
   * registered. Although the filter will remember the filtered MBean and register it once the
   * filter is removed.
   *
   */
  public void registerMBeanProxy(Object object, ObjectName objectName) {
    try {
      if (isRegistered(objectName)) {
        return;
      }

      mbeanServer.registerMBean(object, objectName);
    } catch (InstanceAlreadyExistsException instanceAlreadyExistsException) {
      // An InstanceAlreadyExistsException in this context means that the MBean
      // has already been registered, so just log a warning message.
      logRegistrationWarning(objectName, true);
    } catch (NullPointerException | NotCompliantMBeanException
        | MBeanRegistrationException e) {
      throw new ManagementException(e);
    }
  }

  /**
   *
   * This method will unregister the MBean from GemFire Domain
   *
   */
  public void unregisterMBean(ObjectName objectName) {
    try {
      if (!isRegistered(objectName)) {
        return;
      }

      mbeanServer.unregisterMBean(objectName);

      // For Local GemFire MBeans
      if (localGemFireMBean.get(objectName) != null) {
        localGemFireMBean.remove(objectName);
      }
    } catch (InstanceNotFoundException instanceNotFoundException) {
      // An InstanceNotFoundException in this context means that the MBean
      // has already been unregistered, so just log a debug message as it is
      // essentially a no-op.
      // has already been unregistered, so just log a warning message.
      logRegistrationWarning(objectName, false);
    } catch (NullPointerException | MBeanRegistrationException e) {
      throw new ManagementException(e);
    }
  }

  public Object getMBeanObject(ObjectName objectName) {
    return localGemFireMBean.get(objectName);
  }

  /**
   * Finds the MBean instance by {@link javax.management.ObjectName}
   *
   * @return instance of MBean
   */
  public <T> T findMBeanByName(ObjectName objectName, Class<T> interfaceClass) {

    Object mbeanInstance = localGemFireMBean.get(objectName);
    if (mbeanInstance != null) {
      return interfaceClass.cast(mbeanInstance);
    } else {
      return null;
    }
  }

  public boolean isLocalMBean(ObjectName objectName) {
    return localGemFireMBean.containsKey(objectName);
  }

  /**
   * Method to unregister all the local GemFire MBeans
   *
   */

  public void unregisterAll() {
    try {
      ObjectName name = new ObjectName(OBJECTNAME__PREFIX + "*");
      Set<ObjectName> gemFireObjects = mbeanServer.queryNames(name, null);

      for (ObjectName objectName : gemFireObjects) {
        unregisterMBean(objectName);
      }
    } catch (MalformedObjectNameException | NullPointerException e) {
      throw new ManagementException(e);
    }

  }

  public void cleanJMXResource() {
    localGemFireMBean.clear();
    unregisterAll();
  }

  public boolean isRegistered(ObjectName objectName) {

    return mbeanServer.isRegistered(objectName);
  }

  /**
   * This method returns the name that will be used for a DistributedMember when it is registered as
   * a JMX bean.
   *
   * @param member Member to find the name for
   * @return The name used to register this member as a JMX bean.
   */
  public static String getMemberNameOrUniqueId(DistributedMember member) {
    if (member.getName() != null && !member.getName().equals("")) {
      return makeCompliantName(member.getName());
    }
    return makeCompliantName(member.getUniqueId());
  }

  /**
   * Return a String that been modified to be compliant as a property of an ObjectName.
   * <p>
   * The property name of an ObjectName may not contain any of the following characters: <b><i>: , =
   * * ?</i></b>
   * <p>
   * This method will replace the above non-compliant characters with a dash: <b><i>-</i></b>
   * <p>
   * If value is empty, this method will return the string "nothing".
   * <p>
   * Note: this is <code>public</code> because certain tests call this from outside of the package.
   *
   * @param value the potentially non-compliant ObjectName property
   * @return the value modified to be compliant as an ObjectName property
   */
  public static String makeCompliantName(String value) {
    value = value.replace(':', '-');
    value = value.replace(',', '-');
    value = value.replace('=', '-');
    value = value.replace('*', '-');
    value = value.replace('?', '-');
    if (value.length() < 1) {
      value = "nothing";
    }
    return value;
  }

  public static String makeCompliantRegionPath(String value) {
    if (isQuoted(value)) {
      value = ObjectName.unquote(value);
    } else {
      if (containsSpecialChar(value)) {
        value = ObjectName.quote(value);
      }
    }
    return value;
  }

  private static boolean containsSpecialChar(String value) {
    return value.contains(":") || value.contains("@") || value.contains("-") || value.contains("#")
        || value.contains("+") || value.contains("?");
  }

  private static boolean isQuoted(String value) {
    final int len = value.length();
    return len >= 2 && value.charAt(0) == '"' && value.charAt(len - 1) == '"';
  }

  public static String makeCompliantRegionNameAppender(String value) {

    return value.replace("/", "-").replace(":", "");

  }

  /**
   * returns Member MBean if any
   *
   */
  public MemberMXBean getMemberMXBean() {
    ObjectName objName = getMemberMBeanName(distMember);
    return (MemberMXBean) localGemFireMBean.get(objName);

  }

  public RegionMXBean getLocalRegionMXBean(String regionPath) {
    ObjectName objName = getRegionMBeanName(distMember, regionPath);
    return (RegionMXBean) localGemFireMBean.get(objName);

  }

  public LockServiceMXBean getLocalLockServiceMXBean(String lockServiceName) {
    ObjectName objName = getLockServiceMBeanName(distMember, lockServiceName);
    return (LockServiceMXBean) localGemFireMBean.get(objName);
  }

  public DiskStoreMXBean getLocalDiskStoreMXBean(String disStoreName) {
    ObjectName objName = getDiskStoreMBeanName(distMember, disStoreName);
    return (DiskStoreMXBean) localGemFireMBean.get(objName);

  }

  public CacheServerMXBean getClientServiceMXBean(int serverPort) {
    ObjectName objName = getClientServiceMBeanName(serverPort, distMember);
    return (CacheServerMXBean) localGemFireMBean.get(objName);

  }

  public DistributedLockServiceMXBean getDistributedLockServiceMXBean(String lockServiceName) {
    ObjectName objName = getDistributedLockServiceName(lockServiceName);
    return (DistributedLockServiceMXBean) localGemFireMBean.get(objName);
  }

  public DistributedRegionMXBean getDistributedRegionMXBean(String regionPath) {
    ObjectName objName = getDistributedRegionMbeanName(regionPath);
    return (DistributedRegionMXBean) localGemFireMBean.get(objName);
  }

  public ManagerMXBean getManagerMXBean() {
    ObjectName objName = getManagerName();
    return (ManagerMXBean) localGemFireMBean.get(objName);
  }

  public DistributedSystemMXBean getDistributedSystemMXBean() {
    ObjectName objName = getDistributedSystemName();
    return (DistributedSystemMXBean) localGemFireMBean.get(objName);
  }

  public GatewayReceiverMXBean getGatewayReceiverMXBean() {
    ObjectName objName = getGatewayReceiverMBeanName(distMember);
    return (GatewayReceiverMXBean) localGemFireMBean.get(objName);
  }

  public GatewaySenderMXBean getGatewaySenderMXBean(String senderId) {
    ObjectName objName = getGatewaySenderMBeanName(distMember, senderId);
    return (GatewaySenderMXBean) localGemFireMBean.get(objName);
  }

  public AsyncEventQueueMXBean getAsyncEventQueueMXBean(String queueId) {
    ObjectName objName = getAsyncEventQueueMBeanName(distMember, queueId);
    return (AsyncEventQueueMXBean) localGemFireMBean.get(objName);
  }


  public LocatorMXBean getLocatorMXBean() {
    ObjectName objName = getLocatorMBeanName(distMember);
    return (LocatorMXBean) localGemFireMBean.get(objName);
  }

  public static ObjectName getObjectName(String name) {
    try {
      return ObjectName.getInstance(name);
    } catch (MalformedObjectNameException | NullPointerException e) {
      throw new ManagementException(e);
    }
  }

  public static ObjectName getMemberMBeanName(DistributedMember member) {
    return getObjectName(
        (MessageFormat.format(OBJECTNAME__MEMBER_MXBEAN, getMemberNameOrUniqueId(member))));
  }

  public static ObjectName getMemberMBeanName(String member) {
    return getObjectName(
        (MessageFormat.format(OBJECTNAME__MEMBER_MXBEAN, makeCompliantName(member))));
  }

  public static ObjectName getRegionMBeanName(DistributedMember member, String regionPath) {

    return getObjectName((MessageFormat.format(OBJECTNAME__REGION_MXBEAN,
        makeCompliantRegionPath(regionPath), getMemberNameOrUniqueId(member))));
  }

  public static ObjectName getRegionMBeanName(String member, String regionPath) {
    return getObjectName((MessageFormat.format(OBJECTNAME__REGION_MXBEAN,
        makeCompliantRegionPath(regionPath), makeCompliantName(member))));
  }

  public static ObjectName getRegionMBeanName(ObjectName memberMBeanName, String regionPath) {
    return getObjectName(
        (MessageFormat.format(OBJECTNAME__REGION_MXBEAN, makeCompliantRegionPath(regionPath),
            memberMBeanName.getKeyProperty(ManagementConstants.OBJECTNAME_MEMBER_APPENDER))));
  }

  public static ObjectName getDiskStoreMBeanName(DistributedMember member, String diskName) {
    return getObjectName(
        (MessageFormat.format(OBJECTNAME__DISKSTORE_MXBEAN, diskName,
            getMemberNameOrUniqueId(member))));
  }

  public static ObjectName getDiskStoreMBeanName(String member, String diskName) {
    return getObjectName(
        (MessageFormat.format(OBJECTNAME__DISKSTORE_MXBEAN, diskName, makeCompliantName(member))));
  }

  public static ObjectName getClientServiceMBeanName(int serverPort, DistributedMember member) {
    return getObjectName((MessageFormat.format(OBJECTNAME__CLIENTSERVICE_MXBEAN,
        String.valueOf(serverPort), getMemberNameOrUniqueId(member))));
  }

  public static ObjectName getClientServiceMBeanName(int serverPort, String member) {
    return getObjectName((MessageFormat.format(OBJECTNAME__CLIENTSERVICE_MXBEAN,
        String.valueOf(serverPort), makeCompliantName(member))));
  }

  public static ObjectName getLockServiceMBeanName(DistributedMember member,
      String lockServiceName) {
    return getObjectName((MessageFormat.format(OBJECTNAME__LOCKSERVICE_MXBEAN, lockServiceName,
        getMemberNameOrUniqueId(member))));
  }

  public static ObjectName getLockServiceMBeanName(String member, String lockServiceName) {
    return getObjectName((MessageFormat.format(OBJECTNAME__LOCKSERVICE_MXBEAN, lockServiceName,
        makeCompliantName(member))));
  }

  public static ObjectName getGatewayReceiverMBeanName(DistributedMember member) {
    return getObjectName(
        (MessageFormat.format(OBJECTNAME__GATEWAYRECEIVER_MXBEAN,
            getMemberNameOrUniqueId(member))));
  }

  public static ObjectName getGatewayReceiverMBeanName(String member) {
    return getObjectName(
        (MessageFormat.format(OBJECTNAME__GATEWAYRECEIVER_MXBEAN, makeCompliantName(member))));
  }

  public static ObjectName getGatewaySenderMBeanName(DistributedMember member, String id) {
    return getObjectName(
        (MessageFormat.format(OBJECTNAME__GATEWAYSENDER_MXBEAN, id,
            getMemberNameOrUniqueId(member))));
  }

  public static ObjectName getGatewaySenderMBeanName(String member, String id) {
    return getObjectName(
        (MessageFormat.format(OBJECTNAME__GATEWAYSENDER_MXBEAN, id, makeCompliantName(member))));
  }

  public static ObjectName getAsyncEventQueueMBeanName(DistributedMember member, String queueId) {
    return getObjectName((MessageFormat.format(OBJECTNAME__ASYNCEVENTQUEUE_MXBEAN, queueId,
        getMemberNameOrUniqueId(member))));
  }

  public static ObjectName getDistributedRegionMbeanName(String regionPath) {
    return getObjectName((MessageFormat.format(OBJECTNAME__DISTRIBUTEDREGION_MXBEAN,
        makeCompliantRegionPath(regionPath))));
  }

  /**
   * Without special character transformation
   *
   * @param regionPath region path
   * @return ObjectName MBean name
   */
  public static ObjectName getDistributedRegionMbeanNameInternal(String regionPath) {
    return getObjectName((MessageFormat.format(OBJECTNAME__DISTRIBUTEDREGION_MXBEAN, regionPath)));
  }

  public static ObjectName getDistributedLockServiceName(String lockService) {
    return getObjectName(
        (MessageFormat.format(OBJECTNAME__DISTRIBUTEDLOCKSERVICE_MXBEAN, lockService)));
  }

  public static ObjectName getDistributedSystemName() {
    return getObjectName(OBJECTNAME__DISTRIBUTEDSYSTEM_MXBEAN);
  }

  public static ObjectName getManagerName() {
    String member =
        getMemberNameOrUniqueId(
            InternalDistributedSystem.getConnectedInstance().getDistributedMember());
    return getObjectName((MessageFormat.format(OBJECTNAME__MANAGER_MXBEAN, member)));
  }

  public static ObjectName getLocatorMBeanName(DistributedMember member) {
    return getObjectName(
        (MessageFormat.format(OBJECTNAME__LOCATOR_MXBEAN, getMemberNameOrUniqueId(member))));
  }

  public static ObjectName getLocatorMBeanName(String member) {
    return getObjectName(
        (MessageFormat.format(OBJECTNAME__LOCATOR_MXBEAN, makeCompliantName(member))));
  }

  public static ObjectName getCacheServiceMBeanName(DistributedMember member,
      String cacheServiceId) {
    return getObjectName((MessageFormat.format(OBJECTNAME__CACHESERVICE_MXBEAN, cacheServiceId,
        getMemberNameOrUniqueId(member))));
  }

  public Map<ObjectName, Object> getLocalGemFireMBean() {
    return this.localGemFireMBean;
  }

  public static String getUniqueIDForMember(InternalDistributedMember member) {
    final StringBuilder sb = new StringBuilder();
    sb.append(member.getInetAddress().getHostAddress());
    // View ID will be 0 for Loner, but in that case no federation as well
    sb.append("<v").append(member.getVmViewId()).append(">");
    sb.append(member.getMembershipPort());
    // Lower case to handle IPv6
    return makeCompliantName(sb.toString().toLowerCase());
  }

  public static boolean isAttributeAvailable(String attributeName, String objectName) {

    try {
      ObjectName objName = new ObjectName(objectName);
      mbeanServer.getAttribute(objName, attributeName);
    } catch (MalformedObjectNameException | ReflectionException | MBeanException
        | InstanceNotFoundException | AttributeNotFoundException | NullPointerException e) {
      return false;
    }

    return true;

  }

  void logRegistrationWarning(ObjectName objectName, boolean registering) {
    logger.warn("MBean with ObjectName " + objectName + " has already been "
        + (registering ? "registered." : "unregistered."));
  }
}
