/*
 * 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.io.File;
import java.io.IOException;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.Notification;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.OperationsException;
import javax.management.ReflectionException;
import javax.management.modelmbean.ModelMBean;
import javax.management.remote.JMXConnectionNotification;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnectorServer;
import javax.rmi.ssl.SslRMIClientSocketFactory;

import mx4j.tools.adaptor.http.HttpAdaptor;
import org.apache.logging.log4j.Logger;

import org.apache.geode.GemFireException;
import org.apache.geode.GemFireIOException;
import org.apache.geode.LogWriter;
import org.apache.geode.SystemFailure;
import org.apache.geode.admin.AdminDistributedSystem;
import org.apache.geode.admin.AdminException;
import org.apache.geode.admin.jmx.Agent;
import org.apache.geode.admin.jmx.AgentConfig;
import org.apache.geode.admin.jmx.AgentFactory;
import org.apache.geode.distributed.internal.ClusterDistributionManager;
import org.apache.geode.internal.ExitCode;
import org.apache.geode.internal.GemFireVersion;
import org.apache.geode.internal.admin.remote.TailLogResponse;
import org.apache.geode.internal.logging.InternalLogWriter;
import org.apache.geode.internal.logging.LogConfig;
import org.apache.geode.internal.logging.LogConfigListener;
import org.apache.geode.internal.logging.LogConfigSupplier;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.logging.LogWriterFactory;
import org.apache.geode.internal.logging.LoggingSession;
import org.apache.geode.internal.logging.LoggingThread;
import org.apache.geode.internal.logging.log4j.LogMarker;
import org.apache.geode.internal.statistics.StatisticsConfig;

/**
 * The GemFire JMX Agent provides the ability to administrate one GemFire distributed system via
 * JMX.
 *
 * @since GemFire 3.5
 */
