mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

neil_a_wilson
13.55.2006 fa6e5bb0c17c4d59d8598979feb1a7701bc32679
Publish a separate monitor entry for each connection handler, which includes
the protocol, listen address/port, number of established connections, and
information about each connection.

Also, update the monitor API to make it possible to include a custom
objectclass in each monitor entry. Connection handler monitor entries now
include the ds-connectionhandler-monitor-entry objectclass. Backend monitor
entries now include the ds-backend-monitor-entry objectclass.

OpenDS Issue Numbers: 1066 and 1091
2 files added
14 files modified
998 ■■■■■ changed files
opends/resource/schema/02-config.ldif 23 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/ClientConnection.java 57 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/ConnectionHandler.java 78 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/MonitorProvider.java 24 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/backends/MonitorBackend.java 24 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/DirectoryServer.java 16 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/monitors/BackendMonitor.java 17 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/monitors/ConnectionHandlerMonitor.java 247 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java 22 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/internal/InternalConnectionHandler.java 45 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java 39 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java 71 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java 69 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java 70 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/types/HostPort.java 143 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/ServerConstants.java 53 ●●●●● patch | view | raw | blame | history
opends/resource/schema/02-config.ldif
@@ -1009,6 +1009,18 @@
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.295 NAME 'ds-backend-writability-mode'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.296 NAME
  'ds-connectionhandler-connection' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.297 NAME
  'ds-connectionhandler-listener' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.298 NAME
  'ds-connectionhandler-num-connections' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.299 NAME
  'ds-connectionhandler-protocol' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
  NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL
  MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled )
@@ -1067,7 +1079,7 @@
objectClasses: ( 1.3.6.1.4.1.26027.1.2.13
  NAME 'ds-cfg-connection-handler' SUP top STRUCTURAL
  MUST ( cn $ ds-cfg-connection-handler-class $
  ds-cfg-connection-handler-enabled ) MAY ( ds-cfg-allowed-client $
  ds-cfg-connection-handler-enabled ) MAY ( ds-cfg-allowed-client $
  ds-cfg-denied-client ) X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.14
  NAME 'ds-cfg-ldap-connection-handler' SUP ds-cfg-connection-handler
@@ -1380,4 +1392,13 @@
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.77 NAME 'ds-monitor-entry' SUP top
  STRUCTURAL MUST cn X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.78 NAME 'ds-backend-monitor-entry'
  SUP ds-monitor-entry STRUCTURAL MAY ( ds-backend-id $ ds-backend-base-dn $
  ds-backend-entry-count $ ds-backend-writability-mode )
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.79 NAME
  'ds-connectionhandler-monitor-entry' SUP ds-monitor-entry STRUCTURAL
  MAY ( ds-connectionhandler-connection $ ds-connectionhandler-listener $
  ds-connectionhandler-num-connections $ ds-connectionhandler-protocol )
  X-ORIGIN 'OpenDS Directory Server' )
opends/src/server/org/opends/server/api/ClientConnection.java
@@ -46,6 +46,7 @@
import org.opends.server.types.IntermediateResponse;
import org.opends.server.types.SearchResultEntry;
import org.opends.server.types.SearchResultReference;
import org.opends.server.util.TimeThread;
import static org.opends.server.loggers.Debug.*;
import static org.opends.server.messages.MessageHandler.*;
@@ -83,10 +84,17 @@
  // The lookthrough limit for use with this client connection.
  private int lookthroughLimit;
  // The time that this client connection was established.
  private long connectTime;
  // The opaque information used for storing intermediate state
  // information needed across multi-stage SASL binds.
  private Object saslAuthState;
  // A string representation of the time that this client connection
  // was established.
  private String connectTimeString;
  // A set of persistent searches registered for this client.
  private CopyOnWriteArrayList<PersistentSearch> persistentSearches;
