/*
 * 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 java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.management.InstanceNotFoundException;
import javax.management.JMException;
import javax.management.JMRuntimeException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MBeanServerNotification;
import javax.management.MalformedObjectNameException;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.timer.TimerMBean;

import org.apache.commons.modeler.ManagedBean;
import org.apache.commons.modeler.Registry;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;

import org.apache.geode.SystemFailure;
import org.apache.geode.admin.RuntimeAdminException;
import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.internal.ClassPathLoader;
import org.apache.geode.logging.internal.log4j.api.LogService;

/**
 * Common support for MBeans and {@link ManagedResource}s. Static loading of this class creates the
 * MBeanServer and Modeler Registry.
 *
 * @since GemFire 3.5
 *
 */
public class MBeanUtil {

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

  /** The default MBeanServer domain name is "GemFire" */
  private static final String DEFAULT_DOMAIN = "GemFire";

  /** MBean Name for refreshTimer */
  private static final String REFRESH_TIMER_NAME = DEFAULT_DOMAIN + ":type=RefreshTimer";

  /* indicates whether the mbeanServer, registry & refreshTimer are started */
  @MakeNotStatic
  private static boolean isStarted;

  /** The Commons-Modeler configuration registry for our managed beans */
  @MakeNotStatic
  private static Registry registry;

  /** The <code>MBeanServer</code> for this application */
  @MakeNotStatic
  private static MBeanServer mbeanServer;

  /** MBean name of the Timer which handles refresh notifications */
  @MakeNotStatic
  private static ObjectName refreshTimerObjectName;

  /** Actual TimerMBean responsible for refresh notifications */
  @MakeNotStatic
  private static TimerMBean refreshTimer;

  /**
   * Map of ObjectNames to current timerNotificationIds
   * <p>
   * map: key=ObjectName, value=map: key=RefreshNotificationType, value=timerNotificationId
   */
  @MakeNotStatic
  private static final Map<NotificationListener, Map<RefreshNotificationType, Integer>> refreshClients =
      new HashMap<NotificationListener, Map<RefreshNotificationType, Integer>>();

  /** key=ObjectName, value=ManagedResource */
  @MakeNotStatic
  private static final Map<ObjectName, ManagedResource> managedResources =
      new HashMap<ObjectName, ManagedResource>();

  static {
    try {
      refreshTimerObjectName = ObjectName.getInstance(REFRESH_TIMER_NAME);
    } catch (Exception e) {
      logStackTrace(Level.ERROR, e);
    }
  }

  /**
   * Initializes Mbean Server, Registry, Refresh Timer & registers Server Notification Listener.
   *
   * @return reference to the mbeanServer
   */
  static MBeanServer start() {
    if (!isStarted) {
      mbeanServer = createMBeanServer();
      registry = createRegistry();

      registerServerNotificationListener();
      createRefreshTimer();
      isStarted = true;
    }

    return mbeanServer;
  }

  /**
   * Stops Registry, Refresh Timer. Releases Mbean Server after.
   */
  static void stop() {
    if (isStarted) {
      stopRefreshTimer();

      registry.stop();
      registry = null;
      releaseMBeanServer();// makes mbeanServer null
      isStarted = false;
    }
  }

  /**
   * Create and configure (if necessary) and return the <code>MBeanServer</code> with which we will
   * be registering our <code>ModelMBean</code> implementations.
   *
   * @see javax.management.MBeanServer
   */
  static synchronized MBeanServer createMBeanServer() {
    if (mbeanServer == null) {
      mbeanServer = MBeanServerFactory.createMBeanServer(DEFAULT_DOMAIN);
    }
    return mbeanServer;
  }