public class AgentImpl implements org.apache.geode.admin.jmx.Agent,
    org.apache.geode.admin.jmx.internal.ManagedResource, LogConfigSupplier {

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

  /**
   * MX4J HttpAdaptor only supports "basic" as an authentication method. Enabling HttpAdaptor
   * authentication ({@link AgentConfig#HTTP_AUTHENTICATION_ENABLED_NAME}) causes the browser to
   * require a login with username ({@link AgentConfig#HTTP_AUTHENTICATION_USER_NAME}) and password
   * ({@link AgentConfig#HTTP_AUTHENTICATION_PASSWORD_NAME}).
   */
  private static final String MX4J_HTTPADAPTOR_BASIC_AUTHENTICATION = "basic";

  /** JMX Service URL template for JMX/RMI Connector Server */
  private static final String JMX_SERVICE_URL = "service:jmx:rmi://{0}:{1}/jndi/rmi://{2}:{3}{4}";

  /**
   * Set third-party logging configration: MX4J, Jakarta Commons-Logging.
   */
  static {
    checkDebug();
    String commonsLog = System.getProperty("org.apache.commons.logging.log");
    if (commonsLog == null || commonsLog.length() == 0) {
      System.setProperty("org.apache.commons.logging.log",
          "org.apache.commons.logging.impl.SimpleLog");
    }
  }

  /** Enables mx4j tracing if Agent debugging is enabled. */
  private static void checkDebug() {
    try {
      if (Boolean.getBoolean("gfAgentDebug")) {
        mx4j.log.Log.setDefaultPriority(mx4j.log.Logger.TRACE); // .DEBUG
      }
    } 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 (Throwable t) {
      // 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();
      /* ignore */
    }
  }

  // -------------------------------------------------------------------------
  // Member variables
  // -------------------------------------------------------------------------

  /** This Agent's log writer */
  private InternalLogWriter logWriter;

  /** This Agent's JMX http adaptor from MX4J */
  private HttpAdaptor httpAdaptor;

  /** This Agent's RMI Connector Server from MX4J */
  private JMXConnectorServer rmiConnector;

  /** The name of the MBean manages this resource */
  private final String mbeanName;

  /** The ObjectName of the MBean that manages this resource */
  private final ObjectName objectName;

  /** The actual ModelMBean that manages this resource */
  private ModelMBean modelMBean;

  /** The configuration for this Agent */
  private final AgentConfigImpl agentConfig;

  /**
   * The <code>AdminDistributedSystem</code> this Agent is currently connected to or
   * <code>null</code>
   */
  private AdminDistributedSystem system;

  /** The agent's configuration file */
  private String propertyFile;

  /**
   * A lock object to guard the Connect and Disconnect calls being made on the agent for connections
   * to the DS
   **/
  private Object CONN_SYNC = new Object();

  protected MemberInfoWithStatsMBean memberInfoWithStatsMBean;

  private MBeanServer mBeanServer;

  private final LoggingSession loggingSession;
  private final Set<LogConfigListener> logConfigListeners = new HashSet<>();

  // -------------------------------------------------------------------------
  // Constructor(s)
  // -------------------------------------------------------------------------

  /**
   * Constructs a new Agent using the specified configuration.
   *
   * @param agentConfig instance of configuration for Agent
   * @throws org.apache.geode.admin.AdminException TODO-javadocs
   * @throws IllegalArgumentException if agentConfig is null
   */
  public AgentImpl(AgentConfigImpl agentConfig) throws AdminException, IllegalArgumentException {
    loggingSession = LoggingSession.create();

    shutdownHook = new LoggingThread("Shutdown", false, () -> disconnectFromSystem());
    addShutdownHook();
    if (agentConfig == null) {
      throw new IllegalArgumentException(
          "AgentConfig must not be null");
    }
    this.agentConfig = (AgentConfigImpl) agentConfig;
    this.mbeanName = MBEAN_NAME_PREFIX + MBeanUtil.makeCompliantMBeanNameProperty("Agent");

    try {
      this.objectName = new ObjectName(this.mbeanName);
    } catch (MalformedObjectNameException ex) {
      String s = String.format("While creating ObjectName: %s",
          new Object[] {this.mbeanName});
      throw new AdminException(s, ex);
    }

    this.propertyFile = this.agentConfig.getPropertyFile().getAbsolutePath();

    // bind address only affects how the Agent VM connects to the system...
    // It should be set only once in the agent lifecycle
    this.agentConfig.setBindAddress(getBindAddress());

    // LOG: create LogWriterAppender and LogWriterLogger
    initLogWriter();

    mBeanServer = MBeanUtil.start();

    MBeanUtil.createMBean(this);

    initializeHelperMbean();
  }

  private void initializeHelperMbean() {
    try {
      memberInfoWithStatsMBean = new MemberInfoWithStatsMBean(this);

      MBeanServer mbs = getMBeanServer();
      mbs.registerMBean(memberInfoWithStatsMBean, memberInfoWithStatsMBean.getObjectName());
      /*
       * We are not re-throwing these exceptions as failure create/register the GemFireTypesWrapper
       * will not stop the Agent from working. But we are logging it as it could be an indication of
       * some problem. Also not creating Localized String for the exception.
       */
    } catch (OperationsException e) {
      logger.info("Failed to initialize MemberInfoWithStatsMBean.", e);
    } catch (MBeanRegistrationException e) {
      logger.info("Failed to initialize MemberInfoWithStatsMBean.", e);
    } catch (AdminException e) {
      logger.info("Failed to initialize MemberInfoWithStatsMBean.", e);
    }
  }

  // -------------------------------------------------------------------------
  // Public operations
  // -------------------------------------------------------------------------

  @Override
  public AgentConfig getConfig() {
    return this.agentConfig;
  }

  @Override
  public AdminDistributedSystem getDistributedSystem() {
    return this.system;
  }

  /**
   * Persists the current Agent configuration to its property file.
   *
   * @throws GemFireIOException if unable to persist the configuration to props
   * @see #getPropertyFile
   */
  @Override
  public void saveProperties() {
    throw new GemFireIOException("saveProperties is no longer supported for security reasons");
  }

  /**
   * Starts the jmx agent
   */
  @Override
  public void start() {
    checkDebug();

    this.agentConfig.validate();

    if (mBeanServer == null) {
      mBeanServer = MBeanUtil.start();
    }

    try {
      startHttpAdaptor();
    } catch (StartupException e) {
      loggingSession.stopSession();
      loggingSession.shutdown();
      throw e;
    }

    try {
      startRMIConnectorServer();
    } catch (StartupException e) {
      stopHttpAdaptor();
      loggingSession.stopSession();
      loggingSession.shutdown();
      throw e;
    }

    try {
      startSnmpAdaptor();
    } catch (StartupException e) {
      stopRMIConnectorServer();
      stopHttpAdaptor();
      loggingSession.stopSession();
      loggingSession.shutdown();
      throw e;
    }

    if (this.agentConfig.getAutoConnect()) {
      try {
        connectToSystem();
        /*
         * Call Agent.stop() if connectToSystem() fails. This should clean up agent-DS connection &
         * stop all the HTTP/RMI/SNMP adapters started earlier.
         */
      } catch (AdminException ex) {
        logger.error("auto connect failed:  {}",
            ex.getMessage());
        this.stop();
        throw new StartupException(ex);
      } catch (MalformedObjectNameException ex) {
        String autoConnectFailed = "auto connect failed:  {}";
        logger.error(autoConnectFailed, ex.getMessage());
        this.stop();
        throw new StartupException(new AdminException(
            String.format("auto connect failed: %s", ex.getMessage()), ex));
      }
    } // getAutoConnect

    logger.info("GemFire JMX Agent is running...");

    if (memberInfoWithStatsMBean == null) {
      initializeHelperMbean();
    }
  }

  /**
   * Deregisters everything this Agent registered and releases the MBeanServer.
   */
  @Override
  public void stop() {
    try {
      logger.info("Stopping JMX agent");

      loggingSession.stopSession();

      // stop the GemFire Distributed System
      stopDistributedSystem();

      // stop all JMX Adaptors and Connectors...
      stopHttpAdaptor();
      stopRMIConnectorServer();
      memberInfoWithStatsMBean = null;
      stopSnmpAdaptor();

      // release the MBeanServer for cleanup...
      MBeanUtil.stop();
      mBeanServer = null;

      // remove the register shutdown hook which disconnects the Agent from the Distributed System
      // upon JVM shutdown
      removeShutdownHook();

      logger.info("Agent has stopped");
    } finally {
      loggingSession.shutdown();
    }

  }

  private void stopDistributedSystem() {
    // disconnect from the distributed system...
    try {
      disconnectFromSystem();
    } catch (Exception e) {
      // disconnectFromSystem already prints any Exceptions
    } catch (VirtualMachineError err) {
      SystemFailure.initiateFailure(err);
      throw err;
    } catch (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();
    }
  }

  @Override
  public ObjectName manageDistributedSystem() throws MalformedObjectNameException {
    synchronized (CONN_SYNC) {
      if (isConnected()) {
        return ((AdminDistributedSystemJmxImpl) this.system).getObjectName();
      }
      return null;
    }
  }

  /**
   * Connects to the DistributedSystem currently described by this Agent's attributes for
   * administration and monitoring.
   *
   * @return the object name of the system that the Agent is now connected to
   */
  @Override
  @edu.umd.cs.findbugs.annotations.SuppressWarnings(
      value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD",
      justification = "This is only a style warning.")
  public ObjectName connectToSystem() throws AdminException, MalformedObjectNameException {
    synchronized (CONN_SYNC) {
      try {
        if (isConnected()) {
          return ((AdminDistributedSystemJmxImpl) this.system).getObjectName();
        }

        ClusterDistributionManager.setIsDedicatedAdminVM(true);

        AdminDistributedSystemJmxImpl systemJmx = (AdminDistributedSystemJmxImpl) this.system;
        if (systemJmx == null) {
          systemJmx = (AdminDistributedSystemJmxImpl) createDistributedSystem(this.agentConfig);
          this.system = systemJmx;
        }
        systemJmx.connect(this.logWriter);

        return new ObjectName(systemJmx.getMBeanName());
      } catch (AdminException e) {
        logger.warn(e.getMessage(), e);
        throw e;
      } catch (RuntimeException e) {
        logger.warn(e.getMessage(), 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 (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();
        logger.error(e.getMessage(), e);
        throw e;
      }
    }
  }

  /**
   * Disconnects from the current DistributedSystem (if connected to one).
   */
  @Override
  @edu.umd.cs.findbugs.annotations.SuppressWarnings(
      value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD",
      justification = "This is only a style warning.")
  public void disconnectFromSystem() {
    synchronized (CONN_SYNC) {
      try {
        if (this.system == null || !this.system.isConnected()) {
          return;
        }
        ((AdminDistributedSystemJmxImpl) this.system).disconnect();
      } catch (RuntimeException e) {
        logger.warn(e.getMessage(), 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 (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();
        logger.warn(e.getMessage(), e);
        throw e;
      } finally {
        ClusterDistributionManager.setIsDedicatedAdminVM(false);
      }
    }
  }

  /**
   * Retrieves a displayable snapshot of this Agent's log.
   *
   * @return snapshot of the current log
   */
  public String getLog() {
    File childLogFile = loggingSession.getLogFile().isPresent()
        ? loggingSession.getLogFile().get().getChildLogFile() : null;
    String childTail = tailFile(childLogFile);
    String mainTail = tailFile(new File(this.agentConfig.getLogFile()));
    if (childTail == null && mainTail == null) {
      return "No log file configured, log messages will be directed to stdout.";
    } else {
      StringBuffer result = new StringBuffer();
      if (mainTail != null) {
        result.append(mainTail);
      }
      if (childTail != null) {
        result
            .append("\n" + "-------------------- tail of child log --------------------" + "\n");
        result.append(childTail);
      }
      return result.toString();
    }
  }

  /**
   * Retrieves display-friendly GemFire version information.
   */
  public String getVersion() {
    return GemFireVersion.asString();
  }

  // -------------------------------------------------------------------------
  // Public attribute accessors/mutators
  // -------------------------------------------------------------------------

  /** Returns true if this Agent is currently connected to a system. */
  @Override
  public boolean isConnected() {
    boolean result = false;
    synchronized (CONN_SYNC) {
      result = ((this.system != null) && this.system.isConnected());
    }
    return result;
  }

  /**
   * Gets the agent's property file. This is the file it will use when saving its configuration. It
   * was also used when the agent started to initialize its configuration.
   *
   * @return the agent's property file
   */
  public String getPropertyFile() {
    return this.propertyFile;
  }

  /**
   * Sets the agent's property file.
   *
   * @param value the name of the file to save the agent properties in.
   * @throws IllegalArgumentException if the specified file is a directory.
   * @throws IllegalArgumentException if the specified file's parent is not an existing directory.
   */
  public void setPropertyFile(String value) {
    File f = (new File(value)).getAbsoluteFile();
    if (f.isDirectory()) {
      throw new IllegalArgumentException(
          String.format("The file %s is a directory.", f));
    }
    File parent = f.getParentFile();
    if (parent != null) {
      if (!parent.isDirectory()) {
        throw new IllegalArgumentException(
            String.format("The directory %s does not exist.", parent));
      }
    }
    this.propertyFile = f.getPath();
  }

  /**
   * Gets the mcastAddress of the distributed system that this Agent is managing.
   *
   * @return The mcastAddress value
   */
  public String getMcastAddress() {
    return this.agentConfig.getMcastAddress();
  }

  /**
   * Sets the mcastAddress of the distributed system that this Agent is managing.
   *
   * @param mcastAddress The new mcastAddress value
   */
  public void setMcastAddress(String mcastAddress) {
    this.agentConfig.setMcastAddress(mcastAddress);
  }

  /**
   * Gets the mcastPort of the distributed system that this Agent is managing.
   *
   * @return The mcastPort value
   */
  public int getMcastPort() {
    return this.agentConfig.getMcastPort();
  }

  /**
   * Sets the mcastPort of the distributed system that this Agent is managing.
   *
   * @param mcastPort The new mcastPort value
   */
  public void setMcastPort(int mcastPort) {
    this.agentConfig.setMcastPort(mcastPort);
  }

  /**
   * Gets the locators of the distributed system that this Agent is managing.
   * <p>
   * Format is a comma-delimited list of "host[port]" entries.
   *
   * @return The locators value
   */
  public String getLocators() {
    return this.agentConfig.getLocators();
  }

  /**
   * Sets the locators of the distributed system that this Agent is managing.
   * <p>
   * Format is a comma-delimited list of "host[port]" entries.
   *
   * @param locators The new locators value
   */
  public void setLocators(String locators) {
    this.agentConfig.setLocators(locators);
  }

  /**
   * Gets the membership UDP port range in the distributed system that this Agent is monitoring.
   * <p>
   * This range is given as two numbers separated by a minus sign like "min-max"
   *
   * @return membership UDP port range
   */
  public String getMembershipPortRange() {
    return this.agentConfig.getMembershipPortRange();
  }

  /**
   * Sets the membership UDP port range in the distributed system that this Agent is monitoring.
   * <p>
   * This range is given as two numbers separated by a minus sign like "min-max"
   *
   * @param membershipPortRange membership UDP port range
   */
  public void setMembershipPortRange(String membershipPortRange) {
    this.agentConfig.setMembershipPortRange(membershipPortRange);
  }

  /**
   * Gets the bindAddress of the distributed system that this Agent is managing.
   *
   * @return The bindAddress value
   */
  public String getBindAddress() {
    return this.agentConfig.getBindAddress();
  }

  /**
   * Sets the bindAddress of the distributed system that this Agent is managing.
   *
   * @param bindAddress The new bindAddress value
   */
  public void setBindAddress(String bindAddress) {
    this.agentConfig.setBindAddress(bindAddress);
  }

  /**
   * Retrieves the command that the DistributedSystem will use to perform remote manipulation of
   * config files and log files.
   *
   * @return the remote command for DistributedSystem
   */
  public String getRemoteCommand() {
    return this.agentConfig.getRemoteCommand();
  }

  /**
   * Sets the command that the DistributedSystem will use to perform remote manipulation of config
   * files and log files.
   *
   * @param remoteCommand the remote command for DistributedSystem
   */
  public void setRemoteCommand(String remoteCommand) {
    this.agentConfig.setRemoteCommand(remoteCommand);
  }

  /** Returns the system identity for the DistributedSystem */
  public String getSystemId() {
    return this.agentConfig.getSystemId();
  }

  /** Sets the system identity for the DistributedSystem */
  public void setSystemId(String systemId) {
    this.agentConfig.setSystemId(systemId);
  }

  /**
   * Gets the logFileSizeLimit in megabytes of this Agent. Zero indicates no limit.
   *
   * @return The logFileSizeLimit value
   */
  public int getLogFileSizeLimit() {
    return this.agentConfig.getLogFileSizeLimit();
  }

  /**
   * Sets the logFileSizeLimit in megabytes of this Agent. Zero indicates no limit.
   *
   * @param logFileSizeLimit The new logFileSizeLimit value
   */
  public void setLogFileSizeLimit(int logFileSizeLimit) {
    this.agentConfig.setLogFileSizeLimit(logFileSizeLimit);
    logConfigChanged();
  }

  /**
   * Gets the logDiskSpaceLimit in megabytes of this Agent. Zero indicates no limit.
   *
   * @return The logDiskSpaceLimit value
   */
  public int getLogDiskSpaceLimit() {
    return this.agentConfig.getLogDiskSpaceLimit();
  }

  /**
   * Sets the logDiskSpaceLimit in megabytes of this Agent. Zero indicates no limit.
   *
   * @param logDiskSpaceLimit The new logDiskSpaceLimit value
   */
  public void setLogDiskSpaceLimit(int logDiskSpaceLimit) {
    this.agentConfig.setLogDiskSpaceLimit(logDiskSpaceLimit);
    logConfigChanged();
  }

  /**
   * Gets the logFile name for this Agent to log to.
   *
   * @return The logFile value
   */
  public String getLogFile() {
    return this.agentConfig.getLogFile();
  }

  /**
   * Sets the logFile name for this Agent to log to.
   *
   * @param logFile The new logFile value
   */
  public void setLogFile(String logFile) {
    this.agentConfig.setLogFile(logFile);
    logConfigChanged();
  }

  /**
   * Gets the logLevel of this Agent.
   *
   * @return The logLevel value
   */
  public String getLogLevel() {
    return this.agentConfig.getLogLevel();
  }

  /**
   * Sets the logLevel of this Agent.
   *
   * @param logLevel The new logLevel value
   */
  public void setLogLevel(String logLevel) {
    this.agentConfig.setLogLevel(logLevel);
    logConfigChanged();
  }

  /** Returns true if the Agent is set to auto connect to a system. */
  public boolean getAutoConnect() {
    return this.agentConfig.getAutoConnect();
  }

  /** Returns true if the Agent is set to auto connect to a system. */
  public boolean isAutoConnect() {
    return this.agentConfig.getAutoConnect();
  }

  /** Sets or unsets the option to auto connect to a system. */
  public void setAutoConnect(boolean v) {
    this.agentConfig.setAutoConnect(v);
  }

  /**
   * Returns the address (URL) on which the RMI connector server runs or <code>null</code> if the
   * RMI connector server has not been started. This method is used primarily for testing purposes.
   *
   * @see JMXConnectorServer#getAddress()
   */
  public JMXServiceURL getRMIAddress() {
    if (this.rmiConnector != null) {
      return this.rmiConnector.getAddress();

    } else {
      return null;
    }
  }

  /**
   * Gets the configuration for this Agent.
   *
   * @return the configuration for this Agent
   */
  protected AgentConfig getAgentConfig() {
    return this.agentConfig;
  }

  // -------------------------------------------------------------------------
  // Internal implementation methods
  // -------------------------------------------------------------------------

  /** Returns the tail of the system log specified by <code>File</code>. */
  private String tailFile(File f) {
    try {
      return TailLogResponse.tailSystemLog(f);
    } catch (IOException ex) {
      return String.format("Could not tail %s because: %s",
          new Object[] {f, ex});
    }
  }

  /**
   * Returns the active MBeanServer which has any GemFire MBeans registered.
   *
   * @return the GemFire mbeanServer
   */
  @Override
  public MBeanServer getMBeanServer() {
    return mBeanServer;
  }

  /**
   * Gets the current instance of LogWriter for logging
   *
   * @return the logWriter
   */
  @Override
  public LogWriter getLogWriter() {
    return this.logWriter;
  }

  private final Thread shutdownHook;

  /**
   * Adds a ShutdownHook to the Agent for cleaning up any resources
   */
  private void addShutdownHook() {
    if (!Boolean.getBoolean(
        org.apache.geode.distributed.internal.InternalDistributedSystem.DISABLE_SHUTDOWN_HOOK_PROPERTY)) {
      Runtime.getRuntime().addShutdownHook(shutdownHook);
    }
  }

  private void removeShutdownHook() {
    if (!Boolean.getBoolean(
        org.apache.geode.distributed.internal.InternalDistributedSystem.DISABLE_SHUTDOWN_HOOK_PROPERTY)) {
      Runtime.getRuntime().removeShutdownHook(shutdownHook);
    }
  }

  /**
   * Creates a LogWriterI18n for this Agent to use in logging.
   */
  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RV_RETURN_VALUE_IGNORED_BAD_PRACTICE",
      justification = "Return value for file delete is not important here.")
  private void initLogWriter() throws org.apache.geode.admin.AdminException {
    loggingSession.createSession(this);

    final LogConfig logConfig = this.agentConfig.createLogConfig();

    // LOG: create logWriterAppender here
    loggingSession.startSession();

    // LOG: look in AgentConfigImpl for existing LogWriter to use
    InternalLogWriter existingLogWriter = this.agentConfig.getInternalLogWriter();
    if (existingLogWriter != null) {
      this.logWriter = existingLogWriter;
    } else {
      // LOG: create LogWriterLogger
      this.logWriter = LogWriterFactory.createLogWriterLogger(logConfig, false);
      // Set this log writer in AgentConfigImpl
      this.agentConfig.setInternalLogWriter(this.logWriter);
    }

    // LOG: create logWriter here
    this.logWriter = LogWriterFactory.createLogWriterLogger(logConfig, false);

    // Set this log writer in AgentConfig
    this.agentConfig.setInternalLogWriter(this.logWriter);

    // LOG:CONFIG: changed next three statements from config to info
    logger.info(LogMarker.CONFIG_MARKER,
        String.format("Agent config property file name: %s",
            AgentConfigImpl.retrievePropertyFile()));
    logger.info(LogMarker.CONFIG_MARKER, this.agentConfig.getPropertyFileDescription());
    logger.info(LogMarker.CONFIG_MARKER, this.agentConfig.toPropertiesAsString());
  }

  /**
   * Stops the HttpAdaptor and its XsltProcessor. Unregisters the associated MBeans.
   */
  private void stopHttpAdaptor() {
    if (!this.agentConfig.isHttpEnabled())
      return;

    // stop the adaptor...
    try {
      this.httpAdaptor.stop();
    } catch (Exception e) {
      logger.warn(e.getMessage(), e);
    }

    try {
      MBeanUtil.unregisterMBean(getHttpAdaptorName());
      MBeanUtil.unregisterMBean(getXsltProcessorName());
    } catch (MalformedObjectNameException e) {
      logger.warn(e.getMessage(), e);
    }
  }

  /** Stops the RMIConnectorServer and unregisters its MBean. */
  private void stopRMIConnectorServer() {
    if (!this.agentConfig.isRmiEnabled())
      return;

    // stop the RMI Connector server...
    try {
      this.rmiConnector.stop();
    } catch (Exception e) {
      logger.warn(e.getMessage(), e);
    }

    try {
      ObjectName rmiRegistryNamingName = getRMIRegistryNamingName();
      if (this.agentConfig.isRmiRegistryEnabled()
          && mBeanServer.isRegistered(rmiRegistryNamingName)) {
        String[] empty = new String[0];
        mBeanServer.invoke(rmiRegistryNamingName, "stop", empty, empty);
        MBeanUtil.unregisterMBean(rmiRegistryNamingName);
      }
    } catch (MalformedObjectNameException e) {
      logger.warn(e.getMessage(), e);
    } catch (InstanceNotFoundException e) {
      logger.warn(e.getMessage(), e);
    } catch (ReflectionException e) {
      logger.warn(e.getMessage(), e);
    } catch (MBeanException e) {
      logger.warn(e.getMessage(), e);
    }

    try {
      ObjectName rmiConnectorServerName = getRMIConnectorServerName();
      if (mBeanServer.isRegistered(rmiConnectorServerName)) {
        MBeanUtil.unregisterMBean(rmiConnectorServerName);
      }
    } catch (MalformedObjectNameException e) {
      logger.warn(e.getMessage(), e);
    }
  }

  /** Stops the SnmpAdaptor and unregisters its MBean. */
  private void stopSnmpAdaptor() {
    if (!this.agentConfig.isSnmpEnabled())
      return;

    // stop the SnmpAdaptor...
    try {
      getMBeanServer().invoke(getSnmpAdaptorName(), "unbind", new Object[0], new String[0]);
    } catch (Exception e) {
      logger.warn(e.getMessage(), e);
    }

    try {
      MBeanUtil.unregisterMBean(getSnmpAdaptorName());
    } catch (MalformedObjectNameException e) {
      logger.warn(e.getMessage(), e);
    }
  }

  /** Returns the JMX ObjectName for the RMI registry Naming MBean. */
  private ObjectName getRMIRegistryNamingName()
      throws javax.management.MalformedObjectNameException {
    return ObjectName.getInstance("naming:type=rmiregistry");
  }

  /** Returns the JMX ObjectName for the HttpAdaptor. */
  private ObjectName getHttpAdaptorName() throws javax.management.MalformedObjectNameException {
    return new ObjectName("Server:name=HttpAdaptor");
  }

  /** Returns the JMX ObjectName for the RMIConnectorServer. */
  private ObjectName getRMIConnectorServerName()
      throws javax.management.MalformedObjectNameException {
    return new ObjectName("connectors:protocol=rmi");
  }

  /** Returns the JMX ObjectName for the SnmpAdaptor. */
  private ObjectName getSnmpAdaptorName() throws javax.management.MalformedObjectNameException {
    return new ObjectName("Adaptors:protocol=SNMP");
  }

  /** Returns the JMX ObjectName for the HttpAdaptor's XsltProcessor. */
  private ObjectName getXsltProcessorName() throws javax.management.MalformedObjectNameException {
    return new ObjectName("Server:name=XSLTProcessor");
  }

  // -------------------------------------------------------------------------
  // Factory method for creating DistributedSystem
  // -------------------------------------------------------------------------

  /**
   * Creates and connects to a <code>DistributedSystem</code>.
   *
   */
  private AdminDistributedSystem createDistributedSystem(AgentConfigImpl config)
      throws org.apache.geode.admin.AdminException {
    return new AdminDistributedSystemJmxImpl(config);
  }

  // -------------------------------------------------------------------------
  // Agent main
  // -------------------------------------------------------------------------

  /**
   * Command-line main for running the GemFire Management Agent.
   * <p>
   * Accepts command-line arguments matching the options in {@link AgentConfig} and
   * {@link org.apache.geode.admin.DistributedSystemConfig}.
   * <p>
   * <code>AgentConfig</code> will convert -Jarguments to System properties.
   */
  public static void main(String[] args) {
    SystemFailure.loadEmergencyClasses();

    AgentConfigImpl ac;
    try {
      ac = new AgentConfigImpl(args);
    } catch (RuntimeException ex) {
      System.err
          .println(String.format("Failed reading configuration: %s", ex));
      ExitCode.FATAL.doSystemExit();
      return;
    }

    try {
      Agent agent = AgentFactory.getAgent(ac);
      agent.start();

    } 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 (Throwable t) {
      // 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();
      t.printStackTrace();
      ExitCode.FATAL.doSystemExit();
    }
  }

  // -------------------------------------------------------------------------
  // MX4J Connectors/Adaptors
  // -------------------------------------------------------------------------

  private void createRMIRegistry() throws Exception {
    if (!this.agentConfig.isRmiRegistryEnabled()) {
      return;
    }
    MBeanServer mbs = getMBeanServer();
    String host = this.agentConfig.getRmiBindAddress();
    int port = this.agentConfig.getRmiPort();

    /*
     * Register and start the rmi-registry naming MBean, which is needed by JSR 160
     * RMIConnectorServer
     */
    ObjectName registryName = getRMIRegistryNamingName();
    try {
      RMIRegistryService registryNamingService = null;
      if (host != null && !("".equals(host.trim()))) {
        registryNamingService = new RMIRegistryService(host, port);
      } else {
        registryNamingService = new RMIRegistryService(port);
      }
      mbs.registerMBean(registryNamingService, registryName);
    } catch (javax.management.InstanceAlreadyExistsException e) {
      logger.info("{}  is already registered.",
          registryName);
    }
    mbs.invoke(registryName, "start", null, null);
  }

  /**
   * Defines and starts the JMX RMIConnector and service.
   * <p>
   * If {@link AgentConfig#isRmiEnabled} returns false, then this adaptor will not be started.
   */
  private void startRMIConnectorServer() {
    if (!this.agentConfig.isRmiEnabled())
      return;

    String rmiBindAddress = this.agentConfig.getRmiBindAddress();

    // Set RMI Stubs to use the given RMI Bind Address
    // Default bindAddress is "", if none is set - ignore if not set
    // If java.rmi.server.hostname property is specified then
    // that override is not changed
    String rmiStubServerNameKey = "java.rmi.server.hostname";
    String overrideHostName = System.getProperty(rmiStubServerNameKey);
    if ((overrideHostName == null || overrideHostName.trim().length() == 0)
        && (rmiBindAddress != null && rmiBindAddress.trim().length() != 0)) {
      System.setProperty(rmiStubServerNameKey, rmiBindAddress);
      logger.info((new StringBuilder("Setting ").append(rmiStubServerNameKey).append(" = ")
          .append(rmiBindAddress).toString()));
    }

    try {
      createRMIRegistry();
      ObjectName objName = getRMIConnectorServerName();

      // make sure this adaptor is not already registered...
      if (getMBeanServer().isRegistered(objName)) {
        // dunno how we got here...
        logger.info("RMIConnectorServer already registered as {}", objName);
        return;
      }

      /*
       * url defined as: service:jmx:protocol:sap where 1. protocol: rmi 2. sap is:
       * [host[:port]][url-path] where host: rmi-binding-address port: rmi-server-port url-path:
       * /jndi/rmi://<rmi-binding-address>:<rmi-port><JNDI_NAME>
       */
      String urlString = null;
      String connectorServerHost = "";
      int connectorServerPort = this.agentConfig.getRmiServerPort();
      String rmiRegistryHost = "";
      int rmiRegistryPort = this.agentConfig.getRmiPort();

      // Set registryHost to localhost if not specified
      // RMI stubs would use a default IP if namingHost is left empty
      if (rmiBindAddress == null || rmiBindAddress.trim().length() == 0) {
        connectorServerHost = "localhost";
        rmiRegistryHost = "";
      } else {
        connectorServerHost = applyRFC2732(rmiBindAddress);
        rmiRegistryHost = connectorServerHost;
      }

      urlString = MessageFormat.format(AgentImpl.JMX_SERVICE_URL, connectorServerHost,
          String.valueOf(connectorServerPort), rmiRegistryHost, String.valueOf(rmiRegistryPort),
          JNDI_NAME);

      logger.debug("JMX Service URL string is : \"{}\"", urlString);

      // The address of the connector
      JMXServiceURL url = new JMXServiceURL(urlString);

      Map<String, Object> env = new HashMap<String, Object>();

      RMIServerSocketFactory ssf = new MX4JServerSocketFactory(this.agentConfig.isAgentSSLEnabled(), // true,
          this.agentConfig.isAgentSSLRequireAuth(), // true,
          this.agentConfig.getAgentSSLProtocols(), // "any",
          this.agentConfig.getAgentSSLCiphers(), // "any",
          this.agentConfig.getRmiBindAddress(), 10, // backlog
          this.agentConfig.getGfSecurityProperties());
      env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, ssf);

      if (this.agentConfig.isAgentSSLEnabled()) {
        RMIClientSocketFactory csf = new SslRMIClientSocketFactory();
        env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, csf);
      }

      MBeanServer mbs = null; // will be set by registering w/ mbeanServer
      this.rmiConnector = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);

      // for cleanup
      this.rmiConnector.addNotificationListener(new ConnectionNotificationAdapter(),
          new ConnectionNotificationFilterImpl(), this);

      // Register the JMXConnectorServer in the MBeanServer
      getMBeanServer().registerMBean(this.rmiConnector, objName);

      // Start the JMXConnectorServer
      this.rmiConnector.start();
    } 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 (Throwable t) {
      // 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();
      logger.error("Failed to start RMIConnectorServer:", t);
      throw new StartupException(
          "Failed to start RMI service, verify RMI configuration properties", t);
    }
  }

  /**
   * Starts the optional third-party AdventNet SNMP Adaptor.
   * <p>
   * If {@link AgentConfig#isSnmpEnabled} returns false, then this adaptor will not be started.
   */
  private void startSnmpAdaptor() {
    if (!this.agentConfig.isSnmpEnabled())
      return;
    try {
      ObjectName objName = getSnmpAdaptorName();

      // make sure this adaptor is not already registered...
      if (getMBeanServer().isRegistered(objName)) {
        // dunno how we got here...
        logger.info("SnmpAdaptor already registered as  {}", objName);
        return;
      }

      String className = "com.adventnet.adaptors.snmp.snmpsupport.SmartSnmpAdaptor";
      String snmpDir = this.agentConfig.getSnmpDirectory();
      // ex:/merry2/users/klund/agent

      // validate the directory...
      if (snmpDir == null || snmpDir.length() == 0) {
        throw new IllegalArgumentException(
            "snmp-directory must be specified because SNMP is enabled");
      }
      File root = new File(snmpDir);
      if (!root.exists()) {
        throw new IllegalArgumentException(
            "snmp-directory does not exist");
      }

      // create the adaptor...
      String[] sigs = new String[] {"java.lang.String"};
      Object[] args = new Object[] {snmpDir};

      String bindAddress = this.agentConfig.getSnmpBindAddress();
      if (bindAddress != null && bindAddress.length() > 0) {
        sigs = new String[] {"java.lang.String", sigs[0]};
        args = new Object[] {bindAddress, args[0]};
      }

      // go...
      getMBeanServer().createMBean(className, objName, args, sigs);
    } 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 (Throwable t) {
      // 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();
      logger.error("Failed to start SnmpAdaptor:  {}", t.getMessage());
      throw new StartupException(String.format("Failed to start SnmpAdaptor: %s",
          t.getMessage()), t);
    }
  }

  /**
   * Defines and starts the JMX Http Adaptor service from MX4J.
   * <p>
   * If {@link AgentConfig#isHttpEnabled} returns false, then this adaptor will not be started.
   */
  private void startHttpAdaptor() {
    if (!this.agentConfig.isHttpEnabled())
      return;
    try {
      ObjectName objName = getHttpAdaptorName();

      // make sure this adaptor is not already registered...
      if (getMBeanServer().isRegistered(objName)) {
        // dunno how we got here...
        logger.info("HttpAdaptor already registered as  {}", objName);
        return;
      }

      this.httpAdaptor = new HttpAdaptor();

      // validate and set host and port values...
      if (this.agentConfig.getHttpPort() > 0) {
        this.httpAdaptor.setPort(this.agentConfig.getHttpPort());
        logger.info(LogMarker.CONFIG_MARKER,
            "HTTP adaptor listening on port: {}",
            this.agentConfig.getHttpPort());
      } else {
        logger.error("Incorrect port value  {}",
            this.agentConfig.getHttpPort());
      }

      if (this.agentConfig.getHttpBindAddress() != null) {
        String host = this.agentConfig.getHttpBindAddress();
        logger.info(LogMarker.CONFIG_MARKER, "HTTP adaptor listening on address:  {}", host);
        this.httpAdaptor.setHost(host);
      } else {
        logger.error("Incorrect null hostname");
      }

      // SSL support...
      MX4JServerSocketFactory socketFactory =
          new MX4JServerSocketFactory(this.agentConfig.isAgentSSLEnabled(),
              this.agentConfig.isHttpSSLRequireAuth(), this.agentConfig.getAgentSSLProtocols(),
              this.agentConfig.getAgentSSLCiphers(), this.agentConfig.getGfSecurityProperties());
      this.httpAdaptor.setSocketFactory(socketFactory);

      // authentication (user login) support...
      if (this.agentConfig.isHttpAuthEnabled()) {
        // this pops up a login dialog from the browser...
        this.httpAdaptor.setAuthenticationMethod(MX4J_HTTPADAPTOR_BASIC_AUTHENTICATION); // only
                                                                                         // basic
                                                                                         // works

        this.httpAdaptor.addAuthorization(this.agentConfig.getHttpAuthUser(),
            this.agentConfig.getHttpAuthPassword());
      }

      // add the XsltProcessor...
      this.httpAdaptor.setProcessorName(createXsltProcessor());

      // register the HttpAdaptor and snap on the XsltProcessor...
      getMBeanServer().registerMBean(this.httpAdaptor, objName);
      this.httpAdaptor.start();
    } 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 (Throwable t) {
      // 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();
      logger.error("Failed to start HttpAdaptor:  {}", t.getMessage());
      throw new StartupException(String.format("Failed to start HttpAdaptor: %s",
          t.getMessage()), t);
    }
  }

  /**
   * Defines and starts the Xslt Processor helper service for the Http Adaptor.
   */
  private ObjectName createXsltProcessor() throws javax.management.JMException {
    ObjectName objName = getXsltProcessorName();

    // make sure this mbean is not already registered...
    if (getMBeanServer().isRegistered(objName)) {
      // dunno how we got here...
      logger.info("XsltProcessor already registered as  {}", objName);
      return objName;
    }

    getMBeanServer().registerMBean(new mx4j.tools.adaptor.http.XSLTProcessor(), objName);
    return objName;
  }

  // -------------------------------------------------------------------------
  // SSL configuration for GemFire
  // -------------------------------------------------------------------------
  public boolean isSSLEnabled() {
    return this.agentConfig.isSSLEnabled();
  }

  public void setSSLEnabled(boolean enabled) {
    this.agentConfig.setSSLEnabled(enabled);
  }

  public String getSSLProtocols() {
    return this.agentConfig.getSSLProtocols();
  }

  public void setSSLProtocols(String protocols) {
    this.agentConfig.setSSLProtocols(protocols);
  }

  public String getSSLCiphers() {
    return this.agentConfig.getSSLCiphers();
  }

  public void setSSLCiphers(String ciphers) {
    this.agentConfig.setSSLCiphers(ciphers);
  }

  public boolean isSSLAuthenticationRequired() {
    return this.agentConfig.isSSLAuthenticationRequired();
  }

  public void setSSLAuthenticationRequired(boolean authRequired) {
    this.agentConfig.setSSLAuthenticationRequired(authRequired);
  }

  public Properties getSSLProperties() {
    return this.agentConfig.getSSLProperties();
  }

  public void setSSLProperties(Properties sslProperties) {
    this.agentConfig.setSSLProperties(sslProperties);
  }

  public void addSSLProperty(String key, String value) {
    this.agentConfig.addSSLProperty(key, value);
  }

  public void removeSSLProperty(String key) {
    this.agentConfig.removeSSLProperty(key);
  }

  // -------------------------------------------------------------------------
  // ManagedResource implementation
  // -------------------------------------------------------------------------

  @Override
  public String getMBeanName() {
    return this.mbeanName;
  }

  @Override
  public ModelMBean getModelMBean() {
    return this.modelMBean;
  }

  @Override
  public void setModelMBean(ModelMBean modelMBean) {
    this.modelMBean = modelMBean;
  }

  @Override
  public ObjectName getObjectName() {
    return this.objectName;
  }

  @Override
  public ManagedResourceType getManagedResourceType() {
    return ManagedResourceType.AGENT;
  }

  @Override
  public void cleanupResource() {}

  @Override
  public LogConfig getLogConfig() {
    return agentConfig.createLogConfig();
  }

  @Override
  public StatisticsConfig getStatisticsConfig() {
    return agentConfig.createStatisticsConfig();
  }

  @Override
  public void addLogConfigListener(LogConfigListener logConfigListener) {
    logConfigListeners.add(logConfigListener);
  }

  @Override
  public void removeLogConfigListener(LogConfigListener logConfigListener) {
    logConfigListeners.remove(logConfigListener);
  }

  void logConfigChanged() {
    for (LogConfigListener listener : logConfigListeners) {
      listener.configChanged();
    }
  }

  static class StartupException extends GemFireException {
    private static final long serialVersionUID = 6614145962199330348L;

    StartupException(Throwable cause) {
      super(cause);
    }

    StartupException(String reason, Throwable cause) {
      super(reason, cause);
    }
  }

  // -------------------------------------------------------------------------
  // Other Support methods
  // -------------------------------------------------------------------------
  /**
   * Checks the no. of active RMI clients and updates a flag in the Admin Distributed System.
   *
   * @see AdminDistributedSystemJmxImpl#setRmiClientCountZero(boolean)
   * @since GemFire 6.0
   */
  void updateRmiClientsCount() {
    int noOfClientsConnected = 0;

    String[] connectionIds = this.rmiConnector.getConnectionIds();

    if (connectionIds != null) {
      noOfClientsConnected = connectionIds.length;
    }

    logger.info("No. of RMI clients connected :: {}", noOfClientsConnected);

    AdminDistributedSystemJmxImpl adminDSJmx = (AdminDistributedSystemJmxImpl) this.system;

    adminDSJmx.setRmiClientCountZero(noOfClientsConnected == 0);
  }

  @Override
  public String toString() {
    StringBuffer sb = new StringBuffer();
    sb.append("AgentImpl[");
    sb.append("config=" + agentConfig.toProperties().toString());
    sb.append("; mbeanName=" + mbeanName);
    sb.append("; modelMBean=" + modelMBean);
    sb.append("; objectName=" + objectName);
    sb.append("; propertyFile=" + propertyFile);
    sb.append(": rmiConnector=" + rmiConnector);
    sb.append("]");
    return sb.toString();
  }

  /**
   * Process the String form of a hostname to make it comply with Jmx URL restrictions. Namely wrap
   * IPv6 literal address with "[", "]"
   *
   * @param hostname the name to safeguard.
   * @return a string representation suitable for use in a Jmx connection URL
   */
  private static String applyRFC2732(String hostname) {
    if (hostname.indexOf(":") != -1) {
      // Assuming an IPv6 literal because of the ':'
      return "[" + hostname + "]";
    }
    return hostname;
  }
}