@@ -100,6 +108,8 @@
  {
    assert debugConstructor(CLASS_NAME);
    connectTime        = TimeThread.getTime();
    connectTimeString  = TimeThread.getUTCTime();
    authenticationInfo = new AuthenticationInfo();
    saslAuthState      = null;
    bindInProgress     = false;
@@ -112,6 +122,38 @@
  /**
   * Retrieves the time that this connection was established, measured
   * in the number of milliseconds since January 1, 1970 UTC.
   *
   * @return  The time that this connection was established, measured
   *          in the number of milliseconds since January 1, 1970 UTC.
   */
  public long getConnectTime()
  {
    assert debugEnter(CLASS_NAME, "getConnectTime");
    return connectTime;
  }
  /**
   * Retrieves a string representation of the time that this
   * connection was established.
   *
   * @return  A string representation of the time that this connection
   *          was established.
   */
  public String getConnectTimeString()
  {
    assert debugEnter(CLASS_NAME, "getConnectTimeString");
    return connectTimeString;
  }
  /**
   * Retrieves the unique identifier that has been assigned to this
   * connection.
   *
@@ -852,6 +894,21 @@
  /**
   * Retrieves a one-line summary of this client connection in a form
   * that is suitable for including in the monitor entry for the
   * associated connection handler.  It should be in a format that is
   * both humand readable and machine parseable (e.g., a
   * space-delimited name-value list, with quotes around the values).
   *
   * @return  A one-line summary of this client connection in a form
   *          that is suitable for including in the monitor entry for
   *          the associated connection handler.
   */
  public abstract String getMonitorSummary();
  /**
   * Retrieves a string representation of this client connection.
   *
   * @return  A string representation of this client connection.
opends/src/server/org/opends/server/api/ConnectionHandler.java
@@ -31,6 +31,8 @@
import java.util.Collection;
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.monitors.ConnectionHandlerMonitor;
import org.opends.server.types.HostPort;
import org.opends.server.types.InitializationException;
import static org.opends.server.loggers.Debug.*;
@@ -52,6 +54,11 @@
  // The monitor associated with this connection handler.
  private ConnectionHandlerMonitor monitor;
  /**
   * Creates a new instance of this connection handler.  This must be
   * called by all connection handlers, and all connection handlers
@@ -65,6 +72,7 @@
    super(threadName);
    assert debugConstructor(CLASS_NAME, String.valueOf(threadName));
    monitor = null;
  }
@@ -114,6 +122,44 @@
  /**
   * Retrieves a name that may be used to refer to this connection
   * handler.  Every connection handler instance (even handlers of the
   * same type) must have a unique name.
   *
   * @return  A unique name that may be used to refer to this
   *          connection handler.
   */
  public abstract String getConnectionHandlerName();
  /**
   * Retrieves the name of the protocol used to communicate with
   * clients.  It should take into account any special naming that may
   * be needed to express any security mechanisms or other constraints
   * in place (e.g., "LDAPS" for LDAP over SSL).
   *
   * @return  The name of the protocol used to communicate with
   *          clients.
   */
  public abstract String getProtocol();
  /**
   * Retrieves information about the listener(s) that will be used to
   * accept client connections.
   *
   * @return  Information about the listener(s) that will be used to
   *          accept client connections, or an empty list if this
   *          connection handler does not accept connections from
   *          network clients.
   */
  public abstract Collection<HostPort> getListeners();
  /**
   * Retrieves the set of active client connections that have been
   * established through this connection handler.
   *
@@ -133,6 +179,38 @@
  /**
   * Retrieves the monitor instance for this connection handler.
   *
   * @return  The monitor instance for this connection handler, or
   *          {@code null} if none has been provided.
   */
  public ConnectionHandlerMonitor getConnectionHandlerMonitor()
  {
    assert debugEnter(CLASS_NAME, "getConnectionHandlerMonitor");
    return monitor;
  }
  /**
   * Sets the monitor instance for this connection handler.
   *
   * @param  monitor  The monitor instance for this connection
   *                  handler.
   */
  public void setConnectionHandlerMonitor(
                   ConnectionHandlerMonitor monitor)
  {
    assert debugEnter(CLASS_NAME, "setConnectionHandlerMonitor",
                      String.valueOf(monitor));
    this.monitor = monitor;
  }
  /**
   * Retrieves a string representation of this connection handler.
   *
   * @return  A string representation of this connection handler.
opends/src/server/org/opends/server/api/MonitorProvider.java
@@ -33,9 +33,12 @@
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.types.Attribute;
import org.opends.server.types.DirectoryConfig;
import org.opends.server.types.InitializationException;
import org.opends.server.types.ObjectClass;
import static org.opends.server.loggers.Debug.*;
import static org.opends.server.util.ServerConstants.*;
@@ -149,6 +152,27 @@
  /**
   * Retrieves the objectclass that should be included in the monitor
   * entry created from this monitor provider.  This may be overridden
   * by subclasses that wish to include their own custom objectclass
   * in the monitor entry (e.g., to make it easier to search for
   * monitor entries of that type).  The default implementation
   * returns the "extensibleObject" objectclass.
   *
   * @return  The objectclass that should be included in the monitor
   *          entry created from this monitor provider.
   */
  public ObjectClass getMonitorObjectClass()
  {
    assert debugEnter(CLASS_NAME, "getMonitorObjectClass");
    return DirectoryConfig.getObjectClass(OC_EXTENSIBLE_OBJECT_LC,
                                          true);
  }
  /**
   * Retrieves the length of time in milliseconds that should elapse
   * between calls to the <CODE>updateMonitorData()</CODE> method.  A
   * negative or zero return value indicates that the
opends/src/server/org/opends/server/backends/MonitorBackend.java
@@ -222,7 +222,7 @@
    // Construct the set of objectclasses to include in the base monitor entry.
    monitorObjectClasses = new LinkedHashMap<ObjectClass,String>(3);
    monitorObjectClasses = new LinkedHashMap<ObjectClass,String>(2);
    ObjectClass topOC = DirectoryServer.getObjectClass(OC_TOP, true);
    monitorObjectClasses.put(topOC, OC_TOP);
@@ -230,10 +230,6 @@
                                                           true);
    monitorObjectClasses.put(monitorOC, OC_MONITOR_ENTRY);
    ObjectClass extensibleObjectOC =
         DirectoryServer.getObjectClass(OC_EXTENSIBLE_OBJECT_LC, true);
    monitorObjectClasses.put(extensibleObjectOC, OC_EXTENSIBLE_OBJECT);
    // Define an empty sets for the supported controls and features.
    supportedControls = new HashSet<String>(0);
@@ -509,6 +505,13 @@
    assert debugEnter(CLASS_NAME, "getBaseMonitorEntry");
    HashMap<ObjectClass,String> monitorClasses =
         new LinkedHashMap<ObjectClass,String>(3);
    monitorClasses.putAll(monitorObjectClasses);
    ObjectClass extensibleObjectOC =
         DirectoryServer.getObjectClass(OC_EXTENSIBLE_OBJECT_LC, true);
    monitorClasses.put(extensibleObjectOC, OC_EXTENSIBLE_OBJECT);
    HashMap<AttributeType,List<Attribute>> monitorUserAttrs =
         new LinkedHashMap<AttributeType,List<Attribute>>();
@@ -655,7 +658,7 @@
    // Construct and return the entry.
    return new Entry(baseMonitorDN, monitorObjectClasses, monitorUserAttrs,
    return new Entry(baseMonitorDN, monitorClasses, monitorUserAttrs,
                     monitorOperationalAttrs);
  }
@@ -677,6 +680,13 @@
    assert debugEnter(CLASS_NAME, "getMonitorEntry",
                      String.valueOf(monitorProvider));
    HashMap<ObjectClass,String> monitorClasses =
         new LinkedHashMap<ObjectClass,String>(3);
    monitorClasses.putAll(monitorObjectClasses);
    ObjectClass monitorOC = monitorProvider.getMonitorObjectClass();
    monitorClasses.put(monitorOC, monitorOC.getPrimaryName());
    List<Attribute> monitorAttrs = monitorProvider.getMonitorData();
    HashMap<AttributeType,List<Attribute>> attrMap =
         new LinkedHashMap<AttributeType,List<Attribute>>(
@@ -717,7 +727,7 @@
      }
    }
    return new Entry(entryDN, monitorObjectClasses, attrMap,
    return new Entry(entryDN, monitorClasses, attrMap,
                     new HashMap<AttributeType,List<Attribute>>(0));
  }
opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -91,6 +91,7 @@
import org.opends.server.loggers.StartupDebugLogger;
import org.opends.server.loggers.StartupErrorLogger;
import org.opends.server.monitors.BackendMonitor;
import org.opends.server.monitors.ConnectionHandlerMonitor;
import org.opends.server.schema.AttributeTypeSyntax;
import org.opends.server.schema.BinarySyntax;
import org.opends.server.schema.BooleanEqualityMatchingRule;
@@ -5340,6 +5341,7 @@
        String instanceName = toLowerCase(monitor.getMonitorInstanceName());
        deregisterMonitorProvider(instanceName);
        monitor.finalizeMonitorProvider();
        backend.setBackendMonitor(null);
      }
    }
  }
@@ -6444,6 +6446,11 @@
    synchronized (directoryServer.connectionHandlers)
    {
      directoryServer.connectionHandlers.add(handler);
      ConnectionHandlerMonitor monitor = new ConnectionHandlerMonitor(handler);
      monitor.initializeMonitorProvider(null);
      handler.setConnectionHandlerMonitor(monitor);
      registerMonitorProvider(monitor);
    }
  }
@@ -6463,6 +6470,15 @@
    synchronized (directoryServer.connectionHandlers)
    {
      directoryServer.connectionHandlers.remove(handler);
      ConnectionHandlerMonitor monitor = handler.getConnectionHandlerMonitor();
      if (monitor != null)
      {
        String instanceName = toLowerCase(monitor.getMonitorInstanceName());
        deregisterMonitorProvider(instanceName);
        monitor.finalizeMonitorProvider();
        handler.setConnectionHandlerMonitor(null);
      }
    }
  }
opends/src/server/org/opends/server/monitors/BackendMonitor.java
@@ -41,6 +41,7 @@
import org.opends.server.types.ByteStringFactory;
import org.opends.server.types.DirectoryConfig;
import org.opends.server.types.DN;
import org.opends.server.types.ObjectClass;
import static org.opends.server.loggers.Debug.*;
import static org.opends.server.util.ServerConstants.*;
@@ -141,6 +142,22 @@
  /**
   * Retrieves the objectclass that should be included in the monitor entry
   * created from this monitor provider.
   *
   * @return  The objectclass that should be included in the monitor entry
   *          created from this monitor provider.
   */
  public ObjectClass getMonitorObjectClass()
  {
    assert debugEnter(CLASS_NAME, "getMonitorObjectClass");
    return DirectoryConfig.getObjectClass(OC_MONITOR_BACKEND, true);
  }
  /**
   * {@inheritDoc}
   */
  public long getUpdateInterval()
opends/src/server/org/opends/server/monitors/ConnectionHandlerMonitor.java
New file
@@ -0,0 +1,247 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying * information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 */
package org.opends.server.monitors;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.ConnectionHandler;
import org.opends.server.api.MonitorProvider;
import org.opends.server.config.ConfigEntry;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
import org.opends.server.types.ByteStringFactory;
import org.opends.server.types.DirectoryConfig;
import org.opends.server.types.HostPort;
import org.opends.server.types.ObjectClass;
import static org.opends.server.loggers.Debug.*;
import static org.opends.server.util.ServerConstants.*;
/**
 * This class implements a monitor provider that will report generic information
 * for an enabled Directory Server connection handler, including its protocol,
 * listeners, and established connections.
 */
public class ConnectionHandlerMonitor
       extends MonitorProvider
{
  /**
   * The fully-qualified name of this class for debugging purposes.
   */
  private static final String CLASS_NAME =
       "org.opends.server.monitors.ConnectionHandlerMonitor";
  // The attribute type that will be used to report the established connections.
  private AttributeType connectionsType;
  // The attribute type that will be used to report the listeners.
  private AttributeType listenerType;
  // The attribute type that will be used to report the number of established
  // client connections.
  private AttributeType numConnectionsType;
  // The attribute type that will be used to report the protocol.
  private AttributeType protocolType;
  // The connection handler with which this monitor is associated.
  private ConnectionHandler connectionHandler;
  // The name for this monitor.
  private String monitorName;
  /**
   * Creates a new instance of this connection handler monitor provider that
   * will work with the provided connection handler.  Most of the initialization
   * should be handled in the {@code initializeMonitorProvider} method.
   *
   * @param  connectionHandler  The connection handler with which this monitor
   *                            is associated.
   */
  public ConnectionHandlerMonitor(ConnectionHandler connectionHandler)
  {
    super(connectionHandler.getConnectionHandlerName());
    assert debugConstructor(CLASS_NAME, String.valueOf(connectionHandler));
    this.connectionHandler = connectionHandler;
  }
  /**
   * {@inheritDoc}
   */
  public void initializeMonitorProvider(ConfigEntry configEntry)
  {
    assert debugEnter(CLASS_NAME, "initializeMonitorProvider",
                      String.valueOf(configEntry));
    monitorName = connectionHandler.getConnectionHandlerName();
    connectionsType =
         DirectoryConfig.getAttributeType(ATTR_MONITOR_CONNHANDLER_CONNECTION,
                                          true);
    listenerType =
         DirectoryConfig.getAttributeType(ATTR_MONITOR_CONNHANDLER_LISTENER,
                                          true);
    numConnectionsType =
         DirectoryConfig.getAttributeType(
              ATTR_MONITOR_CONNHANDLER_NUMCONNECTIONS, true);
    protocolType =
         DirectoryConfig.getAttributeType(ATTR_MONITOR_CONNHANDLER_PROTOCOL,
                                          true);
  }
  /**
   * {@inheritDoc}
   */
  public String getMonitorInstanceName()
  {
    assert debugEnter(CLASS_NAME, "getMonitorInstanceName");
    return monitorName;
  }
  /**
   * Retrieves the objectclass that should be included in the monitor entry
   * created from this monitor provider.
   *
   * @return  The objectclass that should be included in the monitor entry
   *          created from this monitor provider.
   */
  public ObjectClass getMonitorObjectClass()
  {
    assert debugEnter(CLASS_NAME, "getMonitorObjectClass");
    return DirectoryConfig.getObjectClass(OC_MONITOR_CONNHANDLER, true);
  }
  /**
   * {@inheritDoc}
   */
  public long getUpdateInterval()
  {
    assert debugEnter(CLASS_NAME, "getUpdateInterval");
    // We don't need do anything on a periodic basis.
    return 0;
  }
  /**
   * {@inheritDoc}
   */
  public void updateMonitorData()
  {
    assert debugEnter(CLASS_NAME, "updateMonitorData");
    // No implementaiton is required.
  }
  /**
   * {@inheritDoc}
   */
  public List<Attribute> getMonitorData()
  {
    assert debugEnter(CLASS_NAME, "getMonitorData");
    LinkedList<Attribute> attrs = new LinkedList<Attribute>();
    int numConnections = 0;
    LinkedList<ClientConnection> conns =
         new LinkedList<ClientConnection>(
                  connectionHandler.getClientConnections());
    LinkedList<HostPort> listeners =
         new LinkedList<HostPort>(connectionHandler.getListeners());
    LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>();
    values.add(new AttributeValue(protocolType,
         ByteStringFactory.create(connectionHandler.getProtocol())));
    attrs.add(new Attribute(protocolType, ATTR_MONITOR_CONNHANDLER_PROTOCOL,
                            values));
    if (! listeners.isEmpty())
    {
      values = new LinkedHashSet<AttributeValue>();
      for (HostPort hp : listeners)
      {
        values.add(new AttributeValue(listenerType,
                                      ByteStringFactory.create(hp.toString())));
      }
      attrs.add(new Attribute(listenerType, ATTR_MONITOR_CONNHANDLER_LISTENER,
                              values));
    }
    if (! conns.isEmpty())
    {
      values = new LinkedHashSet<AttributeValue>();
      for (ClientConnection c : conns)
      {
        numConnections++;
        values.add(new AttributeValue(connectionsType,
             ByteStringFactory.create(c.getMonitorSummary())));
      }
      attrs.add(new Attribute(connectionsType,
                              ATTR_MONITOR_CONNHANDLER_CONNECTION, values));
    }
    values = new LinkedHashSet<AttributeValue>();
    values.add(new AttributeValue(numConnectionsType,
         ByteStringFactory.create(String.valueOf(numConnections))));
    attrs.add(new Attribute(numConnectionsType,
                            ATTR_MONITOR_CONNHANDLER_NUMCONNECTIONS, values));
    return attrs;
  }
}
opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
@@ -1701,6 +1701,25 @@
  /**
   * {@inheritDoc}
   */
  public String getMonitorSummary()
  {
    assert debugEnter(CLASS_NAME, "getMonitorSummary");
    StringBuilder buffer = new StringBuilder();
    buffer.append("connID=\"");
    buffer.append(connectionID);
    buffer.append("\" authDN=\"");
    buffer.append(getAuthenticationInfo().getAuthenticationDN());
    buffer.append("\"");
    return buffer.toString();
  }
  /**
   * Appends a string representation of this client connection to the
   * provided buffer.
   *
@@ -1709,6 +1728,9 @@
   */
  public void toString(StringBuilder buffer)
  {
    assert debugEnter(CLASS_NAME, "toString",
                      "java.lang.StringBuilder");
    buffer.append("InternalClientConnection(connID=");
    buffer.append(connectionID);
    buffer.append(", authDN=\"");
opends/src/server/org/opends/server/protocols/internal/InternalConnectionHandler.java
@@ -36,6 +36,7 @@
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.types.InitializationException;
import org.opends.server.types.HostPort;
import static org.opends.server.loggers.Debug.*;
@@ -65,6 +66,12 @@
  // handler.
  private LinkedList<ClientConnection> connectionList;
  // The list of listeners associated with this connection handler.
  private LinkedList<HostPort> listeners;
  // The name of the protocol for this connection handler.
  private String protocol;
  /**
@@ -81,7 +88,9 @@
    // Since we can't guarantee that the initializeConnectionHandler
    // method will always be called for this method, we'll do the
    // necessary "initialization" here.
    protocol       = "internal";
    connectionList = new LinkedList<ClientConnection>();
    listeners      = new LinkedList<HostPort>();
  }
@@ -154,6 +163,42 @@
  /**
   * {@inheritDoc}
   */
  public String getConnectionHandlerName()
  {
    assert debugEnter(CLASS_NAME, "getConnectionHandlerName");
    return "Internal Connection Handler";
  }
  /**
   * {@inheritDoc}
   */
  public String getProtocol()
  {
    assert debugEnter(CLASS_NAME, "getProtocol");
    return protocol;
  }
  /**
   * {@inheritDoc}
   */
  public Collection<HostPort> getListeners()
  {
    assert debugEnter(CLASS_NAME, "getProtocol");
    return listeners;
  }
  /**
   * Retrieves the set of active client connections that have been
   * established through this connection handler.
   *
opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
@@ -1084,6 +1084,45 @@
  /**
   * {@inheritDoc}
   */
  public String getMonitorSummary()
  {
    assert debugEnter(CLASS_NAME, "getMonitorSummary");
    StringBuilder buffer = new StringBuilder();
    buffer.append("connID=\"");
    buffer.append(connectionID);
    buffer.append("\" connectTime=\"");
    buffer.append(getConnectTimeString());
    buffer.append("\" jmxConnID=\"");
    buffer.append(jmxConnectionID);
    buffer.append("\" authDN=\"");
    DN authDN = getAuthenticationInfo().getAuthenticationDN();
    if (authDN != null)
    {
      authDN.toString(buffer);
    }
    buffer.append("\" security=\"");
    if (securityProvider.isSecure())
    {
      buffer.append(securityProvider.getSecurityMechanismName());
    }
    else
    {
      buffer.append("none");
    }
    buffer.append("\"");
    return buffer.toString();
  }
  /**
   * Appends a string representation of this client connection to the provided
   * buffer.
   *
opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java
@@ -61,6 +61,7 @@
import org.opends.server.types.DN;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
import org.opends.server.types.HostPort;
import org.opends.server.types.InitializationException;
import org.opends.server.types.ResultCode;
@@ -170,6 +171,21 @@
    new LinkedList<ConfigAttribute>();
  /**
   * The unique name for this connection handler.
   */
  protected String connectionHandlerName;
  /**
   * The protocol used to communicate with clients.
   */
  protected String protocol;
  /**
   * The set of listeners for this connection handler.
   */
  protected LinkedList<HostPort> listeners = new LinkedList<HostPort>();
  /**
   * The list of active client connection.
   */
  protected LinkedList<ClientConnection> connectionList =
@@ -493,6 +509,19 @@
      String message = getMessage(msgID, String.valueOf(configEntryDN), "");
      throw new InitializationException(msgID, message);
    }
    if (useSSL)
    {
      protocol = "JMX+SSL";
    }
    else
    {
      protocol = "JMX";
    }
    listeners.clear();
    listeners.add(new HostPort("0.0.0.0", listenPort));
    connectionHandlerName = "JMX Connection Handler "+ listenPort;
  }
  /**
@@ -518,6 +547,36 @@
  }
  /**
   * {@inheritDoc}
   */
  public String getConnectionHandlerName()
  {
    assert debugEnter(CLASS_NAME, "getConnectionHandlerName");
    return connectionHandlerName;
  }
  /**
   * {@inheritDoc}
   */
  public String getProtocol()
  {
    assert debugEnter(CLASS_NAME, "getProtocol");
    return protocol;
  }
  /**
   * {@inheritDoc}
   */
  public Collection<HostPort> getListeners()
  {
    assert debugEnter(CLASS_NAME, "getListeners");
    return listeners;
  }
  /**
   * Retrieves the set of active client connections that have been
   * established through this connection handler.
   *
@@ -842,6 +901,18 @@
      }
    }
    if (useSSL)
    {
      protocol = "JMX+SSL";
    }
    else
    {
      protocol = "JMX";
    }
    listeners.clear();
    listeners.add(new HostPort(listenPort));
    //
    // Start the new RMI Connector
    rmiConnector.initialize();
opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -188,6 +188,10 @@
  // The string representation of the address of the client.
  private String clientAddress;
  // The name of the protocol that the client is using to communicate with the
  // server.
  private String protocol;
  // The string representation of the address of the server to which the client
  // has connected.
  private String serverAddress;
@@ -237,6 +241,7 @@
    disconnectRequested  = false;
    operationsInProgress = new ConcurrentHashMap<Integer,Operation>();
    keepStats            = connectionHandler.keepStats();
    protocol             = "LDAP";
    clientAddress = clientChannel.socket().getInetAddress().getHostAddress();
    clientPort    = clientChannel.socket().getPort();
@@ -351,9 +356,7 @@
  {
    assert debugEnter(CLASS_NAME, "getProtocol");
    // FIXME -- what if it is a secure connection?  And what if it is secure now
    // but wasn't when it was established?
    return "LDAP";
    return protocol;
  }
@@ -522,6 +525,15 @@
                      String.valueOf(securityProvider));
    this.securityProvider = securityProvider;
    if (securityProvider.isSecure())
    {
      protocol = "LDAP+" + securityProvider.getSecurityMechanismName();
    }
    else
    {
      protocol = "LDAP";
    }
  }
@@ -2355,6 +2367,55 @@
  /**
   * {@inheritDoc}
   */
  public String getMonitorSummary()
  {
    assert debugEnter(CLASS_NAME, "getMonitorSummary");
    StringBuilder buffer = new StringBuilder();
    buffer.append("connID=\"");
    buffer.append(connectionID);
    buffer.append("\" connectTime=\"");
    buffer.append(getConnectTimeString());
    buffer.append("\" source=\"");
    buffer.append(clientAddress);
    buffer.append(":");
    buffer.append(clientPort);
    buffer.append("\" destination=\"");
    buffer.append(serverAddress);
    buffer.append(":");
    buffer.append(connectionHandler.getListenPort());
    buffer.append("\" ldapVersion=\"");
    buffer.append(ldapVersion);
    buffer.append("\" authDN=\"");
    DN authDN = getAuthenticationInfo().getAuthenticationDN();
    if (authDN != null)
    {
      authDN.toString(buffer);
    }
    buffer.append("\" security=\"");
    if (securityProvider.isSecure())
    {
      buffer.append(securityProvider.getSecurityMechanismName());
    }
    else
    {
      buffer.append("none");
    }
    buffer.append("\" opsInProgress=\"");
    buffer.append(operationsInProgress.size());
    buffer.append("\"");
    return buffer.toString();
  }
  /**
   * Appends a string representation of this client connection to the provided
   * buffer.
   *
@@ -2480,7 +2541,7 @@
    }
    clearSecurityProvider = securityProvider;
    securityProvider      = tlsSecurityProvider;
    setConnectionSecurityProvider(tlsSecurityProvider);
  }
opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
@@ -69,6 +69,7 @@
import org.opends.server.types.DN;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
import org.opends.server.types.HostPort;
import org.opends.server.types.InitializationException;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SSLClientAuthPolicy;
@@ -206,6 +207,9 @@
  // accepted by the server.
  private int requestHandlerIndex;
  // The set of listeners for this connection handler.
  private LinkedList<HostPort> listeners;
  // The set of request handlers that are associated with this connection
  // handler.
  private LDAPRequestHandler[] requestHandlers;
@@ -223,6 +227,9 @@
  // The unique name assigned to this connection handler.
  private String handlerName;
  // The protocol used by this connection handler.
  private String protocol;
  // The security mechanism used for connections accepted by this connection
  // handler.
  private String securityMechanism;
@@ -996,11 +1003,14 @@
    }
    // Construct a unique name for this connection handler.
    // Construct a unique name for this connection handler, and put together the
    // set of listeners.
    listeners = new LinkedList<HostPort>();
    StringBuilder nameBuffer = new StringBuilder();
    nameBuffer.append("LDAP Connection Handler");
    for (InetAddress a : listenAddresses)
    {
      listeners.add(new HostPort(a.getHostAddress(), listenPort));
      nameBuffer.append(" ");
      nameBuffer.append(a.getHostAddress());
    }
@@ -1013,16 +1023,18 @@
    if (useSSL)
    {
      securityMechanism = SECURITY_MECHANISM_SSL;
      protocol          = "LDAP+SSL";
    }
    else
    {
      securityMechanism = null;
      protocol          = "LDAP";
    }
    // Perform any additional initialization that might be required.
    connHandlerThread = null;
    statTracker = new LDAPStatistics(handlerName);
    statTracker = new LDAPStatistics(handlerName + " Statistics");
    // Create and start the request handlers.
@@ -1091,6 +1103,42 @@
  /**
   * {@inheritDoc}
   */
  public String getConnectionHandlerName()
  {
    assert debugEnter(CLASS_NAME, "getConnectionHandlerName");
    return handlerName;
  }
  /**
   * {@inheritDoc}
   */
  public String getProtocol()
  {
    assert debugEnter(CLASS_NAME, "getProtocol");
    return protocol;
  }
  /**
   * {@inheritDoc}
   */
  public Collection<HostPort> getListeners()
  {
    assert debugEnter(CLASS_NAME, "getProtocol");
    return listeners;
  }
  /**
   * Retrieves the set of active client connections that have been established
   * through this connection handler.
   *
@@ -1114,6 +1162,22 @@
  /**
   * Retrieves the port on which this connection handler is listening
   * for client connections.
   *
   * @return  The port on which this connection handler is listening
   *          for client connections.
   */
  public int getListenPort()
  {
    assert debugEnter(CLASS_NAME, "getListenPort");
    return listenPort;
  }
  /**
   * Operates in a loop, accepting new connections and ensuring that requests on
   * those connections are handled properly.
   */