  /**
   * Create and configure (if necessary) and return the Commons-Modeler registry of managed object
   * descriptions.
   *
   * @see org.apache.commons.modeler.Registry
   */
  static synchronized Registry createRegistry() {
    if (registry == null) {
      try {
        registry = Registry.getRegistry(null, null);
        if (mbeanServer == null) {
          throw new IllegalStateException(
              "MBean Server is not initialized yet.");
        }
        registry.setMBeanServer(mbeanServer);

        String mbeansResource = getOSPath("/org/apache/geode/admin/jmx/mbeans-descriptors.xml");

        URL url = ClassPathLoader.getLatest().getResource(MBeanUtil.class, mbeansResource);
        raiseOnFailure(url != null, String.format("Failed to find %s",
            new Object[] {mbeansResource}));
        registry.loadMetadata(url);

        // simple test to make sure the xml was actually loaded and is valid...
        String[] test = registry.findManagedBeans();
        raiseOnFailure(test != null && test.length > 0,
            String.format("Failed to load metadata from %s",
                new Object[] {mbeansResource}));
      } catch (Exception e) {
        logStackTrace(Level.WARN, e);
        throw new RuntimeAdminException(
            "Failed to get MBean Registry", e);
      }
    }
    return registry;
  }

  /**
   * Creates and registers a <code>ModelMBean</code> for the specified <code>ManagedResource</code>.
   * State changing callbacks into the <code>ManagedResource</code> will also be made.
   *
   * @param resource the ManagedResource to create a managing MBean for
   *
   * @return The object name of the newly-created MBean
   *
   * @see ManagedResource#setModelMBean
   */
  static ObjectName createMBean(ManagedResource resource) {
    return createMBean(resource, lookupManagedBean(resource));
  }

  /**
   * Creates and registers a <code>ModelMBean</code> for the specified <code>ManagedResource</code>.
   * State changing callbacks into the <code>ManagedResource</code> will also be made.
   *
   * @param resource the ManagedResource to create a managing MBean for
   * @param managed the ManagedBean definition to create the MBean with
   * @see ManagedResource#setModelMBean
   */
  static ObjectName createMBean(ManagedResource resource, ManagedBean managed) {

    try {
      DynamicManagedBean mb = new DynamicManagedBean(managed);
      resource.setModelMBean(mb.createMBean(resource));

      // create the ObjectName and register the MBean...
      final ObjectName objName;
      try {
        objName = ObjectName.getInstance(resource.getMBeanName());
      } catch (MalformedObjectNameException e) {
        throw new MalformedObjectNameException(String.format("%s in '%s'",
            new Object[] {e.getMessage(), resource.getMBeanName()}));
      }

      synchronized (MBeanUtil.class) {
        // Only register a bean once. Otherwise, you risk race
        // conditions with things like the RMI connector accessing it.

        if (mbeanServer != null && !mbeanServer.isRegistered(objName)) {
          mbeanServer.registerMBean(resource.getModelMBean(), objName);
          synchronized (managedResources) {
            managedResources.put(objName, resource);
          }
        }
      }
      return objName;
    } catch (java.lang.Exception e) {
      throw new RuntimeAdminException(
          String.format("Failed to create MBean representation for resource %s.",
              new Object[] {resource.getMBeanName()}),
          e);
    }
  }

  /**
   * Ensures that an MBean is registered for the specified <code>ManagedResource</code>. If an MBean
   * cannot be found in the <code>MBeanServer</code>, then this creates and registers a
   * <code>ModelMBean</code>. State changing callbacks into the <code>ManagedResource</code> will
   * also be made.
   *
   * @param resource the ManagedResource to create a managing MBean for
   *
   * @return The object name of the MBean that manages the ManagedResource
   *
   * @see ManagedResource#setModelMBean
   */
  static ObjectName ensureMBeanIsRegistered(ManagedResource resource) {
    try {
      ObjectName objName = ObjectName.getInstance(resource.getMBeanName());
      synchronized (MBeanUtil.class) {
        if (mbeanServer != null && !mbeanServer.isRegistered(objName)) {
          return createMBean(resource);
        }
      }
      raiseOnFailure(mbeanServer.isRegistered(objName),
          String.format("Could not find a MBean registered with ObjectName: %s.",
              new Object[] {objName.toString()}));
      return objName;
    } catch (java.lang.Exception e) {
      throw new RuntimeAdminException(e);
    }
  }