/**
 * Adapter class for NotificationListener that listens to notifications of type
 * javax.management.remote.JMXConnectionNotification
 *
 * @since GemFire 6.0
 */
class ConnectionNotificationAdapter implements NotificationListener {
  private static final Logger logger = LogService.getLogger();

  /**
   * If the handback object passed is an AgentImpl, updates the JMX client count
   *
   * @param notification JMXConnectionNotification for change in client connection status
   * @param handback An opaque object which helps the listener to associate information regarding
   *        the MBean emitter. This object is passed to the MBean during the addListener call and
   *        resent, without modification, to the listener. The MBean object should not use or modify
   *        the object. (NOTE: copied from javax.management.NotificationListener)
   */
  @Override
  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "BC_UNCONFIRMED_CAST",
      justification = "Only JMXConnectionNotification instances are used.")
  public void handleNotification(Notification notification, Object handback) {
    if (handback instanceof AgentImpl) {
      AgentImpl agent = (AgentImpl) handback;

      JMXConnectionNotification jmxNotifn = (JMXConnectionNotification) notification;

      if (logger.isDebugEnabled()) {
        logger.debug("Connection notification for connection id : '{}'",
            jmxNotifn.getConnectionId());
      }

      agent.updateRmiClientsCount();
    }
  }
}


/**
 * Filters out the notifications of the type JMXConnectionNotification.OPENED,
 * JMXConnectionNotification.CLOSED and JMXConnectionNotification.FAILED.
 *
 * @since GemFire 6.0
 */
class ConnectionNotificationFilterImpl implements NotificationFilter {

  /**
   * Default serialVersionUID
   */
  private static final long serialVersionUID = 1L;

  /**
   * Invoked before sending the specified notification to the listener. Returns whether the given
   * notification is to be sent to the listener.
   *
   * @param notification The notification to be sent.
   * @return true if the notification has to be sent to the listener, false otherwise.
   */
  @Override
  public boolean isNotificationEnabled(Notification notification) {
    boolean isThisNotificationEnabled = false;
    if (notification.getType().equals(JMXConnectionNotification.OPENED)
        || notification.getType().equals(JMXConnectionNotification.CLOSED)
        || notification.getType().equals(JMXConnectionNotification.FAILED)) {
      isThisNotificationEnabled = true;
    }
    return isThisNotificationEnabled;
  }
}