@@ -3013,7 +3077,7 @@
        {
          if (statTracker == null)
          {
            statTracker = new LDAPStatistics(handlerName);
            statTracker = new LDAPStatistics(handlerName + " Statistics");
          }
          else
          {
opends/src/server/org/opends/server/types/HostPort.java
New file
@@ -0,0 +1,143 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying * information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 */
package org.opends.server.types;
import static org.opends.server.loggers.Debug.*;
/**
 * This class defines a data structure that combines an address and
 * port number, as may be used to accept a connection from or initiate
 * a connection to a remote system.
 */
public final class HostPort
{
  /**
   * The fully-qualified name of this class for debugging purposes.
   */
  private static final String CLASS_NAME =
       "org.opends.server.types.HostPort";
  // The host for this object.
  private String host;
  // The port for this object;
  private int port;
  /**
   * Creates a new {@code HostPort} object with the specified port
   * number but no host.
   *
   * @param  port  The port number for this {@code HostPort} object.
   */
  public HostPort(int port)
  {
    assert debugConstructor(CLASS_NAME, String.valueOf(port));
    this.host = null;
    this.port = port;
  }
  /**
   * Creates a new {@code HostPort} object with the specified port
   * number but no explicit host.
   *
   * @param  host  The host address or name for this {@code HostPort}
   *               object, or {@code null} if there is none.
   * @param  port  The port number for this {@code HostPort} object.
   */
  public HostPort(String host, int port)
  {
    assert debugConstructor(CLASS_NAME, String.valueOf(host),
                            String.valueOf(port));
    this.host = host;
    this.port = port;
  }
  /**
   * Retrieves the host for this {@code HostPort} object.
   *
   * @return  The host for this {@code HostPort} object, or
   *          {@code null} if none was provided.
   */
  public String getHost()
  {
    assert debugEnter(CLASS_NAME, "getHost");
    return host;
  }
  /**
   * Retrieves the port number for this {@code HostPort} object.
   *
   * @return  The port number for this {@code HostPort} object.
   */
  public int getPort()
  {
    assert debugEnter(CLASS_NAME, "getPort");
    return port;
  }
  /**
   * Retrieves a string representation of this {@code HostPort}
   * object.  It will be the host element (or nothing if no host was
   * given) followed by a colon and the port number.
   *
   * @return  A string representation of this {@code HostPort} object.
   */
  public String toString()
  {
    assert debugEnter(CLASS_NAME, "toString");
    if (host ==  null)
    {
      return ":" + port;
    }
    else
    {
      return host + ":" + port;
    }
  }
}
opends/src/server/org/opends/server/util/ServerConstants.java
@@ -218,6 +218,42 @@
  /**
   * The name of the monitor attribute that is used to hold the connection
   * handler connections.
   */
  public static final String ATTR_MONITOR_CONNHANDLER_CONNECTION =
       "ds-connectionhandler-connection";
  /**
   * The name of the monitor attribute that is used to hold the connection
   * handler listeners.
   */
  public static final String ATTR_MONITOR_CONNHANDLER_LISTENER =
       "ds-connectionhandler-listener";
  /**
   * The name of the monitor attribute that is used to hold the connection
   * handler number of established connections.
   */
  public static final String ATTR_MONITOR_CONNHANDLER_NUMCONNECTIONS =
       "ds-connectionhandler-num-connections";
  /**
   * The name of the monitor attribute that is used to hold the connection
   * handler protocol.
   */
  public static final String ATTR_MONITOR_CONNHANDLER_PROTOCOL =
       "ds-connectionhandler-protocol";
  /**
   * The name of the standard attribute that is used to specify the set of
   * public naming contexts (suffixes) for the Directory Server, formatted in
   * camel case.
@@ -569,6 +605,23 @@
  /**
   * The name of the custom objectclass that will be included in backend monitor
   * entries.
   */
  public static final String OC_MONITOR_BACKEND = "ds-backend-monitor-entry";
  /**
   * The name of the custom objectclass that will be included in connection
   * handler monitor entries.
   */
  public static final String OC_MONITOR_CONNHANDLER =
       "ds-connectionhandler-monitor-entry";
  /**
   * The name of the objectclass that will be used as the structural class for
   * monitor entries.
   */