  /**
   * Retrieves the <code>ManagedBean</code> configuration from the Registry for the specified
   * <code>ManagedResource</code>
   *
   * @param resource the ManagedResource to find the configuration for
   */
  static ManagedBean lookupManagedBean(ManagedResource resource) {
    // find the registry defn for our MBean...
    ManagedBean managed = null;
    if (registry != null) {
      managed = registry.findManagedBean(resource.getManagedResourceType().getClassTypeName());
    } else {
      throw new IllegalArgumentException(
          "ManagedBean is null");
    }

    if (managed == null) {
      throw new IllegalArgumentException(
          "ManagedBean is null");
    }

    // customize the defn...
    managed.setClassName("org.apache.geode.admin.jmx.internal.MX4JModelMBean");

    return managed;
  }

  /**
   * Registers a refresh notification for the specified client MBean. Specifying zero for the
   * refreshInterval disables notification for the refresh client. Note: this does not currently
   * support remote connections.
   *
   * @param client client to listen for refresh notifications
   * @param userData userData to register with the Notification
   * @param type refresh notification type the client will use
   * @param refreshInterval the seconds between refreshes
   */
  static void registerRefreshNotification(NotificationListener client, Object userData,
      RefreshNotificationType type, long refreshInterval) {
    if (client == null) {
      throw new IllegalArgumentException(
          "NotificationListener is required");
    }
    if (type == null) {
      throw new IllegalArgumentException(
          "RefreshNotificationType is required");
    }
    if (refreshTimerObjectName == null || refreshTimer == null) {
      throw new IllegalStateException(
          "RefreshTimer has not been properly initialized.");
    }

    try {
      // get the notifications for the specified client...
      Map<RefreshNotificationType, Integer> notifications = null;
      synchronized (refreshClients) {
        notifications = (Map<RefreshNotificationType, Integer>) refreshClients.get(client);
      }

      if (notifications == null) {
        // If refreshInterval is being set to zero and notifications is removed return
        if (refreshInterval <= 0) {
          return;
        }

        // never registered before, so add client...
        notifications = new HashMap<RefreshNotificationType, Integer>();
        synchronized (refreshClients) {
          refreshClients.put(client, notifications);
        }
        validateRefreshTimer();
        try {
          // register client as a listener with MBeanServer...
          mbeanServer.addNotificationListener(refreshTimerObjectName, // timer to listen to
              client, // the NotificationListener object
              null, // optional NotificationFilter TODO: convert to using
              new Object() // not used but null throws IllegalArgumentException
          );
        } catch (InstanceNotFoundException e) {
          // should not happen since we already checked refreshTimerObjectName
          logStackTrace(Level.WARN, e,
              "Could not find registered RefreshTimer instance.");
        }
      }

      // TODO: change to manipulating timer indirectly thru mserver...

      // check for pre-existing refresh notification entry...
      Integer timerNotificationId = (Integer) notifications.get(type);
      if (timerNotificationId != null) {
        try {
          // found one, so let's remove it...
          refreshTimer.removeNotification(timerNotificationId);
        } catch (InstanceNotFoundException e) {
          // that's ok cause we just wanted to remove it anyway
        } finally {
          // null out the map entry for that notification type...
          notifications.put(type, null);
        }
      }

      if (refreshInterval > 0) {
        // add notification to the refresh timer...
        timerNotificationId = refreshTimer.addNotification(type.getType(), // type
            type.getMessage(), // message = "refresh"
            userData, // userData
            new Date(System.currentTimeMillis() + refreshInterval * 1000L), // first occurrence
            refreshInterval * 1000L); // period to repeat

        // put an entry into the map for the listener...
        notifications.put(type, timerNotificationId);
      } else {
        // do nothing! refreshInterval must be over 0 to do anything...
      }
    } catch (java.lang.RuntimeException e) {
      logStackTrace(Level.WARN, e);
      throw e;
    } catch (VirtualMachineError err) {
      SystemFailure.initiateFailure(err);
      // If this ever returns, rethrow the error. We're poisoned
      // now, so don't let this thread continue.
      throw err;
    } catch (java.lang.Error e) {
      // Whenever you catch Error or Throwable, you must also
      // catch VirtualMachineError (see above). However, there is
      // _still_ a possibility that you are dealing with a cascading
      // error condition, so you also need to check to see if the JVM
      // is still usable:
      SystemFailure.checkFailure();
      logStackTrace(Level.ERROR, e);
      throw e;
    }
  }

