/*
 * 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.internal.logging.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(DistributedMember member) {

    InternalDistributedMember iMember = (InternalDistributedMember) member;
    final StringBuilder sb = new StringBuilder();
    sb.append(iMember.getInetAddress().getHostAddress());
    // View ID will be 0 for Loner, but in that case no federation as well
    sb.append("<v").append(iMember.getVmViewId()).append(">");
    sb.append(iMember.getPort());
    // 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."));
  }
}