  /**
   * Verifies a refresh notification for the specified client MBean. If notification is not
   * registered, then returns a false
   *
   * @param client client to listen for refresh notifications
   * @param type refresh notification type the client will use
   *
   * @return isRegistered boolean indicating if a notification is registered
   */
  static boolean isRefreshNotificationRegistered(NotificationListener client,
      RefreshNotificationType type) {
    boolean isRegistered = false;

    // get the notifications for the specified client...
    Map<RefreshNotificationType, Integer> notifications = null;
    synchronized (refreshClients) {
      notifications = (Map<RefreshNotificationType, Integer>) refreshClients.get(client);
    }

    // never registered before if null ...
    if (notifications != null) {
      // check for pre-existing refresh notification entry...
      Integer timerNotificationId = notifications.get(type);
      if (timerNotificationId != null) {
        isRegistered = true;
      }
    }

    return isRegistered;
  }

  /**
   * Validates refreshTimer has been registered without problems and attempts to re-register if
   * there is a problem.
   */
  static void validateRefreshTimer() {
    if (refreshTimerObjectName == null || refreshTimer == null) {
      createRefreshTimer();
    }

    raiseOnFailure(refreshTimer != null, "Failed to validate Refresh Timer");

    if (mbeanServer != null && !mbeanServer.isRegistered(refreshTimerObjectName)) {
      try {
        mbeanServer.registerMBean(refreshTimer, refreshTimerObjectName);
      } catch (JMException e) {
        logStackTrace(Level.WARN, e);
      } catch (JMRuntimeException e) {
        logStackTrace(Level.WARN, e);
      }
    }
  }

  /**
   * Initializes the timer for sending refresh notifications.
   */
  static void createRefreshTimer() {
    try {
      refreshTimer = new javax.management.timer.Timer();
      mbeanServer.registerMBean(refreshTimer, refreshTimerObjectName);

      refreshTimer.start();
    } catch (JMException e) {
      logStackTrace(Level.WARN, e,
          "Failed to create/register/start refresh timer.");
    } catch (JMRuntimeException e) {
      logStackTrace(Level.WARN, e,
          "Failed to create/register/start refresh timer.");
    } catch (Exception e) {
      logStackTrace(Level.WARN, e,
          "Failed to create/register/start refresh timer.");
    }
  }

  /**
   * Initializes the timer for sending refresh notifications.
   */
  static void stopRefreshTimer() {
    try {
      if (refreshTimer != null && mbeanServer != null) {
        mbeanServer.unregisterMBean(refreshTimerObjectName);

        refreshTimer.stop();
      }
    } catch (JMException e) {
      logStackTrace(Level.WARN, e);
    } catch (JMRuntimeException e) {
      logStackTrace(Level.WARN, e);
    } catch (Exception e) {
      logStackTrace(Level.DEBUG, e, "Failed to stop refresh timer for MBeanUtil");
    }
  }

  /**
   * 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.
   * TODO: clean this up
   *
   * @param value the potentially non-compliant ObjectName property
   * @return the value modified to be compliant as an ObjectName property
   */
  public static String makeCompliantMBeanNameProperty(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;
  }

  /**
   * Unregisters all GemFire MBeans and then releases the MBeanServer for garbage collection.
   */
  static void releaseMBeanServer() {
    try {
      // unregister all GemFire mbeans...
      Iterator iter = mbeanServer.queryNames(null, null).iterator();
      while (iter.hasNext()) {
        ObjectName name = (ObjectName) iter.next();
        if (name.getDomain().startsWith(DEFAULT_DOMAIN)) {
          unregisterMBean(name);
        }
      }

      // last, release the mbean server...
      MBeanServerFactory.releaseMBeanServer(mbeanServer);
      mbeanServer = null;
    } catch (JMRuntimeException e) {
      logStackTrace(Level.WARN, e);
    }
    /*
     * See #42391. Cleaning up the static maps which might be still holding references to
     * ManagedResources
     */
    synchronized (MBeanUtil.managedResources) {
      MBeanUtil.managedResources.clear();
    }
    synchronized (refreshClients) {
      refreshClients.clear();
    }
    /*
     * See #42391. Cleaning up the static maps which might be still holding references to
     * ManagedResources
     */
    synchronized (MBeanUtil.managedResources) {
      MBeanUtil.managedResources.clear();
    }
    synchronized (refreshClients) {
      refreshClients.clear();
    }
  }

  /**
   * Returns true if a MBean with given ObjectName is registered.
   *
   * @param objectName ObjectName to use for checking if MBean is registered
   * @return true if MBeanServer is not null & MBean with given ObjectName is registered with the
   *         MBeanServer
   */
  static boolean isRegistered(ObjectName objectName) {
    return mbeanServer != null && mbeanServer.isRegistered(objectName);
  }

  /**
   * Unregisters the identified MBean if it's registered.
   */
  static void unregisterMBean(ObjectName objectName) {
    try {
      if (mbeanServer != null && mbeanServer.isRegistered(objectName)) {
        mbeanServer.unregisterMBean(objectName);
      }
    } catch (MBeanRegistrationException e) {
      logStackTrace(Level.WARN, null,
          String.format("Failed while unregistering MBean with ObjectName : %s",
              new Object[] {objectName}));
    } catch (InstanceNotFoundException e) {
      logStackTrace(Level.WARN, null,
          String.format("While unregistering, could not find MBean with ObjectName : %s",
              new Object[] {objectName}));
    } catch (JMRuntimeException e) {
      logStackTrace(Level.WARN, null,
          String.format("Could not un-register MBean with ObjectName : %s",
              new Object[] {objectName}));
    }
  }

  static void unregisterMBean(ManagedResource resource) {
    if (resource != null) {
      unregisterMBean(resource.getObjectName());

      // call cleanup on managedResource here and not rely on listener
      // since it is possible that notification listener not deliver
      // all notifications of un-registration. If resource is
      // cleaned here, another call from the listener should be as good as a no-op
      cleanupResource(resource);
    }
  }

  // cleanup resource
  private static void cleanupResource(ManagedResource resource) {
    synchronized (MBeanUtil.managedResources) {
      MBeanUtil.managedResources.remove(resource.getObjectName());
    }
    resource.cleanupResource();

    // get the notifications for the specified client...
    Map<RefreshNotificationType, Integer> notifications = null;
    synchronized (refreshClients) {
      notifications = (Map<RefreshNotificationType, Integer>) refreshClients.remove(resource);
    }

    // never registered before if null ...
    // Also as of current, there is ever only 1 Notification type per
    // MBean, so we do need need a while loop here
    if (notifications != null) {

      // Fix for findbugs reported inefficiency with keySet().
      Set<Map.Entry<RefreshNotificationType, Integer>> entries = notifications.entrySet();

      for (Map.Entry<RefreshNotificationType, Integer> e : entries) {
        Integer timerNotificationId = e.getValue();
        if (null != timerNotificationId) {
          try {
            // found one, so let's remove it...
            refreshTimer.removeNotification(timerNotificationId);
          } catch (InstanceNotFoundException xptn) {
            // that's ok cause we just wanted to remove it anyway
            logStackTrace(Level.DEBUG, xptn);
          }
        }
      }

      try {
        if (mbeanServer != null && mbeanServer.isRegistered(refreshTimerObjectName)) {
          // remove client as a listener with MBeanServer...
          mbeanServer.removeNotificationListener(refreshTimerObjectName, // timer to listen to
              (NotificationListener) resource // the NotificationListener object
          );
        }
      } catch (ListenerNotFoundException xptn) {
        // should not happen since we already checked refreshTimerObjectName
        logStackTrace(Level.WARN, null, xptn.getMessage());
      } catch (InstanceNotFoundException xptn) {
        // should not happen since we already checked refreshTimerObjectName
        logStackTrace(Level.WARN, null,
            String.format("While unregistering, could not find MBean with ObjectName : %s",
                new Object[] {refreshTimerObjectName}));
      }
    }
  }

  // ----- borrowed the following from admin.internal.RemoteCommand -----
  /** Translates the path between Windows and UNIX. */
  static String getOSPath(String path) {
    if (pathIsWindows(path)) {
      return path.replace('/', '\\');
    } else {
      return path.replace('\\', '/');
    }
  }

  /** Returns true if the path is on Windows. */
  static boolean pathIsWindows(String path) {
    if (path != null && path.length() > 1) {
      return (Character.isLetter(path.charAt(0)) && path.charAt(1) == ':')
          || (path.startsWith("//") || path.startsWith("\\\\"));
    }
    return false;
  }

  static void registerServerNotificationListener() {
    if (mbeanServer == null) {
      return;
    }
    try {
      // the MBeanServerDelegate name is spec'ed as the following...
      ObjectName delegate = ObjectName.getInstance("JMImplementation:type=MBeanServerDelegate");
      mbeanServer.addNotificationListener(delegate, new NotificationListener() {
        @Override
        public void handleNotification(Notification notification, Object handback) {
          MBeanServerNotification serverNotification = (MBeanServerNotification) notification;
          if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION
              .equals(serverNotification.getType())) {
            ObjectName objectName = serverNotification.getMBeanName();
            synchronized (MBeanUtil.managedResources) {
              Object entry = MBeanUtil.managedResources.get(objectName);
              if (entry == null)
                return;
              if (!(entry instanceof ManagedResource)) {
                throw new ClassCastException(String.format("%s is not a ManagedResource",
                    new Object[] {entry.getClass().getName()}));
              }
              ManagedResource resource = (ManagedResource) entry;
              {
                // call cleanup on managedResource
                cleanupResource(resource);
              }
            }
          }
        }
      }, null, null);
    } catch (JMException e) {
      logStackTrace(Level.WARN, e,
          "Failed to register ServerNotificationListener.");
    } catch (JMRuntimeException e) {
      logStackTrace(Level.WARN, e,
          "Failed to register ServerNotificationListener.");
    }
  }

  /**
   * Logs the stack trace for the given Throwable if logger is initialized else prints the stack
   * trace using System.out.
   *
   * @param level severity level to log at
   * @param throwable Throwable to log stack trace for
   */
  public static void logStackTrace(Level level, Throwable throwable) {
    logStackTrace(level, throwable, null);
  }

  /**
   * Logs the stack trace for the given Throwable if logger is initialized else prints the stack
   * trace using System.out.
   *
   * @param level severity level to log at
   * @param throwable Throwable to log stack trace for
   * @param message user friendly error message to show
   */
  public static void logStackTrace(Level level, Throwable throwable, String message) {
    logger.log(level, message, throwable);
  }

  /**
   * Raises RuntimeAdminException with given 'message' if given 'condition' is false.
   *
   * @param condition condition to evaluate
   * @param message failure message
   */
  private static void raiseOnFailure(boolean condition, String message) {
    if (!condition) {
      throw new RuntimeAdminException(message);
    }
  }
}
